Linux USB
 help / color / mirror / Atom feed
* [PATCH 1/1] usb: xhci-plat: keep IRQ masked while HCD is inaccessible across system sleep
@ 2026-10-20 11:10 Jiazi Liu
  2026-10-20 11:26 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Jiazi Liu @ 2026-10-20 11:10 UTC (permalink / raw)
  To: mathias.nyman, gregkh; +Cc: linux-usb, linux-kernel, guanyulin, liujiazi

From: Jiazi Liu <liujiazi@amazon.com>

xhci_suspend() clears HCD_FLAG_HW_ACCESSIBLE and halts the xHC, but
the interrupter stays enabled and a pending event is not
acknowledged. The PM core re-enables device IRQs in
dpm_resume_noirq(), before the resume callback runs xhci_resume().

In this window a halted xHC with a pending event keeps its
level-triggered IRQ asserted. usb_hcd_irq() returns IRQ_NONE because
the hardware is not accessible, so the IRQ is delivered again and
again until the IRQ core reports it as spurious and disables it:

  irq 121: nobody cared (try booting with the "irqpoll" option)
   dpm_resume_early+0x90/0x300
   dpm_resume_start+0x2c/0x50
   hibernation_snapshot+0x224/0x488
  handlers:
  [<...>] usb_hcd_irq
  Disabling IRQ #121

This was seen when a hibernation snapshot is taken right after a
restore, as the restore leaves a port status change event pending.

Disable the IRQ in xhci_plat_suspend_common() and enable it again in
xhci_plat_resume_common() after xhci_resume(). Skip this if the host
is a wakeup source, as it needs the IRQ during suspend.

Signed-off-by: Jiazi Liu <liujiazi@amazon.com>
---
 drivers/usb/host/xhci-plat.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 074d9c731639..74a56f18de3e 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -478,13 +478,22 @@ static int xhci_plat_suspend_common(struct device *dev)
 	ret = xhci_priv_suspend_quirk(hcd);
 	if (ret)
 		return ret;
+
+	/*
+	 * Mask the IRQ while the HCD is not accessible. The PM core unmasks
+	 * it before xhci_resume() runs, and a pending event on the halted
+	 * xHC would cause an interrupt storm.
+	 */
+	if (!device_may_wakeup(dev))
+		disable_irq(hcd->irq);
+
 	/*
 	 * xhci_suspend() needs `do_wakeup` to know whether host is allowed
 	 * to do wakeup during suspend.
 	 */
 	ret = xhci_suspend(xhci, device_may_wakeup(dev));
 	if (ret)
-		return ret;
+		goto err_enable_irq;
 
 	if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) {
 		clk_disable_unprepare(xhci->clk);
@@ -492,6 +501,12 @@ static int xhci_plat_suspend_common(struct device *dev)
 	}
 
 	return 0;
+
+err_enable_irq:
+	if (!device_may_wakeup(dev))
+		enable_irq(hcd->irq);
+
+	return ret;
 }
 
 static int xhci_plat_suspend(struct device *dev)
@@ -523,12 +538,12 @@ static int xhci_plat_resume_common(struct device *dev, bool power_lost)
 	if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) {
 		ret = clk_prepare_enable(xhci->clk);
 		if (ret)
-			return ret;
+			goto enable_irq;
 
 		ret = clk_prepare_enable(xhci->reg_clk);
 		if (ret) {
 			clk_disable_unprepare(xhci->clk);
-			return ret;
+			goto enable_irq;
 		}
 	}
 
@@ -544,6 +559,10 @@ static int xhci_plat_resume_common(struct device *dev, bool power_lost)
 	if (ret)
 		goto disable_clks;
 
+	/* The HCD is accessible again, pair with disable_irq() in suspend. */
+	if (!device_may_wakeup(dev))
+		enable_irq(hcd->irq);
+
 	pm_runtime_disable(dev);
 	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
@@ -555,6 +574,9 @@ static int xhci_plat_resume_common(struct device *dev, bool power_lost)
 		clk_disable_unprepare(xhci->clk);
 		clk_disable_unprepare(xhci->reg_clk);
 	}
+enable_irq:
+	if (!device_may_wakeup(dev))
+		enable_irq(hcd->irq);
 
 	return ret;
 }
-- 
2.54.0 (Apple Git-157)


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-20 11:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-20 11:10 [PATCH 1/1] usb: xhci-plat: keep IRQ masked while HCD is inaccessible across system sleep Jiazi Liu
2026-10-20 11:26 ` sashiko-bot

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