The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts
@ 2026-07-14  9:02 Jie Deng
  2026-07-27 14:19 ` Mathias Nyman
  0 siblings, 1 reply; 6+ messages in thread
From: Jie Deng @ 2026-07-14  9:02 UTC (permalink / raw)
  To: mathias.nyman; +Cc: linux-usb, gregkh, linux-kernel, Jie Deng

Commit 944e7deb4238 ("xhci: Avoid PCI MSI/MSIX interrupt
reinitialization at resume") moved MSI/MSI-X setup out of xhci_run()
into a PCI-specific xhci_pci_run() that is only invoked at probe time,
and removed the xhci_cleanup_msix() call from xhci_resume().

The rationale (avoid redundant MSI reconfiguration on every resume) is
sound for controllers that preserve state across suspend.  It is however
*harmful* for controllers carrying XHCI_RESET_ON_RESUME: those hosts are
fully reset on every S3 resume, and on some of them (e.g. ASMedia 3042)
the MSI/MSI-X delivery path is no longer functional after the controller
reset + D3->D0 transition.  Because the MSI vectors are now kept around
unchanged across resume, the first post-resume command-completion event
(ENABLE_SLOT) is delivered to a stale MSI channel and never reaches the
CPU, which surfaces as:
  xhci_hcd 0000:05:00.0: Error while assigning device slot ID: Command Aborted
  xhci_hcd 0000:05:00.0: Max number of devices this xHCI host supports is 127.
  usb 1-2: device not accepting address 3, error -22
  xhci_hcd 0000:05:00.0: Error while assigning device slot ID: Command Aborted
  xhci_hcd 0000:05:00.0: Max number of devices this xHCI host supports is 127.
  usb 1-2: device not accepting address 3, error -22
  xhci_hcd 0000:05:00.0: Error while assigning device slot ID: Command Aborted
  xhci_hcd 0000:05:00.0: Max number of devices this xHCI host supports is 127.
  usb 2-2: device not accepting address 3, error -22

Up to v6.3 the resume reset path did xhci_cleanup_msix() and, through
xhci_run() -> xhci_try_enable_msi(), re-allocated the vectors, which
incidentally re-armed the MSI delivery path and masked the hardware
issue.  Work it around by restoring that behaviour, but only for hosts
marked XHCI_RESET_ON_RESUME and only for PCI devices (platform/RCAR
hosts using the same quirk must not be touched).

Fix: 944e7deb4238 ("xhci: Avoid PCI MSI/MSIX interrupt reinitialization at resume")
Signed-off-by: Jie Deng <dengjie03@kylinos.cn>
---
 drivers/usb/host/xhci-pci.c |  6 ++++--
 drivers/usb/host/xhci.c     | 19 +++++++++++++++++++
 drivers/usb/host/xhci.h     |  2 ++
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6b3fcba44b08..77b3215c95f3 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -126,7 +126,7 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
 }
 
 /* Legacy IRQ is freed by usb_remove_hcd() or usb_hcd_pci_shutdown() */
-static void xhci_cleanup_msix(struct xhci_hcd *xhci)
+void xhci_cleanup_msix(struct xhci_hcd *xhci)
 {
 	struct usb_hcd *hcd = xhci_to_hcd(xhci);
 	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
@@ -138,9 +138,10 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
 	pci_free_irq_vectors(pdev);
 	hcd->msix_enabled = 0;
 }
+EXPORT_SYMBOL_GPL(xhci_cleanup_msix);
 
 /* Try enabling MSI-X with MSI and legacy IRQ as fallback */
-static int xhci_try_enable_msi(struct usb_hcd *hcd)
+int xhci_try_enable_msi(struct usb_hcd *hcd)
 {
 	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -207,6 +208,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
 	hcd->irq = pdev->irq;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(xhci_try_enable_msi);
 
 static int xhci_pci_run(struct usb_hcd *hcd)
 {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 091c82ca8ee2..7dd3afcf6b2e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1190,10 +1190,29 @@ int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume)
 		xhci_for_each_ring_seg(xhci->cmd_ring->first_seg, seg)
 			memset(seg->trbs, 0, sizeof(union xhci_trb) * TRBS_PER_SEGMENT);
 
+		/* XHCI_RESET_ON_RESUME hosts are fully reset on every resume.
+		 * On some of them (e.g. ASMedia 3042) the MSI/MSI-X delivery
+		 * path is no longer valid after the reset + D3->D0 cycle, so
+		 * tear the vectors down here and let xhci_try_enable_msi()
+		 * re-allocate them below, matching pre-6.4 behaviour.
+		 */
+		if (xhci->quirks & XHCI_RESET_ON_RESUME)
+			xhci_cleanup_msix(xhci);
+
 		xhci_debugfs_exit(xhci);
 
 		xhci_init(hcd);
 
+		/* Re-arm the MSI/MSI-X delivery path for RESET_ON_RESUME PCI
+		 * hosts. xhci_run() no longer does this (it was moved to the
+		 * probe-only xhci_pci_run()), and the stale vectors left over
+		 * from before suspend cannot carry the first post-resume
+		 * command-completion event on affected hardware.
+		 */
+		if ((xhci->quirks & XHCI_RESET_ON_RESUME) &&
+		    dev_is_pci(hcd->self.controller))
+			xhci_try_enable_msi(hcd);
+
 		/*
 		 * USB core calls the PCI reinit and start functions twice:
 		 * first with the primary HCD, and then with the secondary HCD.
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 2d3941b5e1e3..a72ebfbb634a 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1903,6 +1903,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume);
 
 irqreturn_t xhci_irq(struct usb_hcd *hcd);
 irqreturn_t xhci_msi_irq(int irq, void *hcd);
+void xhci_cleanup_msix(struct xhci_hcd *xhci);
+int xhci_try_enable_msi(struct usb_hcd *hcd);
 int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev);
 int xhci_alloc_tt_info(struct xhci_hcd *xhci,
 		struct xhci_virt_device *virt_dev,
-- 
2.25.1


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

* Re: [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts
  2026-07-14  9:02 [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts Jie Deng
@ 2026-07-27 14:19 ` Mathias Nyman
  2026-07-30  2:24   ` Jie Deng
  0 siblings, 1 reply; 6+ messages in thread
From: Mathias Nyman @ 2026-07-27 14:19 UTC (permalink / raw)
  To: Jie Deng, mathias.nyman; +Cc: linux-usb, gregkh, linux-kernel

Hi

On 7/14/26 12:02, Jie Deng wrote:
> Commit 944e7deb4238 ("xhci: Avoid PCI MSI/MSIX interrupt
> reinitialization at resume") moved MSI/MSI-X setup out of xhci_run()
> into a PCI-specific xhci_pci_run() that is only invoked at probe time,
> and removed the xhci_cleanup_msix() call from xhci_resume().
> 
> The rationale (avoid redundant MSI reconfiguration on every resume) is
> sound for controllers that preserve state across suspend.  It is however
> *harmful* for controllers carrying XHCI_RESET_ON_RESUME: those hosts are
> fully reset on every S3 resume, and on some of them (e.g. ASMedia 3042)
> the MSI/MSI-X delivery path is no longer functional after the controller
> reset + D3->D0 transition.  Because the MSI vectors are now kept around
> unchanged across resume, the first post-resume command-completion event
> (ENABLE_SLOT) is delivered to a stale MSI channel and never reaches the
> CPU, which surfaces as:
>    xhci_hcd 0000:05:00.0: Error while assigning device slot ID: Command Aborted
>    xhci_hcd 0000:05:00.0: Max number of devices this xHCI host supports is 127.
>    usb 1-2: device not accepting address 3, error -22
>    xhci_hcd 0000:05:00.0: Error while assigning device slot ID: Command Aborted
>    xhci_hcd 0000:05:00.0: Max number of devices this xHCI host supports is 127.
>    usb 1-2: device not accepting address 3, error -22
>    xhci_hcd 0000:05:00.0: Error while assigning device slot ID: Command Aborted
>    xhci_hcd 0000:05:00.0: Max number of devices this xHCI host supports is 127.
>    usb 2-2: device not accepting address 3, error -22
> 

Thanks for reporting and debugging this.

Is this also an issue in runtime resume where system stays in S0 while
xHC transitions from D3 to D0, and is then reset?

Or is it only in system suspend, or in hibernate?
Does it matter if xHC was in D3hot or D3cold before resume?

Not sure if gating with XHCI_RESET_ON_RESUME is the right way as some of those
xHCI PCI hosts may just need to be reset in resume, but retain their MSI settings.
(xhci specs states that resetting xHC should not touch PCI config space)

This may just be a ASMedia PCI xHCI issue.


> Up to v6.3 the resume reset path did xhci_cleanup_msix() and, through
> xhci_run() -> xhci_try_enable_msi(), re-allocated the vectors, which
> incidentally re-armed the MSI delivery path and masked the hardware
> issue.  Work it around by restoring that behaviour, but only for hosts
> marked XHCI_RESET_ON_RESUME and only for PCI devices (platform/RCAR
> hosts using the same quirk must not be touched).
> 
> Fix: 944e7deb4238 ("xhci: Avoid PCI MSI/MSIX interrupt reinitialization at resume")
> Signed-off-by: Jie Deng <dengjie03@kylinos.cn>
> ---
>   drivers/usb/host/xhci-pci.c |  6 ++++--
>   drivers/usb/host/xhci.c     | 19 +++++++++++++++++++
>   drivers/usb/host/xhci.h     |  2 ++
>   3 files changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index 6b3fcba44b08..77b3215c95f3 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -126,7 +126,7 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
>   }
>   
>   /* Legacy IRQ is freed by usb_remove_hcd() or usb_hcd_pci_shutdown() */
> -static void xhci_cleanup_msix(struct xhci_hcd *xhci)
> +void xhci_cleanup_msix(struct xhci_hcd *xhci)
>   {
>   	struct usb_hcd *hcd = xhci_to_hcd(xhci);
>   	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
> @@ -138,9 +138,10 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
>   	pci_free_irq_vectors(pdev);
>   	hcd->msix_enabled = 0;
>   }
> +EXPORT_SYMBOL_GPL(xhci_cleanup_msix);
>   
>   /* Try enabling MSI-X with MSI and legacy IRQ as fallback */
> -static int xhci_try_enable_msi(struct usb_hcd *hcd)
> +int xhci_try_enable_msi(struct usb_hcd *hcd)
>   {
>   	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
>   	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> @@ -207,6 +208,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
>   	hcd->irq = pdev->irq;
>   	return 0;
>   }
> +EXPORT_SYMBOL_GPL(xhci_try_enable_msi);
>   
>   static int xhci_pci_run(struct usb_hcd *hcd)
>   {
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 091c82ca8ee2..7dd3afcf6b2e 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -1190,10 +1190,29 @@ int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume)
>   		xhci_for_each_ring_seg(xhci->cmd_ring->first_seg, seg)
>   			memset(seg->trbs, 0, sizeof(union xhci_trb) * TRBS_PER_SEGMENT);
>   
> +		/* XHCI_RESET_ON_RESUME hosts are fully reset on every resume.
> +		 * On some of them (e.g. ASMedia 3042) the MSI/MSI-X delivery
> +		 * path is no longer valid after the reset + D3->D0 cycle, so
> +		 * tear the vectors down here and let xhci_try_enable_msi()
> +		 * re-allocate them below, matching pre-6.4 behaviour.
> +		 */
> +		if (xhci->quirks & XHCI_RESET_ON_RESUME)
> +			xhci_cleanup_msix(xhci);

Ideally all PCI related xHCI code should be done in xhci-pci.c, like xhci_pci_resume()

In this case it's a bit tricky as msi cleanup and enabling is done mid xhci_resume(),
and would require a lot of refactoring to get it done.

Might need to do it this way first to get the ASMedia host working, and then refactor later.

> +
>   		xhci_debugfs_exit(xhci);
>   
>   		xhci_init(hcd);
>   
> +		/* Re-arm the MSI/MSI-X delivery path for RESET_ON_RESUME PCI
> +		 * hosts. xhci_run() no longer does this (it was moved to the
> +		 * probe-only xhci_pci_run()), and the stale vectors left over
> +		 * from before suspend cannot carry the first post-resume
> +		 * command-completion event on affected hardware.
> +		 */
> +		if ((xhci->quirks & XHCI_RESET_ON_RESUME) &&
> +		    dev_is_pci(hcd->self.controller))
> +			xhci_try_enable_msi(hcd);

Same comment as above

Thanks
Mathias


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

* Re: [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts
  2026-07-27 14:19 ` Mathias Nyman
