Commit 075436b0 authored by YoungJun Cho's avatar YoungJun Cho Committed by Inki Dae

drm/exynos: ipp: add ipp_remove_id()

This patch adds ipp_remove_id() for idr resource free.
Signed-off-by: default avatarYoungJun Cho <yj44.cho@samsung.com>
Acked-by: default avatarSeong-Woo Kim <sw0312.kim@samsung.com>
Acked-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Tested-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent 7f5af059
...@@ -167,6 +167,13 @@ static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj, ...@@ -167,6 +167,13 @@ static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj,
return 0; return 0;
} }
static void ipp_remove_id(struct idr *id_idr, struct mutex *lock, u32 id)
{
mutex_lock(lock);
idr_remove(id_idr, id);
mutex_unlock(lock);
}
static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id) static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id)
{ {
void *obj; void *obj;
...@@ -501,7 +508,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, ...@@ -501,7 +508,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
c_node->start_work = ipp_create_cmd_work(); c_node->start_work = ipp_create_cmd_work();
if (IS_ERR(c_node->start_work)) { if (IS_ERR(c_node->start_work)) {
DRM_ERROR("failed to create start work.\n"); DRM_ERROR("failed to create start work.\n");
goto err_clear; goto err_remove_id;
} }
c_node->stop_work = ipp_create_cmd_work(); c_node->stop_work = ipp_create_cmd_work();
...@@ -542,16 +549,22 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, ...@@ -542,16 +549,22 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
kfree(c_node->stop_work); kfree(c_node->stop_work);
err_free_start: err_free_start:
kfree(c_node->start_work); kfree(c_node->start_work);
err_remove_id:
ipp_remove_id(&ctx->prop_idr, &ctx->prop_lock, property->prop_id);
err_clear: err_clear:
kfree(c_node); kfree(c_node);
return ret; return ret;
} }
static void ipp_clean_cmd_node(struct drm_exynos_ipp_cmd_node *c_node) static void ipp_clean_cmd_node(struct ipp_context *ctx,
struct drm_exynos_ipp_cmd_node *c_node)
{ {
/* delete list */ /* delete list */
list_del(&c_node->list); list_del(&c_node->list);
ipp_remove_id(&ctx->prop_idr, &ctx->prop_lock,
c_node->property.prop_id);
/* destroy mutex */ /* destroy mutex */
mutex_destroy(&c_node->lock); mutex_destroy(&c_node->lock);
mutex_destroy(&c_node->mem_lock); mutex_destroy(&c_node->mem_lock);
...@@ -1122,7 +1135,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data, ...@@ -1122,7 +1135,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
c_node->state = IPP_STATE_STOP; c_node->state = IPP_STATE_STOP;
ippdrv->dedicated = false; ippdrv->dedicated = false;
mutex_lock(&ippdrv->cmd_lock); mutex_lock(&ippdrv->cmd_lock);
ipp_clean_cmd_node(c_node); ipp_clean_cmd_node(ctx, c_node);
if (list_empty(&ippdrv->cmd_list)) if (list_empty(&ippdrv->cmd_list))
pm_runtime_put_sync(ippdrv->dev); pm_runtime_put_sync(ippdrv->dev);
...@@ -1686,7 +1699,7 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev) ...@@ -1686,7 +1699,7 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
&ipp_id); &ipp_id);
if (ret || ipp_id == 0) { if (ret || ipp_id == 0) {
DRM_ERROR("failed to create id.\n"); DRM_ERROR("failed to create id.\n");
goto err_idr; goto err;
} }
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n", 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,34 +1720,40 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
ret = drm_iommu_attach_device(drm_dev, ippdrv->dev); ret = drm_iommu_attach_device(drm_dev, ippdrv->dev);
if (ret) { if (ret) {
DRM_ERROR("failed to activate iommu\n"); DRM_ERROR("failed to activate iommu\n");
goto err_iommu; goto err;
} }
} }
} }
return 0; return 0;
err_iommu: err:
/* get ipp driver entry */ /* get ipp driver entry */
list_for_each_entry_reverse(ippdrv, &exynos_drm_ippdrv_list, drv_list) list_for_each_entry_continue_reverse(ippdrv, &exynos_drm_ippdrv_list,
drv_list) {
if (is_drm_iommu_supported(drm_dev)) if (is_drm_iommu_supported(drm_dev))
drm_iommu_detach_device(drm_dev, ippdrv->dev); drm_iommu_detach_device(drm_dev, ippdrv->dev);
err_idr: ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock,
idr_destroy(&ctx->ipp_idr); ippdrv->prop_list.ipp_id);
idr_destroy(&ctx->prop_idr); }
return ret; return ret;
} }
static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev) static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
{ {
struct exynos_drm_ippdrv *ippdrv; struct exynos_drm_ippdrv *ippdrv;
struct ipp_context *ctx = get_ipp_context(dev);
/* get ipp driver entry */ /* get ipp driver entry */
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
if (is_drm_iommu_supported(drm_dev)) if (is_drm_iommu_supported(drm_dev))
drm_iommu_detach_device(drm_dev, ippdrv->dev); drm_iommu_detach_device(drm_dev, ippdrv->dev);
ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock,
ippdrv->prop_list.ipp_id);
ippdrv->drm_dev = NULL; ippdrv->drm_dev = NULL;
exynos_drm_ippdrv_unregister(ippdrv); exynos_drm_ippdrv_unregister(ippdrv);
} }
...@@ -1765,6 +1784,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, ...@@ -1765,6 +1784,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
struct drm_exynos_file_private *file_priv = file->driver_priv; struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
struct exynos_drm_ippdrv *ippdrv = NULL; struct exynos_drm_ippdrv *ippdrv = NULL;
struct ipp_context *ctx = get_ipp_context(dev);
struct drm_exynos_ipp_cmd_node *c_node, *tc_node; struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
int count = 0; int count = 0;
...@@ -1791,7 +1811,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, ...@@ -1791,7 +1811,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
} }
ippdrv->dedicated = false; ippdrv->dedicated = false;
ipp_clean_cmd_node(c_node); ipp_clean_cmd_node(ctx, c_node);
if (list_empty(&ippdrv->cmd_list)) if (list_empty(&ippdrv->cmd_list))
pm_runtime_put_sync(ippdrv->dev); pm_runtime_put_sync(ippdrv->dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment