Skip to content

Commit 253f588

Browse files
matnymangregkh
authored andcommitted
xhci: Improve detection of device initiated wake signal.
A xHC USB 3 port might miss the first wake signal from a USB 3 device if the port LFPS reveiver isn't enabled fast enough after xHC resume. xHC host will anyway be resumed by a PME# signal, but will go back to suspend if no port activity is seen. The device resends the U3 LFPS wake signal after a 100ms delay, but by then host is already suspended, starting all over from the beginning of this issue. USB 3 specs say U3 wake LFPS signal is sent for max 10ms, then device needs to delay 100ms before resending the wake. Don't suspend immediately if port activity isn't detected in resume. Instead add a retry. If there is no port activity then delay for 120ms, and re-check for port activity. Cc: <stable@vger.kernel.org> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20210311115353.2137560-3-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent a4a251f commit 253f588

1 file changed

Lines changed: 13 additions & 3 deletions

File tree

drivers/usb/host/xhci.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
10881088
struct usb_hcd *secondary_hcd;
10891089
int retval = 0;
10901090
bool comp_timer_running = false;
1091+
bool pending_portevent = false;
10911092

10921093
if (!hcd->state)
10931094
return 0;
@@ -1226,13 +1227,22 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
12261227

12271228
done:
12281229
if (retval == 0) {
1229-
/* Resume root hubs only when have pending events. */
1230-
if (xhci_pending_portevent(xhci)) {
1230+
/*
1231+
* Resume roothubs only if there are pending events.
1232+
* USB 3 devices resend U3 LFPS wake after a 100ms delay if
1233+
* the first wake signalling failed, give it that chance.
1234+
*/
1235+
pending_portevent = xhci_pending_portevent(xhci);
1236+
if (!pending_portevent) {
1237+
msleep(120);
1238+
pending_portevent = xhci_pending_portevent(xhci);
1239+
}
1240+
1241+
if (pending_portevent) {
12311242
usb_hcd_resume_root_hub(xhci->shared_hcd);
12321243
usb_hcd_resume_root_hub(hcd);
12331244
}
12341245
}
1235-
12361246
/*
12371247
* If system is subject to the Quirk, Compliance Mode Timer needs to
12381248
* be re-initialized Always after a system resume. Ports are subject

0 commit comments

Comments
 (0)