summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2014-08-28 11:07:35 +0200
committerChanho Park <chanho61.park@samsung.com>2014-11-18 12:00:46 +0900
commita646017c2cf2eb8ff968c5362d26af5491d44f97 (patch)
tree1b669867de8263d77b7ee0996da82568785ed1d1 /drivers/gpu/drm
parent3819e4d918c2cffcf473153119f3fb113e2612c4 (diff)
downloadlinux-3.10-a646017c2cf2eb8ff968c5362d26af5491d44f97.tar.gz
linux-3.10-a646017c2cf2eb8ff968c5362d26af5491d44f97.tar.bz2
linux-3.10-a646017c2cf2eb8ff968c5362d26af5491d44f97.zip
drm/exynos/ipp: remove events during command cleaning
Events were removed only during stop command, as a result there were memory leaks if program prematurely exited. This patch fixes it. Change-Id: I763b05753eb6bebe7ac3dc74da76dd08b5972142 Signed-off-by: Andrzej Hajda <a.hajda@samsung.com> Reviewed-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c156
1 files changed, 78 insertions, 78 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 53262563265..734a99944eb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -668,6 +668,81 @@ static void ipp_clean_mem_nodes(struct drm_device *drm_dev,
mutex_unlock(&c_node->mem_lock);
}
+static void ipp_free_event(struct drm_pending_event *event)
+{
+ kfree(event);
+}
+
+static int ipp_get_event(struct drm_device *drm_dev,
+ struct drm_file *file,
+ struct drm_exynos_ipp_cmd_node *c_node,
+ struct drm_exynos_ipp_queue_buf *qbuf)
+{
+ struct drm_exynos_ipp_send_event *e;
+ unsigned long flags;
+
+ DRM_DEBUG_KMS("%s:ops_id[%d]buf_id[%d]\n", __func__,
+ qbuf->ops_id, qbuf->buf_id);
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e) {
+ spin_lock_irqsave(&drm_dev->event_lock, flags);
+ file->event_space += sizeof(e->event);
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+ return -ENOMEM;
+ }
+
+ /* make event */
+ e->event.base.type = DRM_EXYNOS_IPP_EVENT;
+ e->event.base.length = sizeof(e->event);
+ e->event.user_data = qbuf->user_data;
+ e->event.prop_id = qbuf->prop_id;
+ e->event.buf_id[EXYNOS_DRM_OPS_DST] = qbuf->buf_id;
+ e->base.event = &e->event.base;
+ e->base.file_priv = file;
+ e->base.destroy = ipp_free_event;
+ list_add_tail(&e->base.link, &c_node->event_list);
+
+ return 0;
+}
+
+static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
+ struct drm_exynos_ipp_queue_buf *qbuf)
+{
+ struct drm_exynos_ipp_send_event *e, *te;
+ int count = 0;
+
+ if (list_empty(&c_node->event_list)) {
+ DRM_DEBUG_KMS("%s:event_list is empty.\n", __func__);
+ return;
+ }
+
+ list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
+ DRM_DEBUG_KMS("%s:count[%d]e[0x%x]\n",
+ __func__, count++, (int)e);
+
+ /*
+ * quf == NULL condition means all event deletion.
+ * stop operations want to delete all event list.
+ * another case delete only same buf id.
+ */
+ if (!qbuf) {
+ /* delete list */
+ list_del(&e->base.link);
+ kfree(e);
+ }
+
+ /* compare buffer id */
+ if (qbuf && (qbuf->buf_id ==
+ e->event.buf_id[EXYNOS_DRM_OPS_DST])) {
+ /* delete list */
+ list_del(&e->base.link);
+ kfree(e);
+ return;
+ }
+ }
+}
+
static void ipp_clean_cmd_node(struct drm_device *drm_dev,
struct drm_exynos_ipp_cmd_node *c_node)
{
@@ -678,6 +753,9 @@ static void ipp_clean_cmd_node(struct drm_device *drm_dev,
cancel_work_sync(&c_node->stop_work->work);
cancel_work_sync(&c_node->event_work->work);
+ /* put event */
+ ipp_put_event(c_node, NULL);
+
for_each_ipp_ops(i)
ipp_clean_mem_nodes(drm_dev, c_node, i);
@@ -811,81 +889,6 @@ err_unlock:
return ret;
}
-static void ipp_free_event(struct drm_pending_event *event)
-{
- kfree(event);
-}
-
-static int ipp_get_event(struct drm_device *drm_dev,
- struct drm_file *file,
- struct drm_exynos_ipp_cmd_node *c_node,
- struct drm_exynos_ipp_queue_buf *qbuf)
-{
- struct drm_exynos_ipp_send_event *e;
- unsigned long flags;
-
- DRM_DEBUG_KMS("%s:ops_id[%d]buf_id[%d]\n", __func__,
- qbuf->ops_id, qbuf->buf_id);
-
- e = kzalloc(sizeof(*e), GFP_KERNEL);
- if (!e) {
- spin_lock_irqsave(&drm_dev->event_lock, flags);
- file->event_space += sizeof(e->event);
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
- return -ENOMEM;
- }
-
- /* make event */
- e->event.base.type = DRM_EXYNOS_IPP_EVENT;
- e->event.base.length = sizeof(e->event);
- e->event.user_data = qbuf->user_data;
- e->event.prop_id = qbuf->prop_id;
- e->event.buf_id[EXYNOS_DRM_OPS_DST] = qbuf->buf_id;
- e->base.event = &e->event.base;
- e->base.file_priv = file;
- e->base.destroy = ipp_free_event;
- list_add_tail(&e->base.link, &c_node->event_list);
-
- return 0;
-}
-
-static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
- struct drm_exynos_ipp_queue_buf *qbuf)
-{
- struct drm_exynos_ipp_send_event *e, *te;
- int count = 0;
-
- if (list_empty(&c_node->event_list)) {
- DRM_DEBUG_KMS("%s:event_list is empty.\n", __func__);
- return;
- }
-
- list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
- DRM_DEBUG_KMS("%s:count[%d]e[0x%x]\n",
- __func__, count++, (int)e);
-
- /*
- * quf == NULL condition means all event deletion.
- * stop operations want to delete all event list.
- * another case delete only same buf id.
- */
- if (!qbuf) {
- /* delete list */
- list_del(&e->base.link);
- kfree(e);
- }
-
- /* compare buffer id */
- if (qbuf && (qbuf->buf_id ==
- e->event.buf_id[EXYNOS_DRM_OPS_DST])) {
- /* delete list */
- list_del(&e->base.link);
- kfree(e);
- return;
- }
- }
-}
-
static void ipp_handle_cmd_work(struct device *dev,
struct exynos_drm_ippdrv *ippdrv,
struct drm_exynos_ipp_cmd_work *cmd_work,
@@ -1391,9 +1394,6 @@ static int ipp_stop_property(struct drm_device *drm_dev,
DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
- /* put event */
- ipp_put_event(c_node, NULL);
-
/* stop operations */
if (ippdrv->stop)
ippdrv->stop(ippdrv->dev, property->cmd);