aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2012-05-16 16:36:24 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-05-18 18:42:04 -0400
commite3567d2c15a7a8e2f992a5f7c7683453ca406d82 (patch)
tree2442117f7358e50f49cfecd030a6017d392f474c /drivers
parent3b3db026414bba1c8f45c49d5eeaefd48d66e1ae (diff)
xhci: Add Intel U1/U2 timeout policy.
All Intel xHCI host controllers support USB 3.0 Link Power Management. The Panther Point xHCI host controller needs the xHCI driver to calculate the U1 and U2 timeout values, because it will blindly accept a MEL that would cause scheduling issues. The Lynx Point xHCI host controller will reject MEL values that are too high, but internally it implements the same algorithm that is needed for Panther Point xHCI. Simplify the code paths by just having the xHCI driver calculate what the U1/U2 timeouts should be. Comments on the policy are in the code. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-pci.c4
-rw-r--r--drivers/usb/host/xhci.c133
-rw-r--r--drivers/usb/host/xhci.h1
3 files changed, 138 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 890ba735dee7..18b231b0c5d3 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -84,6 +84,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
84 /* AMD PLL quirk */ 84 /* AMD PLL quirk */
85 if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) 85 if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
86 xhci->quirks |= XHCI_AMD_PLL_FIX; 86 xhci->quirks |= XHCI_AMD_PLL_FIX;
87 if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
88 xhci->quirks |= XHCI_LPM_SUPPORT;
89 xhci->quirks |= XHCI_INTEL_HOST;
90 }
87 if (pdev->vendor == PCI_VENDOR_ID_INTEL && 91 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
88 pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { 92 pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
89 xhci->quirks |= XHCI_SPURIOUS_SUCCESS; 93 xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 518d002d54cc..4ceba145fa88 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3839,6 +3839,13 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
3839 3839
3840/*---------------------- USB 3.0 Link PM functions ------------------------*/ 3840/*---------------------- USB 3.0 Link PM functions ------------------------*/
3841 3841
3842/* Service interval in nanoseconds = 2^(bInterval - 1) * 125us * 1000ns / 1us */
3843static unsigned long long xhci_service_interval_to_ns(
3844 struct usb_endpoint_descriptor *desc)
3845{
3846 return (1 << (desc->bInterval - 1)) * 125 * 1000;
3847}
3848
3842static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, 3849static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
3843 enum usb3_link_state state) 3850 enum usb3_link_state state)
3844{ 3851{
@@ -3881,12 +3888,112 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
3881 return USB3_LPM_DISABLED; 3888 return USB3_LPM_DISABLED;
3882} 3889}
3883 3890
3891/* Returns the hub-encoded U1 timeout value.
3892 * The U1 timeout should be the maximum of the following values:
3893 * - For control endpoints, U1 system exit latency (SEL) * 3
3894 * - For bulk endpoints, U1 SEL * 5
3895 * - For interrupt endpoints:
3896 * - Notification EPs, U1 SEL * 3
3897 * - Periodic EPs, max(105% of bInterval, U1 SEL * 2)
3898 * - For isochronous endpoints, max(105% of bInterval, U1 SEL * 2)
3899 */
3900static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
3901 struct usb_endpoint_descriptor *desc)
3902{
3903 unsigned long long timeout_ns;
3904 int ep_type;
3905 int intr_type;
3906
3907 ep_type = usb_endpoint_type(desc);
3908 switch (ep_type) {
3909 case USB_ENDPOINT_XFER_CONTROL:
3910 timeout_ns = udev->u1_params.sel * 3;
3911 break;
3912 case USB_ENDPOINT_XFER_BULK:
3913 timeout_ns = udev->u1_params.sel * 5;
3914 break;
3915 case USB_ENDPOINT_XFER_INT:
3916 intr_type = usb_endpoint_interrupt_type(desc);
3917 if (intr_type == USB_ENDPOINT_INTR_NOTIFICATION) {
3918 timeout_ns = udev->u1_params.sel * 3;
3919 break;
3920 }
3921 /* Otherwise the calculation is the same as isoc eps */
3922 case USB_ENDPOINT_XFER_ISOC:
3923 timeout_ns = xhci_service_interval_to_ns(desc);
3924 timeout_ns = DIV_ROUND_UP(timeout_ns * 105, 100);
3925 if (timeout_ns < udev->u1_params.sel * 2)
3926 timeout_ns = udev->u1_params.sel * 2;
3927 break;
3928 default:
3929 return 0;
3930 }
3931
3932 /* The U1 timeout is encoded in 1us intervals. */
3933 timeout_ns = DIV_ROUND_UP(timeout_ns, 1000);
3934 /* Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */
3935 if (timeout_ns == USB3_LPM_DISABLED)
3936 timeout_ns++;
3937
3938 /* If the necessary timeout value is bigger than what we can set in the
3939 * USB 3.0 hub, we have to disable hub-initiated U1.
3940 */
3941 if (timeout_ns <= USB3_LPM_U1_MAX_TIMEOUT)
3942 return timeout_ns;
3943 dev_dbg(&udev->dev, "Hub-initiated U1 disabled "
3944 "due to long timeout %llu ms\n", timeout_ns);
3945 return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U1);
3946}
3947
3948/* Returns the hub-encoded U2 timeout value.
3949 * The U2 timeout should be the maximum of:
3950 * - 10 ms (to avoid the bandwidth impact on the scheduler)
3951 * - largest bInterval of any active periodic endpoint (to avoid going
3952 * into lower power link states between intervals).
3953 * - the U2 Exit Latency of the device
3954 */
3955static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
3956 struct usb_endpoint_descriptor *desc)
3957{
3958 unsigned long long timeout_ns;
3959 unsigned long long u2_del_ns;
3960
3961 timeout_ns = 10 * 1000 * 1000;
3962
3963 if ((usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) &&
3964 (xhci_service_interval_to_ns(desc) > timeout_ns))
3965 timeout_ns = xhci_service_interval_to_ns(desc);
3966
3967 u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
3968 if (u2_del_ns > timeout_ns)
3969 timeout_ns = u2_del_ns;
3970
3971 /* The U2 timeout is encoded in 256us intervals */
3972 timeout_ns = DIV_ROUND_UP(timeout_ns, 256 * 1000);
3973 /* If the necessary timeout value is bigger than what we can set in the
3974 * USB 3.0 hub, we have to disable hub-initiated U2.
3975 */
3976 if (timeout_ns <= USB3_LPM_U2_MAX_TIMEOUT)
3977 return timeout_ns;
3978 dev_dbg(&udev->dev, "Hub-initiated U2 disabled "
3979 "due to long timeout %llu ms\n", timeout_ns);
3980 return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U2);
3981}
3982
3884static u16 xhci_call_host_update_timeout_for_endpoint(struct xhci_hcd *xhci, 3983static u16 xhci_call_host_update_timeout_for_endpoint(struct xhci_hcd *xhci,
3885 struct usb_device *udev, 3984 struct usb_device *udev,
3886 struct usb_endpoint_descriptor *desc, 3985 struct usb_endpoint_descriptor *desc,
3887 enum usb3_link_state state, 3986 enum usb3_link_state state,
3888 u16 *timeout) 3987 u16 *timeout)
3889{ 3988{
3989 if (state == USB3_LPM_U1) {
3990 if (xhci->quirks & XHCI_INTEL_HOST)
3991 return xhci_calculate_intel_u1_timeout(udev, desc);
3992 } else {
3993 if (xhci->quirks & XHCI_INTEL_HOST)
3994 return xhci_calculate_intel_u2_timeout(udev, desc);
3995 }
3996
3890 return USB3_LPM_DISABLED; 3997 return USB3_LPM_DISABLED;
3891} 3998}
3892 3999
@@ -3932,10 +4039,36 @@ static int xhci_update_timeout_for_interface(struct xhci_hcd *xhci,
3932 return 0; 4039 return 0;
3933} 4040}
3934 4041
4042static int xhci_check_intel_tier_policy(struct usb_device *udev,
4043 enum usb3_link_state state)
4044{
4045 struct usb_device *parent;
4046 unsigned int num_hubs;
4047
4048 if (state == USB3_LPM_U2)
4049 return 0;
4050
4051 /* Don't enable U1 if the device is on a 2nd tier hub or lower. */
4052 for (parent = udev->parent, num_hubs = 0; parent->parent;
4053 parent = parent->parent)
4054 num_hubs++;
4055
4056 if (num_hubs < 2)
4057 return 0;
4058
4059 dev_dbg(&udev->dev, "Disabling U1 link state for device"
4060 " below second-tier hub.\n");
4061 dev_dbg(&udev->dev, "Plug device into first-tier hub "
4062 "to decrease power consumption.\n");
4063 return -E2BIG;
4064}
4065
3935static int xhci_check_tier_policy(struct xhci_hcd *xhci, 4066static int xhci_check_tier_policy(struct xhci_hcd *xhci,
3936 struct usb_device *udev, 4067 struct usb_device *udev,
3937 enum usb3_link_state state) 4068 enum usb3_link_state state)
3938{ 4069{
4070 if (xhci->quirks & XHCI_INTEL_HOST)
4071 return xhci_check_intel_tier_policy(udev, state);
3939 return -EINVAL; 4072 return -EINVAL;
3940} 4073}
3941 4074
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index d55b3678c8b8..de3d6e3e57be 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1489,6 +1489,7 @@ struct xhci_hcd {
1489#define XHCI_AMD_0x96_HOST (1 << 9) 1489#define XHCI_AMD_0x96_HOST (1 << 9)
1490#define XHCI_TRUST_TX_LENGTH (1 << 10) 1490#define XHCI_TRUST_TX_LENGTH (1 << 10)
1491#define XHCI_LPM_SUPPORT (1 << 11) 1491#define XHCI_LPM_SUPPORT (1 << 11)
1492#define XHCI_INTEL_HOST (1 << 12)
1492 unsigned int num_active_eps; 1493 unsigned int num_active_eps;
1493 unsigned int limit_active_eps; 1494 unsigned int limit_active_eps;
1494 /* There are two roothubs to keep track of bus suspend info for */ 1495 /* There are two roothubs to keep track of bus suspend info for */