* [PATCH v2] usb: ehci: Quiesce controller before halting it on shutdown
@ 2026-10-22 1:21 Joe Wang
2026-10-22 1:47 ` Alan Stern
0 siblings, 1 reply; 2+ messages in thread
From: Joe Wang @ 2026-10-22 1:21 UTC (permalink / raw)
To: Alan Stern, Greg Kroah-Hartman
Cc: linux-aspeed, linux-usb, linux-kernel, Joe Wang
ehci_shutdown() runs from the .shutdown callback during reboot,
poweroff and kexec, for example when LinuxBoot firmware boots the
final OS. The HCD is not removed in that path, so ehci_stop() is not
called and the controller may still be running. ehci_shutdown() then
halts it without first turning off the schedules, leaving a DMA master
running while the system shuts down.
On ASPEED EHCI controllers, clearing USBCMD.RS while both the periodic
and asynchronous schedules are enabled may also leave the controller
unable to halt. If an asynchronous transaction runs past the end of
the micro-frame after RS is cleared, the controller walks the periodic
schedule with a cleared internal buffer, reads from address 0x0 and
never sets USBSTS.HCHalted.
If the controller was running, call ehci_quiesce() before halting it,
as ehci_stop() and ehci_bus_suspend() already do. Do this after
rh_state is set to EHCI_RH_STOPPING, so that URB submissions and
hrtimer events cannot re-enable the schedules, and let ehci_quiesce()
accept that state: like EHCI_RH_RUNNING, it means the controller may
still be doing DMA. The controller-death path in ehci_irq() also sets
EHCI_RH_STOPPING, but it has already cleared CMD_RUN, CMD_ASE and
CMD_PSE, so a quiesce there cannot re-enable anything.
Signed-off-by: Joe Wang <joe_wang@aspeedtech.com>
---
This issue was observed on a customer host platform using the AST2700
PCIe EHCI (ehci-pci), and the root cause was confirmed by the ASPEED
hardware team in RTL simulation. The stop sequence used here (clear
PSE/ASE, wait for PSS/ASS to clear, then clear RS) is their
recommended workaround and was confirmed to resolve the issue on that
platform.
When the controller is running, the added delay at shutdown is bounded
by the two existing 16-uframe handshakes in ehci_quiesce().
Tested on AST2700 (ehci-platform): reboot with a hub and USB mass
storage under load, ehci_shutdown() on already halted controllers,
and unbind/bind (ehci_stop()); no regressions.
---
Changes in v2:
- Apply to all EHCI controllers, not only ASPEED (Alan)
- Quiesce only if the controller was running (Alan)
- Link to v1: https://lore.kernel.org/r/20261016-upstream_ehci_aspeed_shutdown-v1-1-8440c13b5652@aspeedtech.com
---
drivers/usb/host/ehci-hcd.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 3c46bb18c7f3..d9d816eedc66 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -274,7 +274,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
{
u32 temp;
- if (ehci->rh_state != EHCI_RH_RUNNING)
+ if (ehci->rh_state < EHCI_RH_RUNNING)
return;
/* wait for any schedule enables/disables to take effect */
@@ -356,6 +356,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
static void ehci_shutdown(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ bool was_running;
/**
* Protect the system from crashing at system shutdown in cases where
@@ -367,11 +368,19 @@ static void ehci_shutdown(struct usb_hcd *hcd)
return;
spin_lock_irq(&ehci->lock);
+ was_running = ehci->rh_state == EHCI_RH_RUNNING;
ehci->shutdown = true;
ehci->rh_state = EHCI_RH_STOPPING;
ehci->enabled_hrtimer_events = 0;
spin_unlock_irq(&ehci->lock);
+ /*
+ * Turn off the schedules before halting. rh_state is STOPPING now,
+ * so they cannot be re-enabled.
+ */
+ if (was_running)
+ ehci_quiesce(ehci);
+
ehci_silence_controller(ehci);
hrtimer_cancel(&ehci->hrtimer);
---
base-commit: 2f2f7eeef8b0a1a9b9ca998231419873ccae8d4e
change-id: 20261016-upstream_ehci_aspeed_shutdown-9ccffedb2a1c
Best regards,
--
Joe Wang <joe_wang@aspeedtech.com>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH v2] usb: ehci: Quiesce controller before halting it on shutdown
2026-10-22 1:21 [PATCH v2] usb: ehci: Quiesce controller before halting it on shutdown Joe Wang
@ 2026-10-22 1:47 ` Alan Stern
0 siblings, 0 replies; 2+ messages in thread
From: Alan Stern @ 2026-10-22 1:47 UTC (permalink / raw)
To: Joe Wang; +Cc: Greg Kroah-Hartman, linux-aspeed, linux-usb, linux-kernel
On Thu, Oct 22, 2026 at 09:21:11AM +0800, Joe Wang wrote:
> ehci_shutdown() runs from the .shutdown callback during reboot,
> poweroff and kexec, for example when LinuxBoot firmware boots the
> final OS. The HCD is not removed in that path, so ehci_stop() is not
> called and the controller may still be running. ehci_shutdown() then
> halts it without first turning off the schedules, leaving a DMA master
> running while the system shuts down.
>
> On ASPEED EHCI controllers, clearing USBCMD.RS while both the periodic
> and asynchronous schedules are enabled may also leave the controller
> unable to halt. If an asynchronous transaction runs past the end of
> the micro-frame after RS is cleared, the controller walks the periodic
> schedule with a cleared internal buffer, reads from address 0x0 and
> never sets USBSTS.HCHalted.
>
> If the controller was running, call ehci_quiesce() before halting it,
> as ehci_stop() and ehci_bus_suspend() already do. Do this after
> rh_state is set to EHCI_RH_STOPPING, so that URB submissions and
> hrtimer events cannot re-enable the schedules, and let ehci_quiesce()
> accept that state: like EHCI_RH_RUNNING, it means the controller may
> still be doing DMA. The controller-death path in ehci_irq() also sets
> EHCI_RH_STOPPING, but it has already cleared CMD_RUN, CMD_ASE and
> CMD_PSE, so a quiesce there cannot re-enable anything.
>
> Signed-off-by: Joe Wang <joe_wang@aspeedtech.com>
> ---
> This issue was observed on a customer host platform using the AST2700
> PCIe EHCI (ehci-pci), and the root cause was confirmed by the ASPEED
> hardware team in RTL simulation. The stop sequence used here (clear
> PSE/ASE, wait for PSS/ASS to clear, then clear RS) is their
> recommended workaround and was confirmed to resolve the issue on that
> platform.
>
> When the controller is running, the added delay at shutdown is bounded
> by the two existing 16-uframe handshakes in ehci_quiesce().
>
> Tested on AST2700 (ehci-platform): reboot with a hub and USB mass
> storage under load, ehci_shutdown() on already halted controllers,
> and unbind/bind (ehci_stop()); no regressions.
> ---
> Changes in v2:
> - Apply to all EHCI controllers, not only ASPEED (Alan)
> - Quiesce only if the controller was running (Alan)
> - Link to v1: https://lore.kernel.org/r/20261016-upstream_ehci_aspeed_shutdown-v1-1-8440c13b5652@aspeedtech.com
> ---
> drivers/usb/host/ehci-hcd.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
Acked-by: Alan Stern <stern@rowland.harvard.edu>
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index 3c46bb18c7f3..d9d816eedc66 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -274,7 +274,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
> {
> u32 temp;
>
> - if (ehci->rh_state != EHCI_RH_RUNNING)
> + if (ehci->rh_state < EHCI_RH_RUNNING)
> return;
>
> /* wait for any schedule enables/disables to take effect */
> @@ -356,6 +356,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
> static void ehci_shutdown(struct usb_hcd *hcd)
> {
> struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> + bool was_running;
>
> /**
> * Protect the system from crashing at system shutdown in cases where
> @@ -367,11 +368,19 @@ static void ehci_shutdown(struct usb_hcd *hcd)
> return;
>
> spin_lock_irq(&ehci->lock);
> + was_running = ehci->rh_state == EHCI_RH_RUNNING;
> ehci->shutdown = true;
> ehci->rh_state = EHCI_RH_STOPPING;
> ehci->enabled_hrtimer_events = 0;
> spin_unlock_irq(&ehci->lock);
>
> + /*
> + * Turn off the schedules before halting. rh_state is STOPPING now,
> + * so they cannot be re-enabled.
> + */
> + if (was_running)
> + ehci_quiesce(ehci);
> +
> ehci_silence_controller(ehci);
>
> hrtimer_cancel(&ehci->hrtimer);
>
> ---
> base-commit: 2f2f7eeef8b0a1a9b9ca998231419873ccae8d4e
> change-id: 20261016-upstream_ehci_aspeed_shutdown-9ccffedb2a1c
>
> Best regards,
> --
> Joe Wang <joe_wang@aspeedtech.com>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-22 1:47 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-22 1:21 [PATCH v2] usb: ehci: Quiesce controller before halting it on shutdown Joe Wang
2026-10-22 1:47 ` Alan Stern
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®