Skip to contentSkip to conversation

usb: common: usb-conn-gpio: manage connector ID with devres

PATCH New Sang-Hoon Choi 1 participant 1 message Oct 2 USB

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 usb: common: usb-conn-gpio: manage connector ID with devres

usb_conn_psy_register() allocates a connector ID, but usb_conn_probe() does not release it if a later GPIO-to-IRQ conversion or IRQ request fails. The failed probe therefore leaks the allocated ID.

Manage the ID with a devm action registered before the power supply. This also makes the ID available only after the power supply has been unregistered during teardown, avoiding premature reuse of its name.

Fixes d4e5b10c5562 ("usb: common: usb-conn-gpio: use a unique name for usb connector device")
Assisted-by LLM

---
Compile-tested the affected object with x86_64 allmodconfig
and W=1 (GCC 13.3.0). Base: mainline 3b7cab693ba2bab63774bf5b988e8a61b2ef0f32. No hardware testing or runtime failure reproduction was performed.

 drivers/usb/common/usb-conn-gpio.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)
drivers/usb/common/usb-conn-gpio.c +14 -9
index 421c3af38e06..128ab683f110 100644
@@ -157,6 +157,13 @@ static int usb_charger_get_property(struct power_supply *psy,
 	return 0;
 }
 
+static void usb_conn_ida_free(void *data)
+{
+	struct usb_conn_info *info = data;
+
+	ida_free(&usb_conn_ida, info->conn_id);
+}
+
 static int usb_conn_psy_register(struct usb_conn_info *info)
 {
 	struct device *dev = info->dev;
@@ -164,17 +171,20 @@ static int usb_conn_psy_register(struct usb_conn_info *info)
 	struct power_supply_config cfg = {
 		.fwnode = dev_fwnode(dev),
 	};
+	int ret;
 
 	info->conn_id = ida_alloc(&usb_conn_ida, GFP_KERNEL);
 	if (info->conn_id < 0)
 		return info->conn_id;
 
+	ret = devm_add_action_or_reset(dev, usb_conn_ida_free, info);
+	if (ret)
+		return ret;
+
 	desc->name = devm_kasprintf(dev, GFP_KERNEL, "usb-charger-%d",
 				    info->conn_id);
-	if (!desc->name) {
-		ida_free(&usb_conn_ida, info->conn_id);
+	if (!desc->name)
 		return -ENOMEM;
-	}
 
 	desc->properties = usb_charger_properties;
 	desc->num_properties = ARRAY_SIZE(usb_charger_properties);
@@ -183,10 +193,8 @@ static int usb_conn_psy_register(struct usb_conn_info *info)
 	cfg.drv_data = info;
 
 	info->charger = devm_power_supply_register(dev, desc, &cfg);
-	if (IS_ERR(info->charger)) {
+	if (IS_ERR(info->charger))
 		dev_err(dev, "Unable to register charger %d\n", info->conn_id);
-		ida_free(&usb_conn_ida, info->conn_id);
-	}
 
 	return PTR_ERR_OR_ZERO(info->charger);
 }
@@ -294,9 +302,6 @@ static void usb_conn_remove(struct platform_device *pdev)
 
 	cancel_delayed_work_sync(&info->dw_det);
 
-	if (info->charger)
-		ida_free(&usb_conn_ida, info->conn_id);
-
 	if (info->last_role == USB_ROLE_HOST && info->vbus)
 		regulator_disable(info->vbus);