diff options
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 90 |
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 | */ | ||
982 | static 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 | */ | ||
1001 | static 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 | } |