Skip to content

Commit f217c98

Browse files
author
Sarah Sharp
committed
xhci: Don't enable/disable RWE on bus suspend/resume.
The RWE bit of the USB 2.0 PORTPMSC register is supposed to enable remote wakeup for devices in the lower power link state L1. It has nothing to do with the device suspend remote wakeup from L2. The RWE bit is designed to be set once (when USB 2.0 LPM is enabled for the port) and cleared only when USB 2.0 LPM is disabled for the port. The xHCI bus suspend method was setting the RWE bit erroneously, and the bus resume method was clearing it. The xHCI 1.0 specification with errata up to Aug 12, 2012 says in section 4.23.5.1.1.1 "Hardware Controlled LPM": "While Hardware USB2 LPM is enabled, software shall not modify the HIRDBESL or RWE fields of the USB2 PORTPMSC register..." If we have previously enabled USB 2.0 LPM for a device, that means when the USB 2.0 bus is resumed, we violate the xHCI specification by clearing RWE. It also means that after a bus resume, the host would think remote wakeup is disabled from L1 for ports with USB 2.0 Link PM enabled, which is not what we want. This patch should be backported to kernels as old as 3.2, that contain the commit 65580b4 "xHCI: set USB2 hardware LPM". That was the first kernel that supported USB 2.0 Link PM. Signed-off-by: Sarah Sharp <[email protected]> Cc: [email protected]
1 parent d0e639c commit f217c98

File tree

1 file changed

+0
-26
lines changed

1 file changed

+0
-26
lines changed

drivers/usb/host/xhci-hub.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,18 +1157,6 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
11571157
t1 = xhci_port_state_to_neutral(t1);
11581158
if (t1 != t2)
11591159
xhci_writel(xhci, t2, port_array[port_index]);
1160-
1161-
if (hcd->speed != HCD_USB3) {
1162-
/* enable remote wake up for USB 2.0 */
1163-
__le32 __iomem *addr;
1164-
u32 tmp;
1165-
1166-
/* Get the port power control register address. */
1167-
addr = port_array[port_index] + PORTPMSC;
1168-
tmp = xhci_readl(xhci, addr);
1169-
tmp |= PORT_RWE;
1170-
xhci_writel(xhci, tmp, addr);
1171-
}
11721160
}
11731161
hcd->state = HC_STATE_SUSPENDED;
11741162
bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
@@ -1247,20 +1235,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)
12471235
xhci_ring_device(xhci, slot_id);
12481236
} else
12491237
xhci_writel(xhci, temp, port_array[port_index]);
1250-
1251-
if (hcd->speed != HCD_USB3) {
1252-
/* disable remote wake up for USB 2.0 */
1253-
__le32 __iomem *addr;
1254-
u32 tmp;
1255-
1256-
/* Add one to the port status register address to get
1257-
* the port power control register address.
1258-
*/
1259-
addr = port_array[port_index] + PORTPMSC;
1260-
tmp = xhci_readl(xhci, addr);
1261-
tmp &= ~PORT_RWE;
1262-
xhci_writel(xhci, tmp, addr);
1263-
}
12641238
}
12651239

12661240
(void) xhci_readl(xhci, &xhci->op_regs->command);

0 commit comments

Comments
 (0)