aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@vmware.com>2011-03-24 01:41:23 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-04-13 19:19:48 -0400
commitdfa49c4ad120a784ef1ff0717168aa79f55a483a (patch)
treed8dc009e82608aa2935d95ab07f50d7d3e3b7d9a /drivers
parent926008c9386dde09b015753b6681c502177baa30 (diff)
USB: xhci - fix math in xhci_get_endpoint_interval()
When parsing exponent-expressed intervals we subtract 1 from the value and then expect it to match with original + 1, which is highly unlikely, and we end with frequent spew: usb 3-4: ep 0x83 - rounding interval to 512 microframes Also, parsing interval for fullspeed isochronous endpoints was incorrect - according to USB spec they use exponent-based intervals (but xHCI spec claims frame-based intervals). I trust USB spec more, especially since USB core agrees with it. This should be queued for stable kernels back to 2.6.31. Reviewed-by: Micah Elizabeth Scott <micah@vmware.com> Signed-off-by: Dmitry Torokhov <dtor@vmware.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@kernel.org
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-mem.c90
1 files changed, 62 insertions, 28 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 7f56c9b80692..627f3438028c 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -974,6 +974,47 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
974 return 0; 974 return 0;
975} 975}
976 976
977/*
978 * Convert interval expressed as 2^(bInterval - 1) == interval into
979 * straight exponent value 2^n == interval.
980 *
981 */
982static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
983 struct usb_host_endpoint *ep)
984{
985 unsigned int interval;
986
987 interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
988 if (interval != ep->desc.bInterval - 1)
989 dev_warn(&udev->dev,
990 "ep %#x - rounding interval to %d microframes\n",
991 ep->desc.bEndpointAddress,
992 1 << interval);
993
994 return interval;
995}
996
997/*
998 * Convert bInterval expressed in frames (in 1-255 range) to exponent of
999 * microframes, rounded down to nearest power of 2.
1000 */
1001static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
1002 struct usb_host_endpoint *ep)
1003{
1004 unsigned int interval;
1005
1006 interval = fls(8 * ep->desc.bInterval) - 1;
1007 interval = clamp_val(interval, 3, 10);
1008 if ((1 << interval) != 8 * ep->desc.bInterval)
1009 dev_warn(&udev->dev,
1010 "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
1011 ep->desc.bEndpointAddress,
1012 1 << interval,
1013 8 * ep->desc.bInterval);
1014
1015 return interval;
1016}
1017
977/* Return the polling or NAK interval. 1018/* Return the polling or NAK interval.
978 * 1019 *
979 * The polling interval is expressed in "microframes". If xHCI's Interval field 1020 * The polling interval is expressed in "microframes". If xHCI's Interval field
@@ -991,45 +1032,38 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
991 case USB_SPEED_HIGH: 1032 case USB_SPEED_HIGH:
992 /* Max NAK rate */ 1033 /* Max NAK rate */
993 if (usb_endpoint_xfer_control(&ep->desc) || 1034 if (usb_endpoint_xfer_control(&ep->desc) ||
994 usb_endpoint_xfer_bulk(&ep->desc)) 1035 usb_endpoint_xfer_bulk(&ep->desc)) {
995 interval = ep->desc.bInterval; 1036 interval = ep->desc.bInterval;
1037 break;
1038 }
996 /* Fall through - SS and HS isoc/int have same decoding */ 1039 /* Fall through - SS and HS isoc/int have same decoding */
1040
997 case USB_SPEED_SUPER: 1041 case USB_SPEED_SUPER:
998 if (usb_endpoint_xfer_int(&ep->desc) || 1042 if (usb_endpoint_xfer_int(&ep->desc) ||
999 usb_endpoint_xfer_isoc(&ep->desc)) { 1043 usb_endpoint_xfer_isoc(&ep->desc)) {
1000 if (ep->desc.bInterval == 0) 1044 interval = xhci_parse_exponent_interval(udev, ep);
1001 interval = 0;
1002 else
1003 interval = ep->desc.bInterval - 1;
1004 if (interval > 15)
1005 interval = 15;
1006 if (interval != ep->desc.bInterval + 1)
1007 dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n",
1008 ep->desc.bEndpointAddress, 1 << interval);
1009 } 1045 }
1010 break; 1046 break;
1011 /* Convert bInterval (in 1-255 frames) to microframes and round down to 1047
1012 * nearest power of 2.
1013 */
1014 case USB_SPEED_FULL: 1048 case USB_SPEED_FULL:
1049 if (usb_endpoint_xfer_int(&ep->desc)) {
1050 interval = xhci_parse_exponent_interval(udev, ep);
1051 break;
1052 }
1053 /*
1054 * Fall through for isochronous endpoint interval decoding
1055 * since it uses the same rules as low speed interrupt
1056 * endpoints.
1057 */
1058
1015 case USB_SPEED_LOW: 1059 case USB_SPEED_LOW:
1016 if (usb_endpoint_xfer_int(&ep->desc) || 1060 if (usb_endpoint_xfer_int(&ep->desc) ||
1017 usb_endpoint_xfer_isoc(&ep->desc)) { 1061 usb_endpoint_xfer_isoc(&ep->desc)) {
1018 interval = fls(8*ep->desc.bInterval) - 1; 1062
1019 if (interval > 10) 1063 interval = xhci_parse_frame_interval(udev, ep);
1020 interval = 10;
1021 if (interval < 3)
1022 interval = 3;
1023 if ((1 << interval) != 8*ep->desc.bInterval)
1024 dev_warn(&udev->dev,
1025 "ep %#x - rounding interval"
1026 " to %d microframes, "
1027 "ep desc says %d microframes\n",
1028 ep->desc.bEndpointAddress,
1029 1 << interval,
1030 8*ep->desc.bInterval);
1031 } 1064 }
1032 break; 1065 break;
1066
1033 default: 1067 default:
1034 BUG(); 1068 BUG();
1035 } 1069 }