mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] usb: common: usb-conn-gpio: join IRQs before canceling work
@ 2026-10-02 21:41 Myeonghun Pak
  0 siblings, 0 replies; only message in thread
From: Myeonghun Pak @ 2026-10-02 21:41 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Chunfeng Yun, linux-usb, linux-kernel, stable

The GPIO IRQ handlers can enqueue delayed work after remove has canceled
it. A similar lifetime issue exists during probe: once the ID IRQ has
been requested, a later VBUS IRQ setup failure can unwind probe while
the ID IRQ is still able to queue work.

Managed IRQ cleanup happens only after remove or failed probe returns,
so queued work can outlive the state it accesses.

Request both IRQs disabled and enable them only after setup succeeds.
During cleanup, explicitly free and synchronize the installed IRQs
before canceling delayed work. This closes the producer before joining
the work it can queue.

This issue was identified during our ongoing static-analysis research
while reviewing kernel code.

Fixes: 4602f3bff266 ("usb: common: add USB GPIO based connection detection driver")
Assisted-by: LLM
Cc: stable@vger.kernel.org
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
 drivers/usb/common/usb-conn-gpio.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c
index 421c3af38e06975259f4a1792aa3b3708a192d59..60badc9a2db8b8e7e621141307de3c1729e8f101 100644
--- a/drivers/usb/common/usb-conn-gpio.c
+++ b/drivers/usb/common/usb-conn-gpio.c
@@ -29,7 +29,7 @@
 #define USB_GPIO_DEB_US		((USB_GPIO_DEB_MS) * 1000)	/* us */
 
 #define USB_CONN_IRQF	\
-	(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT)
+	(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_NO_AUTOEN)
 
 struct usb_conn_info {
 	struct device *dev;
@@ -262,7 +262,7 @@
 		if (info->vbus_irq < 0) {
 			dev_err(dev, "failed to get VBUS IRQ\n");
 			ret = info->vbus_irq;
-			goto put_role_sw;
+			goto free_id_irq;
 		}
 
 		ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
@@ -270,19 +270,30 @@
 						pdev->name, info);
 		if (ret < 0) {
 			dev_err(dev, "failed to request VBUS IRQ\n");
-			goto put_role_sw;
+			goto free_id_irq;
 		}
 	}
 
 	platform_set_drvdata(pdev, info);
 	device_set_wakeup_capable(&pdev->dev, true);
 
+	info->initial_detection = true;
+
+	/* Enable the IRQs only after all the setup has succeeded. */
+	if (info->id_gpiod)
+		enable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		enable_irq(info->vbus_irq);
+
 	/* Perform initial detection */
-	info->initial_detection = true;
 	usb_conn_queue_dwork(info, 0);
 
 	return 0;
 
+free_id_irq:
+	if (info->id_gpiod)
+		devm_free_irq(dev, info->id_irq, info);
+	cancel_delayed_work_sync(&info->dw_det);
 put_role_sw:
 	usb_role_switch_put(info->role_sw);
 	return ret;
@@ -291,6 +302,11 @@
 static void usb_conn_remove(struct platform_device *pdev)
 {
 	struct usb_conn_info *info = platform_get_drvdata(pdev);
+
+	if (info->id_gpiod)
+		devm_free_irq(&pdev->dev, info->id_irq, info);
+	if (info->vbus_gpiod)
+		devm_free_irq(&pdev->dev, info->vbus_irq, info);
 
 	cancel_delayed_work_sync(&info->dw_det);
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-02 21:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-02 21:41 [PATCH] usb: common: usb-conn-gpio: join IRQs before canceling work Myeonghun Pak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®