[PATCH] xhci: Fix full speed bInterval encoding some more.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit dfa49c4ad120a784ef1ff0717168aa79f55a483a
   "USB: xhci - fix math in xhci_get_endpoint_interval()"
expands the clamping of the interval value to 0-15, which is only legal
for HS/SS endpoints.  For FS, it must be 3-11.  When testing with FS
isochronous endpoints (an audio device), values outside this range caused
the following error 0x11 (again) on an NEC xHCI controller:

  xhci_hcd 0000:01:00.0: ERROR: unexpected command completion code 0x11.
  usb 1-1: Not enough bandwidth for altsetting 1

This commit makes xhci_parse_exponent_interval() check the EP speed and
clamp the interval appropriately.  Also, xhci_parse_frame_interval() clamped
interval to 3-10; this has been changed to 3-11, as is valid for LS/HS.

With this patch, full-speed isoch devices (e.g. audio) work again on xHCI.

This should be queued for all stable kernels that contain
 dfa49c4ad120a784ef1ff0717168aa79f55a483a

Signed-off-by: Matt Evans <matt@xxxxxxxxxx>
---

A review of the xhci_parse_frame_interval() change (max 10 -> 11) would be
appreciated.  The value 10 comes from Sarah's original xhci_get_endpoint_interval()
implementation; was there a reason for this being 10 rather than (as per the spec)
11?

 drivers/usb/host/xhci-mem.c |   15 ++++++++++++---
 1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 26caba4..ba5c40a 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -975,14 +975,22 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
 /*
  * Convert interval expressed as 2^(bInterval - 1) == interval into
  * straight exponent value 2^n == interval.
- *
+ * Not used for LS.
  */
 static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
 		struct usb_host_endpoint *ep)
 {
 	unsigned int interval;
 
-	interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
+	/*
+	 * xHCI spec 6.2.3 Table 56: "The legal range of values is 3 to 11 for
+	 * Full- or Low-speed Interrupt endpoints and 0 to 15 for all other
+	 * endpoint types".  LS doesn't get here, so just check for FS:
+	 */
+	if (udev->speed == USB_SPEED_FULL)
+		interval = clamp_val(ep->desc.bInterval, 4, 12) - 1;
+	else
+		interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
 	if (interval != ep->desc.bInterval - 1)
 		dev_warn(&udev->dev,
 			 "ep %#x - rounding interval to %d microframes\n",
@@ -995,6 +1003,7 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
 /*
  * Convert bInterval expressed in frames (in 1-255 range) to exponent of
  * microframes, rounded down to nearest power of 2.
+ * Only used for FS/HS.
  */
 static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
 		struct usb_host_endpoint *ep)
@@ -1002,7 +1011,7 @@ static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
 	unsigned int interval;
 
 	interval = fls(8 * ep->desc.bInterval) - 1;
-	interval = clamp_val(interval, 3, 10);
+	interval = clamp_val(interval, 3, 11);
 	if ((1 << interval) != 8 * ep->desc.bInterval)
 		dev_warn(&udev->dev,
 			 "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
-- 
1.7.0.4

--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux