Commit 063ebeb4 authored by Sarah Sharp's avatar Sarah Sharp

xhci: Report USB 2.1 link status for L1

USB 2.1 devices can go into a lower power link state, L1.  When they are
active, they are in the L0 state.  The L1 transition can be purely
driven by software, or some USB host controllers (including some xHCI
1.0 hosts) allow the host hardware to track idleness and automatically
place a port into L1.

The USB 2.1 Link Power Management ECN gives a way for USB 2.1 hubs that
support LPM to report that a port is in L1.  The port status bit 5 will
be set when the port is in L1.  The xHCI host reports the root port as
being in 'U2' when the devices is in L1, and as being in 'U0' when the
port is active (in L0).

Translate the xHCI USB 2.1 link status into the format external hubs
use, and pass the L1 status up to the USB core and tools like lsusb.
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
parent eae5b176
...@@ -461,8 +461,15 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, ...@@ -461,8 +461,15 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
} }
} }
/* Updates Link Status for USB 2.1 port */
static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg)
{
if ((status_reg & PORT_PLS_MASK) == XDEV_U2)
*status |= USB_PORT_STAT_L1;
}
/* Updates Link Status for super Speed port */ /* Updates Link Status for super Speed port */
static void xhci_hub_report_link_state(u32 *status, u32 status_reg) static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg)
{ {
u32 pls = status_reg & PORT_PLS_MASK; u32 pls = status_reg & PORT_PLS_MASK;
...@@ -631,14 +638,16 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, ...@@ -631,14 +638,16 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
else else
status |= USB_PORT_STAT_POWER; status |= USB_PORT_STAT_POWER;
} }
/* Update Port Link State for super speed ports*/ /* Update Port Link State */
if (hcd->speed == HCD_USB3) { if (hcd->speed == HCD_USB3) {
xhci_hub_report_link_state(&status, raw_port_status); xhci_hub_report_usb3_link_state(&status, raw_port_status);
/* /*
* Verify if all USB3 Ports Have entered U0 already. * Verify if all USB3 Ports Have entered U0 already.
* Delete Compliance Mode Timer if so. * Delete Compliance Mode Timer if so.
*/ */
xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex); xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex);
} else {
xhci_hub_report_usb2_link_state(&status, raw_port_status);
} }
if (bus_state->port_c_suspend & (1 << wIndex)) if (bus_state->port_c_suspend & (1 << wIndex))
status |= 1 << USB_PORT_FEAT_C_SUSPEND; status |= 1 << USB_PORT_FEAT_C_SUSPEND;
......
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