xhci: Force Maximum Packet size for Full-speed bulk devices to valid range.
authorMathias Nyman <mathias.nyman@linux.intel.com>
Mon, 10 Feb 2020 13:45:50 +0000 (15:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Feb 2020 14:56:20 +0000 (06:56 -0800)
A Full-speed bulk USB audio device (DJ-Tech CTRL) with a invalid Maximum
Packet Size of 4 causes a xHC "Parameter Error" at enumeration.

This is because valid Maximum packet sizes for Full-speed bulk endpoints
are 8, 16, 32 and 64 bytes. Hosts are not required to support other values
than these. See usb 2 specs section 5.8.3 for details.

The device starts working after forcing the maximum packet size to 8.
This is most likely the case with other devices as well, so force the
maximum packet size to a valid range.

Cc: stable@vger.kernel.org
Reported-by: Rene D Obermueller <cmdrrdo@gmail.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20200210134553.9144-2-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-mem.c

index 3b1388fa2f36e74093e2dc2abc0083cd650266c5..0e2701649369a18fadeef8ffd5023c766714d017 100644 (file)
@@ -1475,9 +1475,15 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
        /* Allow 3 retries for everything but isoc, set CErr = 3 */
        if (!usb_endpoint_xfer_isoc(&ep->desc))
                err_count = 3;
-       /* Some devices get this wrong */
-       if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH)
-               max_packet = 512;
+       /* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */
+       if (usb_endpoint_xfer_bulk(&ep->desc)) {
+               if (udev->speed == USB_SPEED_HIGH)
+                       max_packet = 512;
+               if (udev->speed == USB_SPEED_FULL) {
+                       max_packet = rounddown_pow_of_two(max_packet);
+                       max_packet = clamp_val(max_packet, 8, 64);
+               }
+       }
        /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
        if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
                avg_trb_len = 8;