On Thu, Apr 24, 2014 at 11:01:58PM +0800, Mathias Nyman wrote: > On 04/22/2014 07:27 AM, Pratyush Anand wrote: > > 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@xxxxxx> > > Tested-by: Aymen Bouattay <aymen.bouattay@xxxxxx> > > --- > > drivers/usb/host/xhci.c | 66 +++++++++++++++++++++++++++++++++++-------------- > > 1 file changed, 48 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c > > index 6cc58fe..f5ac76a 100644 > > --- a/drivers/usb/host/xhci.c > > +++ b/drivers/usb/host/xhci.c > > @@ -4140,8 +4140,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: > > @@ -4149,7 +4148,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; > > @@ -4181,11 +4181,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. > > @@ -4197,14 +4214,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; > > @@ -4220,6 +4237,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 > > @@ -4238,13 +4270,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 > > + return xhci_calculate_u2_timeout(xhci, udev, desc); > > > > return USB3_LPM_DISABLED; > > Tiny nitpick, but this last return doesn't do much here. > > either: > if (state == USB3_LPM_U1) > return xhci_calculate_u1.. > > return xhci_calculate_u2... > > or then: > > if (state == USB3_LPM_U1) > return xhci_claculate_u1... > else if (state == USB3_LPM_U2) /* or just if (state == USB_LPM_U2) */ > return xhci_calculate_u2.. > return USB3_LPM_DISABLED This seems better.. Will modify in next version. Pratyush > > -Mathias -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html