提交 9502c46c 编写于 作者: P Pratyush Anand 提交者: Greg Kroah-Hartman

xhci: A default implementation for Ux timeout calculation and tier policy check

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: NPratyush Anand <pratyush.anand@st.com>
Tested-by: NAymen Bouattay <aymen.bouattay@st.com>
Signed-off-by: NMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 ec5734c4
...@@ -4288,8 +4288,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, ...@@ -4288,8 +4288,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
return USB3_LPM_DISABLED; 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 control endpoints, U1 system exit latency (SEL) * 3
* - For bulk endpoints, U1 SEL * 5 * - For bulk endpoints, U1 SEL * 5
* - For interrupt endpoints: * - For interrupt endpoints:
...@@ -4297,7 +4296,8 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, ...@@ -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) * - Periodic EPs, max(105% of bInterval, U1 SEL * 2)
* - For isochronous endpoints, 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) struct usb_endpoint_descriptor *desc)
{ {
unsigned long long timeout_ns; unsigned long long timeout_ns;
...@@ -4329,11 +4329,28 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev, ...@@ -4329,11 +4329,28 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
return 0; return 0;
} }
/* The U1 timeout is encoded in 1us intervals. */ return timeout_ns;
timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000); }
/* Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */
/* 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) 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 /* 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. * 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, ...@@ -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); 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) * - 10 ms (to avoid the bandwidth impact on the scheduler)
* - largest bInterval of any active periodic endpoint (to avoid going * - largest bInterval of any active periodic endpoint (to avoid going
* into lower power link states between intervals). * into lower power link states between intervals).
* - the U2 Exit Latency of the device * - 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) struct usb_endpoint_descriptor *desc)
{ {
unsigned long long timeout_ns; unsigned long long timeout_ns;
...@@ -4368,6 +4385,21 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev, ...@@ -4368,6 +4385,21 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
if (u2_del_ns > timeout_ns) if (u2_del_ns > timeout_ns)
timeout_ns = u2_del_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 */ /* The U2 timeout is encoded in 256us intervals */
timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000); timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000);
/* If the necessary timeout value is bigger than what we can set in the /* 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, ...@@ -4386,13 +4418,10 @@ static u16 xhci_call_host_update_timeout_for_endpoint(struct xhci_hcd *xhci,
enum usb3_link_state state, enum usb3_link_state state,
u16 *timeout) u16 *timeout)
{ {
if (state == USB3_LPM_U1) { if (state == USB3_LPM_U1)
if (xhci->quirks & XHCI_INTEL_HOST) return xhci_calculate_u1_timeout(xhci, udev, desc);
return xhci_calculate_intel_u1_timeout(udev, desc); else if (state == USB3_LPM_U2)
} else { return xhci_calculate_u2_timeout(xhci, udev, desc);
if (xhci->quirks & XHCI_INTEL_HOST)
return xhci_calculate_intel_u2_timeout(udev, desc);
}
return USB3_LPM_DISABLED; return USB3_LPM_DISABLED;
} }
...@@ -4469,7 +4498,8 @@ static int xhci_check_tier_policy(struct xhci_hcd *xhci, ...@@ -4469,7 +4498,8 @@ static int xhci_check_tier_policy(struct xhci_hcd *xhci,
{ {
if (xhci->quirks & XHCI_INTEL_HOST) if (xhci->quirks & XHCI_INTEL_HOST)
return xhci_check_intel_tier_policy(udev, state); return xhci_check_intel_tier_policy(udev, state);
return -EINVAL; else
return 0;
} }
/* Returns the U1 or U2 timeout that should be enabled. /* Returns the U1 or U2 timeout that should be enabled.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册