drm/exynos: ipp: add ipp_remove_id()
This patch adds ipp_remove_id() for idr resource free. Signed-off-by: YoungJun Cho <yj44.cho@samsung.com> Acked-by: Seong-Woo Kim <sw0312.kim@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Tested-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
Родитель
7f5af0597b
Коммит
075436b08b
|
@ -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,
|
||||||
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 @@ err_free_stop:
|
||||||
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,
|
||||||
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)
|
||||||
&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)
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче