Hi Joe, Thank you for the patch. On Fri, Jan 31, 2025 at 04:34:53PM +0900, Joe Hattori wrote: > Current implementation of .probe() leaks a reference of i2c_adapter. > Implement an error path and call put_device() on the obtained > i2c_adapter in it to fix this refcount bug. > > Also, remove the IS_ERR() check before calling > i2c_put_adapter(conn->bridge.ddc) since conn->bridge.dcc is either NULL > or a valid pointer, and a null-check is already done in > i2c_put_adapter(). > > This bug was found by an experimental verification tool that I am > developing. > > Fixes: 0c275c30176b ("drm/bridge: Add bridge driver for display connectors") > Signed-off-by: Joe Hattori <joe@xxxxxxxxxxxxxxxxxxxxx> > --- > Changes in V4: > - Stopped assigning the return value of dev_err_probe(). > - Updated the commit message. > > Changes in V3: > - Removed shadowed variables (ret). > > Changes in V2: > - Omit the null check before calling i2c_put_adapter(). > --- > drivers/gpu/drm/bridge/display-connector.c | 31 +++++++++++++--------- > 1 file changed, 19 insertions(+), 12 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c > index 72bc508d4e6e..52a86f99fa45 100644 > --- a/drivers/gpu/drm/bridge/display-connector.c > +++ b/drivers/gpu/drm/bridge/display-connector.c > @@ -329,35 +329,39 @@ static int display_connector_probe(struct platform_device *pdev) > > /* Get the DP PWR for DP connector. */ > if (type == DRM_MODE_CONNECTOR_DisplayPort) { > - int ret; > - > ret = display_connector_get_supply(pdev, conn, "dp-pwr"); > - if (ret < 0) > - return dev_err_probe(&pdev->dev, ret, "failed to get DP PWR regulator\n"); > + if (ret < 0) { > + dev_err_probe(&pdev->dev, ret, > + "failed to get DP PWR regulator\n"); > + goto err_put; > + } > } > > /* enable DDC */ > if (type == DRM_MODE_CONNECTOR_HDMIA) { > - int ret; > - > conn->ddc_en = devm_gpiod_get_optional(&pdev->dev, "ddc-en", > GPIOD_OUT_HIGH); > > if (IS_ERR(conn->ddc_en)) { > dev_err(&pdev->dev, "Couldn't get ddc-en gpio\n"); > - return PTR_ERR(conn->ddc_en); > + ret = PTR_ERR(conn->ddc_en); > + goto err_put; > } > > ret = display_connector_get_supply(pdev, conn, "hdmi-pwr"); > - if (ret < 0) > - return dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n"); > + if (ret < 0) { > + dev_err_probe( > + &pdev->dev, ret, > + "failed to get HDMI +5V Power regulator\n"); This looks weird. dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n"); or dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n"); if you prefer. With that fixed, Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > + goto err_put; > + } > } > > if (conn->supply) { > ret = regulator_enable(conn->supply); > if (ret) { > dev_err(&pdev->dev, "failed to enable PWR regulator: %d\n", ret); > - return ret; > + goto err_put; > } > } > > @@ -383,6 +387,10 @@ static int display_connector_probe(struct platform_device *pdev) > drm_bridge_add(&conn->bridge); > > return 0; > + > +err_put: > + i2c_put_adapter(conn->bridge.ddc); > + return ret; > } > > static void display_connector_remove(struct platform_device *pdev) > @@ -397,8 +405,7 @@ static void display_connector_remove(struct platform_device *pdev) > > drm_bridge_remove(&conn->bridge); > > - if (!IS_ERR(conn->bridge.ddc)) > - i2c_put_adapter(conn->bridge.ddc); > + i2c_put_adapter(conn->bridge.ddc); > } > > static const struct of_device_id display_connector_match[] = { -- Regards, Laurent Pinchart