I run Manjaro btw.
]]>"Don't let USB3 ports stuck in polling state prevent suspend"
]]>First execute lsusb.py to find the device that causes the problem.
For me it was a xhci host controller with no devices attached:
usb2 1d6b:0003 09 3.00 5000MBit/s 0mA 1IF (Linux 5.0.0-arch1-1-ARCH xhci-hcd xHCI Host Controller 0000:00:14.0) hub
Remember the PCI ID (here 0000:00:14.0).
Create a file under /usr/lib/systemd/system-sleep/ e.g. 10-usb_suspend_workaround.sh and change PCI_DEV to match yours.
#!/bin/bash
PCI_DEV="0000:00:14.0"
case $1/$2 in
pre/*)
# echo "Going to $2..."
echo "$PCI_DEV" > /sys/bus/pci/drivers/xhci_hcd/unbind
;;
post/*)
# echo "Waking up from $2..."
echo "$PCI_DEV" > /sys/bus/pci/drivers/xhci_hcd/bind
;;
esac
Don't forget to chmod +x the file.
]]>$ echo 1 >/sys/bus/usb/devices/2-4/remove
and then all subsequent suspends work. It is far from ideal but HTH.
]]>diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 01b5818a4be5..da98a11244e2 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1474,18 +1474,15 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
unsigned long flags;
struct xhci_hub *rhub;
struct xhci_port **ports;
- u32 portsc_buf[USB_MAXCHILDREN];
- bool wake_enabled;
rhub = xhci_get_rhub(hcd);
ports = rhub->ports;
max_ports = rhub->num_ports;
bus_state = &xhci->bus_state[hcd_index(hcd)];
- wake_enabled = hcd->self.root_hub->do_remote_wakeup;
spin_lock_irqsave(&xhci->lock, flags);
- if (wake_enabled) {
+ if (hcd->self.root_hub->do_remote_wakeup) {
if (bus_state->resuming_ports || /* USB2 */
bus_state->port_remote_wakeup) { /* USB3 */
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -1493,37 +1490,26 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
return -EBUSY;
}
}
- /*
- * Prepare ports for suspend, but don't write anything before all ports
- * are checked and we know bus suspend can proceed
- */
- bus_state->bus_suspended = 0;
+
port_index = max_ports;
+ bus_state->bus_suspended = 0;
while (port_index--) {
+ /* suspend the port if the port is not suspended */
u32 t1, t2;
+ int slot_id;
t1 = readl(ports[port_index]->addr);
t2 = xhci_port_state_to_neutral(t1);
- portsc_buf[port_index] = 0;
-
- /* Bail out if a USB3 port has a new device in link training */
- if ((hcd->speed >= HCD_USB3) &&
- (t1 & PORT_PLS_MASK) == XDEV_POLLING) {
- bus_state->bus_suspended = 0;
- spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "Bus suspend bailout, port in polling\n");
- return -EBUSY;
- }
- /* suspend ports in U0, or bail out for new connect changes */
- if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
- if ((t1 & PORT_CSC) && wake_enabled) {
- bus_state->bus_suspended = 0;
+ if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
+ xhci_dbg(xhci, "port %d not suspended\n", port_index);
+ slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+ port_index + 1);
+ if (slot_id) {
spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "Bus suspend bailout, port connect change\n");
- return -EBUSY;
+ xhci_stop_device(xhci, slot_id, 1);
+ spin_lock_irqsave(&xhci->lock, flags);
}
- xhci_dbg(xhci, "port %d not suspended\n", port_index);
t2 &= ~PORT_PLS_MASK;
t2 |= PORT_LINK_STROBE | XDEV_U3;
set_bit(port_index, &bus_state->bus_suspended);
@@ -1532,7 +1518,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
* including the USB 3.0 roothub, but only if CONFIG_PM
* is enabled, so also enable remote wake here.
*/
- if (wake_enabled) {
+ if (hcd->self.root_hub->do_remote_wakeup) {
if (t1 & PORT_CONNECT) {
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
t2 &= ~PORT_WKCONN_E;
@@ -1552,26 +1538,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
t1 = xhci_port_state_to_neutral(t1);
if (t1 != t2)
- portsc_buf[port_index] = t2;
- }
-
- /* write port settings, stopping and suspending ports if needed */
- port_index = max_ports;
- while (port_index--) {
- if (!portsc_buf[port_index])
- continue;
- if (test_bit(port_index, &bus_state->bus_suspended)) {
- int slot_id;
-
- slot_id = xhci_find_slot_id_by_port(hcd, xhci,
- port_index + 1);
- if (slot_id) {
- spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_stop_device(xhci, slot_id, 1);
- spin_lock_irqsave(&xhci->lock, flags);
- }
- }
- writel(portsc_buf[port_index], ports[port_index]->addr);
+ writel(t2, ports[port_index]->addr);
}
hcd->state = HC_STATE_SUSPENDED;
bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
Manually adjusted revert for 4.20.6 (build tested only)
]]>There is obviously some kind of state change that isn't reset after the first suspend. I've tried reloading the following modules between suspends
usbhid, xhci_hcd, xhci_pci
but it doesn't seem to help.
]]>[ 87.281315] dpm_run_callback(): usb_dev_suspend+0x0/0x10 returns -16
[ 87.281318] PM: Device usb2 failed to suspend async: error -16 [ 87.316409] sd 0:0:0:0: [sda] Synchronizing SCSI cache [ 87.318809] sd 0:0:0:0: [sda] Stopping disk
[ 87.650193] PM: Some devices failed to suspend, or early wake event detected
works at first suspend but fails for the subsequent ones.
]]>Kernel version: 4.20.6-arch1-1
EDIT: Worked for like a week with multiple restarts, now its back.
]]>I do have the exact same Problems since 4.19.8 an still newest kernel 4.20.5-arch1-1-ARCH on my mbp. Tried everything I can imagine, but no look. Would be extremly grateful if someone would have an Idea on how to solve this.
Kind Regards
Michael