diff options
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_ipp.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index b60ae54ef82b..f1c51b4dd56c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c | |||
@@ -167,6 +167,13 @@ static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj, | |||
167 | return 0; | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | static void ipp_remove_id(struct idr *id_idr, struct mutex *lock, u32 id) | ||
171 | { | ||
172 | mutex_lock(lock); | ||
173 | idr_remove(id_idr, id); | ||
174 | mutex_unlock(lock); | ||
175 | } | ||
176 | |||
170 | static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id) | 177 | static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id) |
171 | { | 178 | { |
172 | void *obj; | 179 | void *obj; |
@@ -501,7 +508,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, | |||
501 | c_node->start_work = ipp_create_cmd_work(); | 508 | c_node->start_work = ipp_create_cmd_work(); |
502 | if (IS_ERR(c_node->start_work)) { | 509 | if (IS_ERR(c_node->start_work)) { |
503 | DRM_ERROR("failed to create start work.\n"); | 510 | DRM_ERROR("failed to create start work.\n"); |
504 | goto err_clear; | 511 | goto err_remove_id; |
505 | } | 512 | } |
506 | 513 | ||
507 | c_node->stop_work = ipp_create_cmd_work(); | 514 | c_node->stop_work = ipp_create_cmd_work(); |
@@ -542,16 +549,22 @@ err_free_stop: | |||
542 | kfree(c_node->stop_work); | 549 | kfree(c_node->stop_work); |
543 | err_free_start: | 550 | err_free_start: |
544 | kfree(c_node->start_work); | 551 | kfree(c_node->start_work); |
552 | err_remove_id: | ||
553 | ipp_remove_id(&ctx->prop_idr, &ctx->prop_lock, property->prop_id); | ||
545 | err_clear: | 554 | err_clear: |
546 | kfree(c_node); | 555 | kfree(c_node); |
547 | return ret; | 556 | return ret; |
548 | } | 557 | } |
549 | 558 | ||
550 | static void ipp_clean_cmd_node(struct drm_exynos_ipp_cmd_node *c_node) | 559 | static void ipp_clean_cmd_node(struct ipp_context *ctx, |
560 | struct drm_exynos_ipp_cmd_node *c_node) | ||
551 | { | 561 | { |
552 | /* delete list */ | 562 | /* delete list */ |
553 | list_del(&c_node->list); | 563 | list_del(&c_node->list); |
554 | 564 | ||
565 | ipp_remove_id(&ctx->prop_idr, &ctx->prop_lock, | ||
566 | c_node->property.prop_id); | ||
567 | |||
555 | /* destroy mutex */ | 568 | /* destroy mutex */ |
556 | mutex_destroy(&c_node->lock); | 569 | mutex_destroy(&c_node->lock); |
557 | mutex_destroy(&c_node->mem_lock); | 570 | mutex_destroy(&c_node->mem_lock); |
@@ -1122,7 +1135,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data, | |||
1122 | c_node->state = IPP_STATE_STOP; | 1135 | c_node->state = IPP_STATE_STOP; |
1123 | ippdrv->dedicated = false; | 1136 | ippdrv->dedicated = false; |
1124 | mutex_lock(&ippdrv->cmd_lock); | 1137 | mutex_lock(&ippdrv->cmd_lock); |
1125 | ipp_clean_cmd_node(c_node); | 1138 | ipp_clean_cmd_node(ctx, c_node); |
1126 | 1139 | ||
1127 | if (list_empty(&ippdrv->cmd_list)) | 1140 | if (list_empty(&ippdrv->cmd_list)) |
1128 | pm_runtime_put_sync(ippdrv->dev); | 1141 | pm_runtime_put_sync(ippdrv->dev); |
@@ -1686,7 +1699,7 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev) | |||
1686 | &ipp_id); | 1699 | &ipp_id); |
1687 | if (ret || ipp_id == 0) { | 1700 | if (ret || ipp_id == 0) { |
1688 | DRM_ERROR("failed to create id.\n"); | 1701 | DRM_ERROR("failed to create id.\n"); |
1689 | goto err_idr; | 1702 | goto err; |
1690 | } | 1703 | } |
1691 | 1704 | ||
1692 | DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n", | 1705 | DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n", |
@@ -1707,34 +1720,40 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev) | |||
1707 | ret = drm_iommu_attach_device(drm_dev, ippdrv->dev); | 1720 | ret = drm_iommu_attach_device(drm_dev, ippdrv->dev); |
1708 | if (ret) { | 1721 | if (ret) { |
1709 | DRM_ERROR("failed to activate iommu\n"); | 1722 | DRM_ERROR("failed to activate iommu\n"); |
1710 | goto err_iommu; | 1723 | goto err; |
1711 | } | 1724 | } |
1712 | } | 1725 | } |
1713 | } | 1726 | } |
1714 | 1727 | ||
1715 | return 0; | 1728 | return 0; |
1716 | 1729 | ||
1717 | err_iommu: | 1730 | err: |
1718 | /* get ipp driver entry */ | 1731 | /* get ipp driver entry */ |
1719 | list_for_each_entry_reverse(ippdrv, &exynos_drm_ippdrv_list, drv_list) | 1732 | list_for_each_entry_continue_reverse(ippdrv, &exynos_drm_ippdrv_list, |
1733 | drv_list) { | ||
1720 | if (is_drm_iommu_supported(drm_dev)) | 1734 | if (is_drm_iommu_supported(drm_dev)) |
1721 | drm_iommu_detach_device(drm_dev, ippdrv->dev); | 1735 | drm_iommu_detach_device(drm_dev, ippdrv->dev); |
1722 | 1736 | ||
1723 | err_idr: | 1737 | ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock, |
1724 | idr_destroy(&ctx->ipp_idr); | 1738 | ippdrv->prop_list.ipp_id); |
1725 | idr_destroy(&ctx->prop_idr); | 1739 | } |
1740 | |||
1726 | return ret; | 1741 | return ret; |
1727 | } | 1742 | } |
1728 | 1743 | ||
1729 | static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev) | 1744 | static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev) |
1730 | { | 1745 | { |
1731 | struct exynos_drm_ippdrv *ippdrv; | 1746 | struct exynos_drm_ippdrv *ippdrv; |
1747 | struct ipp_context *ctx = get_ipp_context(dev); | ||
1732 | 1748 | ||
1733 | /* get ipp driver entry */ | 1749 | /* get ipp driver entry */ |
1734 | list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { | 1750 | list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { |
1735 | if (is_drm_iommu_supported(drm_dev)) | 1751 | if (is_drm_iommu_supported(drm_dev)) |
1736 | drm_iommu_detach_device(drm_dev, ippdrv->dev); | 1752 | drm_iommu_detach_device(drm_dev, ippdrv->dev); |
1737 | 1753 | ||
1754 | ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock, | ||
1755 | ippdrv->prop_list.ipp_id); | ||
1756 | |||
1738 | ippdrv->drm_dev = NULL; | 1757 | ippdrv->drm_dev = NULL; |
1739 | exynos_drm_ippdrv_unregister(ippdrv); | 1758 | exynos_drm_ippdrv_unregister(ippdrv); |
1740 | } | 1759 | } |
@@ -1765,6 +1784,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, | |||
1765 | struct drm_exynos_file_private *file_priv = file->driver_priv; | 1784 | struct drm_exynos_file_private *file_priv = file->driver_priv; |
1766 | struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; | 1785 | struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; |
1767 | struct exynos_drm_ippdrv *ippdrv = NULL; | 1786 | struct exynos_drm_ippdrv *ippdrv = NULL; |
1787 | struct ipp_context *ctx = get_ipp_context(dev); | ||
1768 | struct drm_exynos_ipp_cmd_node *c_node, *tc_node; | 1788 | struct drm_exynos_ipp_cmd_node *c_node, *tc_node; |
1769 | int count = 0; | 1789 | int count = 0; |
1770 | 1790 | ||
@@ -1791,7 +1811,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, | |||
1791 | } | 1811 | } |
1792 | 1812 | ||
1793 | ippdrv->dedicated = false; | 1813 | ippdrv->dedicated = false; |
1794 | ipp_clean_cmd_node(c_node); | 1814 | ipp_clean_cmd_node(ctx, c_node); |
1795 | if (list_empty(&ippdrv->cmd_list)) | 1815 | if (list_empty(&ippdrv->cmd_list)) |
1796 | pm_runtime_put_sync(ippdrv->dev); | 1816 | pm_runtime_put_sync(ippdrv->dev); |
1797 | } | 1817 | } |