@ 2026-07-30  2:24   ` Jie Deng
  2026-07-30  4:48     ` Michal Pecio
  0 siblings, 1 reply; 6+ messages in thread
From: Jie Deng @ 2026-07-30  2:24 UTC (permalink / raw)
  To: Mathias Nyman, mathias.nyman; +Cc: linux-usb, gregkh, linux-kernel


在 2026/7/27 22:19, Mathias Nyman 写道:
Sorry for the late reply. I've been conducting tests and validations 
these days.
> Is this also an issue in runtime resume where system stays in S0 while
> xHC transitions from D3 to D0, and is then reset?
Runtime PM is not practically triggerable on this desktop setup,
but code inspection shows runtime resume also goes through
xhci_resume() with reset_registers=true for XHCI_RESET_ON_RESUME hosts.
>
> Or is it only in system suspend, or in hibernate?
> Does it matter if xHC was in D3hot or D3cold before resume?
We conducted 1000 tests on Hibernate and did not observe the problem 
recurring.
When it is suspended, both xHC D3hot and D3clod can reproduce the problem.
>
> Not sure if gating with XHCI_RESET_ON_RESUME is the right way as some 
> of those
> xHCI PCI hosts may just need to be reset in resume, but retain their 
> MSI settings.
> (xhci specs states that resetting xHC should not touch PCI config space)
>
> This may just be a ASMedia PCI xHCI issue. 
Additionally, I was able to reproduce the problem using the Renesas 
uPD720201 controller as well.

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

