]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: typec: fusb302: Fix resource leak when devm_drm_dp_hpd_bridge_add() fails
authorFelix Gu <ustc.gu@gmail.com>
Tue, 28 Apr 2026 13:18:21 +0000 (21:18 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 21 May 2026 14:40:54 +0000 (16:40 +0200)
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 <ustc.gu@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Link: https://patch.msgid.link/20260428-fusb-v2-1-aa3b5942cabb@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/tcpm/fusb302.c

index 889c4c29c1b806c74e1cfd54e0a5bc413a31a778..9ab1277b7ed1ef1df940497477385274ea9e8fe9 100644 (file)
@@ -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);