]> www.infradead.org Git - users/hch/misc.git/commitdiff
Bluetooth: btusb: Fix regression with fake CSR controllers 0a12:0001
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 16 Oct 2024 15:47:00 +0000 (11:47 -0400)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 16 Oct 2024 20:10:25 +0000 (16:10 -0400)
Fake CSR controllers don't seem to handle short-transfer properly which
cause command to time out:

kernel: usb 1-1: new full-speed USB device number 19 using xhci_hcd
kernel: usb 1-1: New USB device found, idVendor=0a12, idProduct=0001, bcdDevice=88.91
kernel: usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
kernel: usb 1-1: Product: BT DONGLE10
...
Bluetooth: hci1: Opcode 0x1004 failed: -110
kernel: Bluetooth: hci1: command 0x1004 tx timeout

According to USB Spec 2.0 Section 5.7.3 Interrupt Transfer Packet Size
Constraints a interrupt transfer is considered complete when the size is 0
(ZPL) or < wMaxPacketSize:

 'When an interrupt transfer involves more data than can fit in one
 data payload of the currently established maximum size, all data
 payloads are required to be maximum-sized except for the last data
 payload, which will contain the remaining data. An interrupt transfer
 is complete when the endpoint does one of the following:

 • Has transferred exactly the amount of data expected
 • Transfers a packet with a payload size less than wMaxPacketSize or
 transfers a zero-length packet'

Link: https://bugzilla.kernel.org/show_bug.cgi?id=219365
Fixes: 7b05933340f4 ("Bluetooth: btusb: Fix not handling ZPL/short-transfer")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btusb.c

index 33d655e7d1248eb7da693a0dd7729c26cebc1b79..e9534fbc92e32f04c249c8be1703103070f82ee0 100644 (file)
@@ -1345,10 +1345,15 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
        if (!urb)
                return -ENOMEM;
 
-       /* Use maximum HCI Event size so the USB stack handles
-        * ZPL/short-transfer automatically.
-        */
-       size = HCI_MAX_EVENT_SIZE;
+       if (le16_to_cpu(data->udev->descriptor.idVendor)  == 0x0a12 &&
+           le16_to_cpu(data->udev->descriptor.idProduct) == 0x0001)
+               /* Fake CSR devices don't seem to support sort-transter */
+               size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
+       else
+               /* Use maximum HCI Event size so the USB stack handles
+                * ZPL/short-transfer automatically.
+                */
+               size = HCI_MAX_EVENT_SIZE;
 
        buf = kmalloc(size, mem_flags);
        if (!buf) {