aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2014-08-28 05:07:30 -0400
committerInki Dae <daeinki@gmail.com>2014-09-19 11:56:11 -0400
commit6602ffb84949779fd5d27399ca5f608a409a2a83 (patch)
tree26c3d22b650cd8f3e965f4fca1420b3bcd4d8329
parent985c293d094ae640a25e0c0e78d161a3fcb95b5d (diff)
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. 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>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c67
1 files changed, 32 insertions, 35 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 060a198da771..ab7b74cd4daa 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -599,6 +599,35 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
599 return ret; 599 return ret;
600} 600}
601 601
602static int ipp_put_mem_node(struct drm_device *drm_dev,
603 struct drm_exynos_ipp_cmd_node *c_node,
604 struct drm_exynos_ipp_mem_node *m_node)
605{
606 int i;
607
608 DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
609
610 if (!m_node) {
611 DRM_ERROR("invalid dequeue node.\n");
612 return -EFAULT;
613 }
614
615 DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id);
616
617 /* put gem buffer */
618 for_each_ipp_planar(i) {
619 unsigned long handle = m_node->buf_info.handles[i];
620 if (handle)
621 exynos_drm_gem_put_dma_addr(drm_dev, handle,
622 c_node->filp);
623 }
624
625 list_del(&m_node->list);
626 kfree(m_node);
627
628 return 0;
629}
630
602static struct drm_exynos_ipp_mem_node 631static struct drm_exynos_ipp_mem_node
603 *ipp_get_mem_node(struct drm_device *drm_dev, 632 *ipp_get_mem_node(struct drm_device *drm_dev,
604 struct drm_file *file, 633 struct drm_file *file,
@@ -619,6 +648,7 @@ static struct drm_exynos_ipp_mem_node
619 m_node->ops_id = qbuf->ops_id; 648 m_node->ops_id = qbuf->ops_id;
620 m_node->prop_id = qbuf->prop_id; 649 m_node->prop_id = qbuf->prop_id;
621 m_node->buf_id = qbuf->buf_id; 650 m_node->buf_id = qbuf->buf_id;
651 INIT_LIST_HEAD(&m_node->list);
622 652
623 DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id); 653 DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id);
624 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id); 654 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id);
@@ -634,7 +664,8 @@ static struct drm_exynos_ipp_mem_node
634 qbuf->handle[i], file); 664 qbuf->handle[i], file);
635 if (IS_ERR(addr)) { 665 if (IS_ERR(addr)) {
636 DRM_ERROR("failed to get addr.\n"); 666 DRM_ERROR("failed to get addr.\n");
637 goto err_clear; 667 ipp_put_mem_node(drm_dev, c_node, m_node);
668 return ERR_PTR(-EFAULT);
638 } 669 }
639 670
640 buf_info->handles[i] = qbuf->handle[i]; 671 buf_info->handles[i] = qbuf->handle[i];
@@ -649,40 +680,6 @@ static struct drm_exynos_ipp_mem_node
649 mutex_unlock(&c_node->mem_lock); 680 mutex_unlock(&c_node->mem_lock);
650 681
651 return m_node; 682 return m_node;
652
653err_clear:
654 kfree(m_node);
655 return ERR_PTR(-EFAULT);
656}
657
658static int ipp_put_mem_node(struct drm_device *drm_dev,
659 struct drm_exynos_ipp_cmd_node *c_node,
660 struct drm_exynos_ipp_mem_node *m_node)
661{
662 int i;
663
664 DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
665
666 if (!m_node) {
667 DRM_ERROR("invalid dequeue node.\n");
668 return -EFAULT;
669 }
670
671 DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id);
672
673 /* put gem buffer */
674 for_each_ipp_planar(i) {
675 unsigned long handle = m_node->buf_info.handles[i];
676 if (handle)
677 exynos_drm_gem_put_dma_addr(drm_dev, handle,
678 c_node->filp);
679 }
680
681 /* delete list in queue */
682 list_del(&m_node->list);
683 kfree(m_node);
684
685 return 0;
686} 683}
687 684
688static void ipp_free_event(struct drm_pending_event *event) 685static void ipp_free_event(struct drm_pending_event *event)