]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/mediatek: mtk_drm_drv: Fix kobject put for mtk_mutex device ptr
authorAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Thu, 3 Apr 2025 10:47:37 +0000 (12:47 +0200)
committerChun-Kuang Hu <chunkuang.hu@kernel.org>
Wed, 14 May 2025 23:01:52 +0000 (23:01 +0000)
This driver is taking a kobject for mtk_mutex only once per mmsys
device for each drm-mediatek driver instance, differently from the
behavior with other components, but it is decrementing the kobj's
refcount in a loop and once per mmsys: this is not right and will
result in a refcount_t underflow warning when mediatek-drm returns
multiple probe deferrals in one boot (or when manually bound and
unbound).

Besides that, the refcount for mutex_dev was not decremented for
error cases in mtk_drm_bind(), causing another refcount_t warning
but this time for overflow, when the failure happens not during
driver bind but during component bind.

In order to fix one of the reasons why this is happening, remove
the put_device(xx->mutex_dev) loop from the mtk_drm_kms_init()'s
put_mutex_dev label (and drop the label) and add a single call to
correctly free the single incremented refcount of mutex_dev to
the mtk_drm_unbind() function to fix the refcount_t underflow.

Moreover, add the same call to the error cases in mtk_drm_bind()
to fix the refcount_t overflow.

Fixes: 1ef7ed48356c ("drm/mediatek: Modify mediatek-drm for mt8195 multi mmsys support")
Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://patchwork.kernel.org/project/dri-devel/patch/20250403104741.71045-2-angelogioacchino.delregno@collabora.com/
Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
drivers/gpu/drm/mediatek/mtk_drm_drv.c

index 74158b9d65035bda2f44680deba3eafb664a589f..5994e2a97dc135bf4f4e046c6ebe56fec31e5ed0 100644 (file)
@@ -470,7 +470,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 
        ret = drmm_mode_config_init(drm);
        if (ret)
-               goto put_mutex_dev;
+               return ret;
 
        drm->mode_config.min_width = 64;
        drm->mode_config.min_height = 64;
@@ -489,7 +489,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
                drm->dev_private = private->all_drm_private[i];
                ret = component_bind_all(private->all_drm_private[i]->dev, drm);
                if (ret)
-                       goto put_mutex_dev;
+                       return ret;
        }
 
        /*
@@ -582,9 +582,6 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 err_component_unbind:
        for (i = 0; i < private->data->mmsys_dev_num; i++)
                component_unbind_all(private->all_drm_private[i]->dev, drm);
-put_mutex_dev:
-       for (i = 0; i < private->data->mmsys_dev_num; i++)
-               put_device(private->all_drm_private[i]->mutex_dev);
 
        return ret;
 }
@@ -655,8 +652,10 @@ static int mtk_drm_bind(struct device *dev)
                return 0;
 
        drm = drm_dev_alloc(&mtk_drm_driver, dev);
-       if (IS_ERR(drm))
-               return PTR_ERR(drm);
+       if (IS_ERR(drm)) {
+               ret = PTR_ERR(drm);
+               goto err_put_dev;
+       }
 
        private->drm_master = true;
        drm->dev_private = private;
@@ -682,6 +681,8 @@ err_free:
        drm_dev_put(drm);
        for (i = 0; i < private->data->mmsys_dev_num; i++)
                private->all_drm_private[i]->drm = NULL;
+err_put_dev:
+       put_device(private->mutex_dev);
        return ret;
 }
 
@@ -694,6 +695,8 @@ static void mtk_drm_unbind(struct device *dev)
                drm_dev_unregister(private->drm);
                mtk_drm_kms_deinit(private->drm);
                drm_dev_put(private->drm);
+
+               put_device(private->mutex_dev);
        }
        private->mtk_drm_bound = false;
        private->drm_master = false;