Commit 58e21f73 authored by Sarah Sharp's avatar Sarah Sharp

xhci: Set L1 device slot on USB2 LPM enable/disable.

To enable USB 2.0 Link Power Management (LPM), the xHCI host controller
needs the device slot ID to generate the device address used in L1 entry
tokens.  That information is set in the L1 device slot ID field of the
USB 2.0 LPM registers.

Currently, the L1 device slot ID is overwritten when the xHCI driver
initiates the software test of USB 2.0 Link PM in
xhci_usb2_software_lpm_test.  It is never cleared when USB 2.0 Link PM
is disabled for the device.  That should be harmless, because the
Hardware LPM Enable (HLE) bit is cleared when USB 2.0 Link PM is
disabled, so the host should not pay attention to the slot ID.

This patch should have no effect on host behavior, but since
xhci_usb2_software_lpm_test is going away in an upcoming bug fix patch,
we need to move that code to the function that enables and disables USB
2.0 Link PM.

This patch should be backported to kernels as old as 3.11, that contain
the commit a558ccdc "usb: xhci: add USB2
Link power management BESL support".  The upcoming bug fix patch is also
marked for that stable kernel.
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: stable@vger.kernel.org
parent dcc01c08
...@@ -4216,7 +4216,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, ...@@ -4216,7 +4216,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
} }
pm_val &= ~PORT_HIRD_MASK; pm_val &= ~PORT_HIRD_MASK;
pm_val |= PORT_HIRD(hird) | PORT_RWE; pm_val |= PORT_HIRD(hird) | PORT_RWE | PORT_L1DS(udev->slot_id);
xhci_writel(xhci, pm_val, pm_addr); xhci_writel(xhci, pm_val, pm_addr);
pm_val = xhci_readl(xhci, pm_addr); pm_val = xhci_readl(xhci, pm_addr);
pm_val |= PORT_HLE; pm_val |= PORT_HLE;
...@@ -4224,7 +4224,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, ...@@ -4224,7 +4224,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
/* flush write */ /* flush write */
xhci_readl(xhci, pm_addr); xhci_readl(xhci, pm_addr);
} else { } else {
pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK | PORT_L1DS_MASK);
xhci_writel(xhci, pm_val, pm_addr); xhci_writel(xhci, pm_val, pm_addr);
/* flush write */ /* flush write */
xhci_readl(xhci, pm_addr); xhci_readl(xhci, pm_addr);
......
...@@ -383,6 +383,7 @@ struct xhci_op_regs { ...@@ -383,6 +383,7 @@ struct xhci_op_regs {
#define PORT_RWE (1 << 3) #define PORT_RWE (1 << 3)
#define PORT_HIRD(p) (((p) & 0xf) << 4) #define PORT_HIRD(p) (((p) & 0xf) << 4)
#define PORT_HIRD_MASK (0xf << 4) #define PORT_HIRD_MASK (0xf << 4)
#define PORT_L1DS_MASK (0xff << 8)
#define PORT_L1DS(p) (((p) & 0xff) << 8) #define PORT_L1DS(p) (((p) & 0xff) << 8)
#define PORT_HLE (1 << 16) #define PORT_HLE (1 << 16)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment