diff options
author | Andrzej Hajda <a.hajda@samsung.com> | 2014-08-28 05:07:30 -0400 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2014-09-19 11:56:11 -0400 |
commit | 6602ffb84949779fd5d27399ca5f608a409a2a83 (patch) | |
tree | 26c3d22b650cd8f3e965f4fca1420b3bcd4d8329 | |
parent | 985c293d094ae640a25e0c0e78d161a3fcb95b5d (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.c | 67 |
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 | ||
602 | static 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 | |||
602 | static struct drm_exynos_ipp_mem_node | 631 | static 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 | |||
653 | err_clear: | ||
654 | kfree(m_node); | ||
655 | return ERR_PTR(-EFAULT); | ||
656 | } | ||
657 | |||
658 | static 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 | ||
688 | static void ipp_free_event(struct drm_pending_event *event) | 685 | static void ipp_free_event(struct drm_pending_event *event) |