From ca927fc45e4906bdab42426da044fba4d3584f34 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Tue, 28 Apr 2026 21:18:21 +0800 Subject: [PATCH] usb: typec: fusb302: Fix resource leak when devm_drm_dp_hpd_bridge_add() fails If devm_drm_dp_hpd_bridge_add() fails during fusb302_probe(), the original code returned directly without cleaning up the resources. Move bridge registration before the IRQ is requested and route bridge registration failures through the existing TCPM unregister and fwnode cleanup path. Fixes: 5d79c525405d ("usb: typec: fusb302: add DRM DP HPD bridge support") Signed-off-by: Felix Gu Reviewed-by: Heikki Krogerus Reviewed-by: Sebastian Reichel Link: https://patch.msgid.link/20260428-fusb-v2-1-aa3b5942cabb@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/fusb302.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 889c4c29c1b8..9ab1277b7ed1 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1751,19 +1751,22 @@ static int fusb302_probe(struct i2c_client *client) bridge_dev = devm_drm_dp_hpd_bridge_alloc(chip->dev, to_of_node(chip->tcpc_dev.fwnode)); if (IS_ERR(bridge_dev)) { - ret = PTR_ERR(bridge_dev); - dev_err_probe(chip->dev, ret, "failed to alloc bridge\n"); - goto destroy_workqueue; + ret = dev_err_probe(chip->dev, PTR_ERR(bridge_dev), + "failed to alloc bridge\n"); + goto fwnode_put; } chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); if (IS_ERR(chip->tcpm_port)) { - fwnode_handle_put(chip->tcpc_dev.fwnode); ret = dev_err_probe(dev, PTR_ERR(chip->tcpm_port), "cannot register tcpm port\n"); - goto destroy_workqueue; + goto fwnode_put; } + ret = devm_drm_dp_hpd_bridge_add(chip->dev, bridge_dev); + if (ret) + goto tcpm_unregister_port; + ret = request_threaded_irq(chip->gpio_int_n_irq, NULL, fusb302_irq_intn, IRQF_ONESHOT | IRQF_TRIGGER_LOW, "fsc_interrupt_int_n", chip); @@ -1774,14 +1777,11 @@ static int fusb302_probe(struct i2c_client *client) enable_irq_wake(chip->gpio_int_n_irq); i2c_set_clientdata(client, chip); - ret = devm_drm_dp_hpd_bridge_add(chip->dev, bridge_dev); - if (ret) - return ret; - - return ret; + return 0; tcpm_unregister_port: tcpm_unregister_port(chip->tcpm_port); +fwnode_put: fwnode_handle_put(chip->tcpc_dev.fwnode); destroy_workqueue: fusb302_debugfs_exit(chip);