diff options
author | Andrzej Hajda <a.hajda@samsung.com> | 2014-08-28 11:07:30 +0200 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-11-18 12:00:45 +0900 |
commit | 25d5f5d38eea0b04ee2ae1e217d36026d6fbbbff (patch) | |
tree | 7af23bcfc49d8368ea7dd43545557b715743b31d /drivers/gpu/drm | |
parent | c4e369289da7071e8bcd04835ab40fb1a0d0434e (diff) | |
download | linux-3.10-25d5f5d38eea0b04ee2ae1e217d36026d6fbbbff.tar.gz linux-3.10-25d5f5d38eea0b04ee2ae1e217d36026d6fbbbff.tar.bz2 linux-3.10-25d5f5d38eea0b04ee2ae1e217d36026d6fbbbff.zip |
drm/exynos/ipp: free partially allocated resources on error
In case of allocation errors some already allocated buffers
were not freed. The patch fixes it.
Change-Id: I23447928fb497ad33324fc2affa430bd2de98122
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.c | 70 |
1 files changed, 31 insertions, 39 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index e2e5dc52e98..8b311ef83cd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -682,6 +682,35 @@ err_unlock: return ret; } +static int ipp_put_mem_node(struct drm_device *drm_dev, + struct drm_exynos_ipp_cmd_node *c_node, + struct drm_exynos_ipp_mem_node *m_node) +{ + int i; + + DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); + + if (!m_node) { + DRM_ERROR("invalid dequeue node.\n"); + return -EFAULT; + } + + DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); + + /* put gem buffer */ + for_each_ipp_planar(i) { + unsigned long handle = m_node->buf_info.handles[i]; + if (handle) + exynos_drm_gem_put_dma_addr(drm_dev, handle, + c_node->filp); + } + + list_del(&m_node->list); + kfree(m_node); + + return 0; +} + static struct drm_exynos_ipp_mem_node *ipp_get_mem_node(struct drm_device *drm_dev, struct drm_file *file, @@ -707,6 +736,7 @@ static struct drm_exynos_ipp_mem_node m_node->ops_id = qbuf->ops_id; m_node->prop_id = qbuf->prop_id; m_node->buf_id = qbuf->buf_id; + INIT_LIST_HEAD(&m_node->list); DRM_DEBUG_KMS("%s:m_node[0x%x]ops_id[%d]\n", __func__, (int)m_node, qbuf->ops_id); @@ -750,50 +780,12 @@ static struct drm_exynos_ipp_mem_node return m_node; err_clear: - kfree(m_node); + ipp_put_mem_node(drm_dev, c_node, m_node); err_unlock: mutex_unlock(&c_node->mem_lock); return ERR_PTR(-EFAULT); } -static int ipp_put_mem_node(struct drm_device *drm_dev, - struct drm_exynos_ipp_cmd_node *c_node, - struct drm_exynos_ipp_mem_node *m_node) -{ - int i; - - DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)m_node); - - if (!m_node) { - DRM_ERROR("invalid dequeue node.\n"); - return -EFAULT; - } - - if (list_empty(&m_node->list)) { - DRM_ERROR("empty memory node.\n"); - return -ENOMEM; - } - - mutex_lock(&c_node->mem_lock); - - DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, m_node->ops_id); - - /* put gem buffer */ - for_each_ipp_planar(i) { - unsigned long handle = m_node->buf_info.handles[i]; - if (handle) - exynos_drm_gem_put_dma_addr(drm_dev, handle, - c_node->filp); - } - - /* delete list in queue */ - list_del(&m_node->list); - kfree(m_node); - - mutex_unlock(&c_node->mem_lock); - - return 0; -} static void ipp_free_event(struct drm_pending_event *event) { |