* [PATCH] usb: core: raise root-hub autosuspend delay to stop a busy-loop
@ 2026-10-28 4:18 Jianping Liu
2026-10-30 2:23 ` Alan Stern
0 siblings, 1 reply; 4+ messages in thread
From: Jianping Liu @ 2026-10-28 4:18 UTC (permalink / raw)
To: gregkh, dakr, shashank.mahadasyam, johan, hadess, frankjpliu,
guanyulin, gary, rafael.j.wysocki
Cc: linux-kernel, linux-usb
From: Jianping Liu <frankjpliu@tencent.com>
hub_probe() sets the hub autosuspend delay to 0. An idle hub is
therefore suspended at once, with no waiting time.
Suspending the root hub can fail. While a port reports over-current
or a connect change, xHCI refuses the bus suspend and returns -EBUSY.
usb_runtime_suspend() returns that error. The hub is resumed, and when
its status URB completes the same suspend runs again.
The PM core would normally leave a gap before that next attempt. It
starts the autosuspend timer only when the delay is still in the
future. A delay of 0 is already due, so no timer is started and there
is nothing to wait for. Suspend and resume repeat immediately, and one
CPU core stays at 100% until the port is no longer stuck.
If a root-hub runtime suspend fails while the delay is still 0, set
the delay to 1000 ms so the next attempt waits. If a later runtime
suspend succeeds and the delay is not 0, put it back to 0.
Signed-off-by: Jianping Liu <frankjpliu@tencent.com>
---
drivers/usb/core/driver.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d3a61ebc6afb..30965d6ffd67 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -2008,6 +2008,20 @@ int usb_runtime_suspend(struct device *dev)
if (status == -EAGAIN || status == -EBUSY)
usb_mark_last_busy(udev);
+ /*
+ * Root hubs use 0ms delay, so a persistent -EBUSY retries with no
+ * wait and pins one CPU at 100%. Set autosuspend_delay to 1000ms
+ * on fail, then back to 0 ms on success.
+ */
+ if (!udev->parent) {
+ int delay = READ_ONCE(dev->power.autosuspend_delay);
+
+ if (unlikely(status != 0 && delay == 0))
+ pm_runtime_set_autosuspend_delay(dev, 1000);
+ if (unlikely(status == 0 && delay != 0))
+ pm_runtime_set_autosuspend_delay(dev, 0);
+ }
+
/*
* The PM core reacts badly unless the return code is 0,
* -EAGAIN, or -EBUSY, so always return -EBUSY on an error
--
2.43.7
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] usb: core: raise root-hub autosuspend delay to stop a busy-loop
2026-10-28 4:18 [PATCH] usb: core: raise root-hub autosuspend delay to stop a busy-loop Jianping Liu
@ 2026-10-30 2:23 ` Alan Stern
2026-11-02 11:25 ` frank jpliu
2026-11-02 13:34 ` Michal Pecio
0 siblings, 2 replies; 4+ messages in thread
From: Alan Stern @ 2026-10-30 2:23 UTC (permalink / raw)
To: Jianping Liu
Cc: gregkh, dakr, shashank.mahadasyam, johan, hadess, frankjpliu,
guanyulin, gary, rafael.j.wysocki, linux-kernel, linux-usb
On Wed, Oct 28, 2026 at 12:18:59PM +0800, Jianping Liu wrote:
> From: Jianping Liu <frankjpliu@tencent.com>
>
> hub_probe() sets the hub autosuspend delay to 0. An idle hub is
> therefore suspended at once, with no waiting time.
>
> Suspending the root hub can fail. While a port reports over-current
> or a connect change, xHCI refuses the bus suspend and returns -EBUSY.
> usb_runtime_suspend() returns that error. The hub is resumed, and when
> its status URB completes the same suspend runs again.
Why should root hubs be special? An ordinary hub doesn't refuse to
suspend because of an over-current or connect change. xhci-hcd ought to
behave the same way.
> The PM core would normally leave a gap before that next attempt. It
> starts the autosuspend timer only when the delay is still in the
> future. A delay of 0 is already due, so no timer is started and there
> is nothing to wait for. Suspend and resume repeat immediately, and one
> CPU core stays at 100% until the port is no longer stuck.
>
> If a root-hub runtime suspend fails while the delay is still 0, set
> the delay to 1000 ms so the next attempt waits. If a later runtime
> suspend succeeds and the delay is not 0, put it back to 0.
The concerns raised by Sashiko are valid. If people really want hubs
(or just root hubs) to have a positive autosuspend delay, it should be
set to a small value such as 100 ms. Not constantly alternating between
0 and 1000.
Furthermore, this can be controlled from userspace by writing to the
aprpopriate sysfs attribute file. The kernel doesn't need to be
involved.
Alan Stern
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] usb: core: raise root-hub autosuspend delay to stop a busy-loop
2026-10-30 2:23 ` Alan Stern
@ 2026-11-02 11:25 ` frank jpliu
2026-11-02 13:34 ` Michal Pecio
1 sibling, 0 replies; 4+ messages in thread
From: frank jpliu @ 2026-11-02 11:25 UTC (permalink / raw)
To: Alan Stern
Cc: gregkh, dakr, shashank.mahadasyam, johan, hadess, frankjpliu,
guanyulin, gary, rafael.j.wysocki, linux-kernel, linux-usb
On Fri, Oct 30, 2026 at 10:23 AM Alan Stern <stern@rowland.harvard.edu> wrote:
>
> On Wed, Oct 28, 2026 at 12:18:59PM +0800, Jianping Liu wrote:
> > From: Jianping Liu <frankjpliu@tencent.com>
> >
> > hub_probe() sets the hub autosuspend delay to 0. An idle hub is
> > therefore suspended at once, with no waiting time.
> >
> > Suspending the root hub can fail. While a port reports over-current
> > or a connect change, xHCI refuses the bus suspend and returns -EBUSY.
> > usb_runtime_suspend() returns that error. The hub is resumed, and when
> > its status URB completes the same suspend runs again.
>
> Why should root hubs be special? An ordinary hub doesn't refuse to
> suspend because of an over-current or connect change. xhci-hcd ought to
> behave the same way.
>
> > The PM core would normally leave a gap before that next attempt. It
> > starts the autosuspend timer only when the delay is still in the
> > future. A delay of 0 is already due, so no timer is started and there
> > is nothing to wait for. Suspend and resume repeat immediately, and one
> > CPU core stays at 100% until the port is no longer stuck.
> >
> > If a root-hub runtime suspend fails while the delay is still 0, set
> > the delay to 1000 ms so the next attempt waits. If a later runtime
> > suspend succeeds and the delay is not 0, put it back to 0.
>
> The concerns raised by Sashiko are valid. If people really want hubs
> (or just root hubs) to have a positive autosuspend delay, it should be
> set to a small value such as 100 ms. Not constantly alternating between
> 0 and 1000.
>
> Furthermore, this can be controlled from userspace by writing to the
> aprpopriate sysfs attribute file. The kernel doesn't need to be
> involved.
Makes sense, thanks for the explanation. I'll drop this patch and
won't pursue it further.
Thanks for your time and the review.
Best regards,
Frank
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] usb: core: raise root-hub autosuspend delay to stop a busy-loop
2026-10-30 2:23 ` Alan Stern
2026-11-02 11:25 ` frank jpliu
@ 2026-11-02 13:34 ` Michal Pecio
1 sibling, 0 replies; 4+ messages in thread
From: Michal Pecio @ 2026-11-02 13:34 UTC (permalink / raw)
To: Alan Stern
Cc: Jianping Liu, gregkh, dakr, shashank.mahadasyam, johan, hadess,
frankjpliu, guanyulin, gary, rafael.j.wysocki, linux-kernel,
linux-usb, Mathias Nyman
On Thu, 29 Oct 2026 22:23:02 -0400, Alan Stern wrote:
> On Wed, Oct 28, 2026 at 12:18:59PM +0800, Jianping Liu wrote:
> > From: Jianping Liu <frankjpliu@tencent.com>
> >
> > hub_probe() sets the hub autosuspend delay to 0. An idle hub is
> > therefore suspended at once, with no waiting time.
> >
> > Suspending the root hub can fail. While a port reports over-current
> > or a connect change, xHCI refuses the bus suspend and returns
> > -EBUSY. usb_runtime_suspend() returns that error. The hub is
> > resumed, and when its status URB completes the same suspend runs
> > again.
Yes, I have seen this ping-ponging before.
>
> Why should root hubs be special? An ordinary hub doesn't refuse to
> suspend because of an over-current or connect change. xhci-hcd ought
> to behave the same way.
IDK what happened there, but we have this:
commit e9fb08d617bfae5471d902112667d0eeb9dee3c4
Author: Mathias Nyman <mathias.nyman@linux.intel.com>
Date: Tue Apr 21 17:08:21 2020 +0300
xhci: prevent bus suspend if a roothub port detected a over-current condition
Suspending the bus and host controller while a port is in a over-current
condition may halt the host.
Also keep the roothub running if over-current is active.
Cc: <stable@vger.kernel.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20200421140822.28233-3-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Regards,
Michal
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-02 13:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-28 4:18 [PATCH] usb: core: raise root-hub autosuspend delay to stop a busy-loop Jianping Liu
2026-10-30 2:23 ` Alan Stern
2026-11-02 11:25 ` frank jpliu
2026-11-02 13:34 ` Michal Pecio
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®