Skip to content

Commit a49e1e2

Browse files
matnymangregkh
authored andcommitted
usb: hub: Fix flushing and scheduling of delayed work that tunes runtime pm
Delayed work to prevent USB3 hubs from runtime-suspending immediately after resume was added in commit 8f5b7e2 ("usb: hub: fix detection of high tier USB3 devices behind suspended hubs"). This delayed work needs be flushed if system suspends, or hub needs to be quiesced for other reasons right after resume. Not flushing it triggered issues on QC SC8280XP CRD board during suspend/resume testing. Fix it by flushing the delayed resume work in hub_quiesce() The delayed work item that allow hub runtime suspend is also scheduled just before calling autopm get. Alan pointed out there is a small risk that work is run before autopm get, which would call autopm put before get, and mess up the runtime pm usage order. Swap the order of work sheduling and calling autopm get to solve this. Cc: stable <[email protected]> Fixes: 8f5b7e2 ("usb: hub: fix detection of high tier USB3 devices behind suspended hubs") Reported-by: Konrad Dybcio <[email protected]> Closes: https://lore.kernel.org/linux-usb/[email protected] Reported-by: Alan Stern <[email protected]> Closes: https://lore.kernel.org/linux-usb/[email protected] Signed-off-by: Mathias Nyman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 099cf1f commit a49e1e2

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

drivers/usb/core/hub.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,11 +1359,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
13591359

13601360
if (type == HUB_RESUME && hub_is_superspeed(hub->hdev)) {
13611361
/* give usb3 downstream links training time after hub resume */
1362+
usb_autopm_get_interface_no_resume(
1363+
to_usb_interface(hub->intfdev));
1364+
13621365
INIT_DELAYED_WORK(&hub->init_work, hub_post_resume);
13631366
queue_delayed_work(system_power_efficient_wq, &hub->init_work,
13641367
msecs_to_jiffies(USB_SS_PORT_U0_WAKE_TIME));
1365-
usb_autopm_get_interface_no_resume(
1366-
to_usb_interface(hub->intfdev));
13671368
return;
13681369
}
13691370

@@ -1417,6 +1418,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
14171418

14181419
/* Stop hub_wq and related activity */
14191420
timer_delete_sync(&hub->irq_urb_retry);
1421+
flush_delayed_work(&hub->init_work);
14201422
usb_kill_urb(hub->urb);
14211423
if (hub->has_indicators)
14221424
cancel_delayed_work_sync(&hub->leds);

0 commit comments

Comments
 (0)