kmb_probe() obtain a reference to a platform device by of_find_device_by_node(). This call increases the reference count of the returned device, which should be dropped by calling put_device() when the device is no longer needed. However, the code fails to call put_device() in several error handling paths and the normal device removal path. This could result in reference count leaks that prevent the proper cleanup of the platform device when the driver is unloaded or during error recovery.
Add put_device() in all code paths where dsi_pdev is no longer needed, including error paths and the normal removal path.
Found by code review.
Cc: stable@vger.kernel.org Fixes: 7f7b96a8a0a1 ("drm/kmb: Add support for KeemBay Display") Signed-off-by: Ma Ke make24@iscas.ac.cn --- drivers/gpu/drm/kmb/kmb_drv.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c index 32cda134ae3e..4fc9fdf92118 100644 --- a/drivers/gpu/drm/kmb/kmb_drv.c +++ b/drivers/gpu/drm/kmb/kmb_drv.c @@ -473,6 +473,8 @@ static void kmb_remove(struct platform_device *pdev)
/* Unregister DSI host */ kmb_dsi_host_unregister(kmb->kmb_dsi); + if (kmb->kmb_dsi && kmb->kmb_dsi->pdev) + put_device(&kmb->kmb_dsi->pdev->dev); drm_atomic_helper_shutdown(drm); }
@@ -517,17 +519,20 @@ static int kmb_probe(struct platform_device *pdev) ret = kmb_dsi_host_bridge_init(get_device(&dsi_pdev->dev));
if (ret == -EPROBE_DEFER) { - return -EPROBE_DEFER; + ret = -EPROBE_DEFER; + goto err_free2; } else if (ret) { DRM_ERROR("probe failed to initialize DSI host bridge\n"); - return ret; + goto err_free2; }
/* Create DRM device */ kmb = devm_drm_dev_alloc(dev, &kmb_driver, struct kmb_drm_private, drm); - if (IS_ERR(kmb)) - return PTR_ERR(kmb); + if (IS_ERR(kmb)) { + ret = PTR_ERR(kmb); + goto err_free2; + }
dev_set_drvdata(dev, &kmb->drm);
@@ -576,7 +581,8 @@ static int kmb_probe(struct platform_device *pdev) err_free1: dev_set_drvdata(dev, NULL); kmb_dsi_host_unregister(kmb->kmb_dsi); - + err_free2: + put_device(&dsi_pdev->dev); return ret; }
…
Add put_device() in all code paths where dsi_pdev is no longer needed, including error paths and the normal removal path.
How do you think about to apply the attribute “__free(put_device)”? https://elixir.bootlin.com/linux/v6.18-rc5/source/include/linux/device.h#L11...
By the way: I propose to avoid duplicate of_node_put() calls in this function implementation.
Would it be helpful to append parentheses to the function name in the summary phrase?
Regards, Markus
linux-stable-mirror@lists.linaro.org