* Re: [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts
  2026-07-30  2:24   ` Jie Deng
@ 2026-07-30  4:48     ` Michal Pecio
  2026-07-31  7:38       ` Jie Deng
  0 siblings, 1 reply; 6+ messages in thread
From: Michal Pecio @ 2026-07-30  4:48 UTC (permalink / raw)
  To: Jie Deng; +Cc: Mathias Nyman, mathias.nyman, linux-usb, gregkh, linux-kernel

To avoid putting PCI-specific code in xhci.c, I wonder if it would
still work if the disable/enable cycle is done by xhci_pci_resume()
before calling xhci_resume()?

On Thu, 30 Jul 2026 10:24:05 +0800, Jie Deng wrote:
> Runtime PM is not practically triggerable on this desktop setup,
> but code inspection shows runtime resume also goes through
> xhci_resume() with reset_registers=true for XHCI_RESET_ON_RESUME
> hosts.

Resetting at runtime resume sounds like an odd thing to do, maybe
runtime suspend should be rejected then. But this is unrelated...

> We conducted 1000 tests on Hibernate and did not observe the problem 
> recurring.
> When it is suspended, both xHC D3hot and D3clod can reproduce the
> problem.

> Additionally, I was able to reproduce the problem using the Renesas 
> uPD720201 controller as well.

I wonder if it's an issue with those chips or a general PCIe or IRQ
resume bug in some particular host system? It looks like nobody else
complained about this old patch for three years.

I don't have ASM3042, but I do have ASM1042, ASM1142, ASM3142 and
also uPD720200, uPD720201 (rarely available for testing), uPD720202.
To be honest, I have never seen lost IRQs after resume here.

How often is this supposed to happen, how exactly is it reproduced?

Regards,
Michal

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

* Re: [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts
  2026-07-30  4:48     ` Michal Pecio
@ 2026-07-31  7:38       ` Jie Deng
  2026-07-31 10:57         ` Michal Pecio
  0 siblings, 1 reply; 6+ messages in thread
From: Jie Deng @ 2026-07-31  7:38 UTC (permalink / raw)
  To: Michal Pecio
  Cc: Mathias Nyman, mathias.nyman, linux-usb, gregkh, linux-kernel

Thank you for your reply.

在 2026/7/30 12:48, Michal Pecio 写道:
> To avoid putting PCI-specific code in xhci.c, I wonder if it would
> still work if the disable/enable cycle is done by xhci_pci_resume()
> before calling xhci_resume()?
The architecture is indeed cleaner. I will reply to you after conducting 
the test.
> I wonder if it's an issue with those chips or a general PCIe or IRQ
> resume bug in some particular host system? It looks like nobody else
> complained about this old patch for three years.
>
> I don't have ASM3042, but I do have ASM1042, ASM1142, ASM3142 and
> also uPD720200, uPD720201 (rarely available for testing), uPD720202.
> To be honest, I have never seen lost IRQs after resume here.
I was testing the S3 reproducibility issue on the ARM64 platform
  (uPD720201 requires manually adding the XHCI_RESET_ON_RESUME quirk).
  Next, I will conduct a comparison verification on the x86 platform,
  which will take some time.
> How often is this supposed to happen, how exactly is it reproduced?
Approximately 200 iterations of S3 were needed to consistently reproduce 
the issue.
The S3 test script is as follows:
#! /bin/bash
#
for i in $(seq 1 $1); do
     echo "the $i th s3" > /dev/ttyAMA0
     echo "the $i th s3"
     rtcwake -m mem -s 20
     sleep 15
done

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

* Re: [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts
  2026-07-31  7:38       ` Jie Deng
@ 2026-07-31 10:57         ` Michal Pecio
  0 siblings, 0 replies; 6+ messages in thread
From: Michal Pecio @ 2026-07-31 10:57 UTC (permalink / raw)
  To: Jie Deng; +Cc: Mathias Nyman, mathias.nyman, linux-usb, gregkh, linux-kernel

On Fri, 31 Jul 2026 15:38:22 +0800, Jie Deng wrote:
> The S3 test script is as follows:
> #! /bin/bash
> #
> for i in $(seq 1 $1); do
>      echo "the $i th s3" > /dev/ttyAMA0
>      echo "the $i th s3"
>      rtcwake -m mem -s 20
>      sleep 15
> done

That's simple enough, I could run it for a few hours on x86 PC with
a few different PCIe xHCI cards.

Just in case, are some USB devices supposed to be connected, or not
connected, or maybe it's known to make no difference?

You mentioned that the problem occurs both in D3cold and D3hot, on
my system I'm not sure if D3hot is possible with S3 so I would end
up with D3cold or use s2idle instead of S3.

I recall that in D3cold most of my PCIe cards don't supply AUX power
to the xHCI. Was AUX power supplied to these chips in your tests?
If so, I may be forced to use s2idle. Or maybe will just try both.

Regards,
Michal

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

end of thread, other threads:[~2026-07-31 10:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14  9:02 [PATCH] usb: xhci: Restore MSI/MSI-X reinitialization on resume for RESET_ON_RESUME hosts Jie Deng
2026-07-27 14:19 ` Mathias Nyman
2026-07-30  2:24   ` Jie Deng
2026-07-30  4:48     ` Michal Pecio
2026-07-31  7:38       ` Jie Deng
2026-07-31 10:57         ` Michal Pecio

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