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: Sarah Sharp <sarah.a.sh...@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c |   15 ++++++++++++---
 1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 83fc636..93f3fdf 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -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 */
-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;
 
@@ -631,14 +638,16 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                else
                        status |= USB_PORT_STAT_POWER;
        }
-       /* Update Port Link State for super speed ports*/
+       /* Update Port Link State */
        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.
                 * Delete Compliance Mode Timer if so.
                 */
                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))
                status |= 1 << USB_PORT_FEAT_C_SUSPEND;
-- 
1.7.9

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to