xhci: A default implementation for Ux timeout calculation and tier policy check
authorPratyush Anand <pratyush.anand@st.com>
Fri, 4 Jul 2014 14:01:23 +0000 (17:01 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Jul 2014 22:41:34 +0000 (15:41 -0700)
As best case, a host controller should support U0 to U1 switching for
the devices connected below any tier of hub level supported by usb
specification. Therefore xhci_check_tier_policy should always return
success as default implementation.

A host should be able to issue LGO_Ux after the timeout calculated as
per definition of system exit latency defined in C.1.5.2. Therefore
xhci_calculate_ux_timeout returns ux_params.sel as the default
implementation.

Use default calculation in absence of any vendor specific limitations.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
Tested-by: Aymen Bouattay <aymen.bouattay@st.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci.c

index f07be65b4e70252715e50fe19d495d3f61155f97..b04fef1e4ff84b3c6c87f33c9c2fde9a5d90cb7f 100644 (file)
@@ -4288,8 +4288,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
        return USB3_LPM_DISABLED;
 }
 
-/* Returns the hub-encoded U1 timeout value.
- * The U1 timeout should be the maximum of the following values:
+/* The U1 timeout should be the maximum of the following values:
  *  - For control endpoints, U1 system exit latency (SEL) * 3
  *  - For bulk endpoints, U1 SEL * 5
  *  - For interrupt endpoints:
@@ -4297,7 +4296,8 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
  *    - Periodic EPs, max(105% of bInterval, U1 SEL * 2)
  *  - For isochronous endpoints, max(105% of bInterval, U1 SEL * 2)
  */
-static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
+static unsigned long long xhci_calculate_intel_u1_timeout(
+               struct usb_device *udev,
                struct usb_endpoint_descriptor *desc)
 {
        unsigned long long timeout_ns;
@@ -4329,11 +4329,28 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
                return 0;
        }
 
-       /* The U1 timeout is encoded in 1us intervals. */
-       timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000);
-       /* Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */
+       return timeout_ns;
+}
+
+/* Returns the hub-encoded U1 timeout value. */
+static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
+               struct usb_device *udev,
+               struct usb_endpoint_descriptor *desc)
+{
+       unsigned long long timeout_ns;
+
+       if (xhci->quirks & XHCI_INTEL_HOST)
+               timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
+       else
+               timeout_ns = udev->u1_params.sel;
+
+       /* The U1 timeout is encoded in 1us intervals.
+        * Don't return a timeout of zero, because that's USB3_LPM_DISABLED.
+        */
        if (timeout_ns == USB3_LPM_DISABLED)
-               timeout_ns++;
+               timeout_ns = 1;
+       else
+               timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000);
 
        /* If the necessary timeout value is bigger than what we can set in the
         * USB 3.0 hub, we have to disable hub-initiated U1.
@@ -4345,14 +4362,14 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
        return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U1);
 }
 
-/* Returns the hub-encoded U2 timeout value.
- * The U2 timeout should be the maximum of:
+/* The U2 timeout should be the maximum of:
  *  - 10 ms (to avoid the bandwidth impact on the scheduler)
  *  - largest bInterval of any active periodic endpoint (to avoid going
  *    into lower power link states between intervals).
  *  - the U2 Exit Latency of the device
  */
-static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
+static unsigned long long xhci_calculate_intel_u2_timeout(
+               struct usb_device *udev,
                struct usb_endpoint_descriptor *desc)
 {
        unsigned long long timeout_ns;
@@ -4368,6 +4385,21 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
        if (u2_del_ns > timeout_ns)
                timeout_ns = u2_del_ns;
 
+       return timeout_ns;
+}
+
+/* Returns the hub-encoded U2 timeout value. */
+static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
+               struct usb_device *udev,
+               struct usb_endpoint_descriptor *desc)
+{
+       unsigned long long timeout_ns;
+
+       if (xhci->quirks & XHCI_INTEL_HOST)
+               timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
+       else
+               timeout_ns = udev->u2_params.sel;
+
        /* The U2 timeout is encoded in 256us intervals */
        timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000);
        /* If the necessary timeout value is bigger than what we can set in the
@@ -4386,13 +4418,10 @@ static u16 xhci_call_host_update_timeout_for_endpoint(struct xhci_hcd *xhci,
                enum usb3_link_state state,
                u16 *timeout)
 {
-       if (state == USB3_LPM_U1) {
-               if (xhci->quirks & XHCI_INTEL_HOST)
-                       return xhci_calculate_intel_u1_timeout(udev, desc);
-       } else {
-               if (xhci->quirks & XHCI_INTEL_HOST)
-                       return xhci_calculate_intel_u2_timeout(udev, desc);
-       }
+       if (state == USB3_LPM_U1)
+               return xhci_calculate_u1_timeout(xhci, udev, desc);
+       else if (state == USB3_LPM_U2)
+               return xhci_calculate_u2_timeout(xhci, udev, desc);
 
        return USB3_LPM_DISABLED;
 }
@@ -4469,7 +4498,8 @@ static int xhci_check_tier_policy(struct xhci_hcd *xhci,
 {
        if (xhci->quirks & XHCI_INTEL_HOST)
                return xhci_check_intel_tier_policy(udev, state);
-       return -EINVAL;
+       else
+               return 0;
 }
 
 /* Returns the U1 or U2 timeout that should be enabled.