[U-Boot] [PATCH v2 01/13] usb: xhci: Add interrupt transfer support

Bin Meng bmeng.cn at gmail.com
Fri Jul 14 07:45:03 UTC 2017


xHCI uses normal TRBs for both bulk and interrupt. This adds the
missing interrupt transfer support to xHCI so that devices like
USB keyboard that uses interrupt transfer can work.

Note: when interrupt transfer complets, the xHC generates an
event TRB with TRB type 'Transfer Event', which is exactly
the same as a control or bulk transfer. In our xHCI driver,
xhci_wait_for_event() checks the event TRB type and depending
on the timing, it may wrongly return an event TRB to the caller
which originates from another USB device (different slot ID is
checked by the driver and if different a "BUG" will be thrown).

The following situation can cerntainly trigger such a "BUG":
- a USB keyboard is connected to xHC
- USB keyboard driver is successfully probed
- adding some debug output after a control or bulk transfer
  is initiated, but before xHC event is checked

There are possible ways to avoid such issue:
- Add multiple event queue support and let such device like USB
  keyboard generate transfer event TRB from a different queue.
- In xhci_wait_for_event(), check slot ID and if it is not the
  caller's, add the event to a completed event list for that
  device/slot.
- Each device registers a callback routine for each transfer.
  In xhci_wait_for_event() if we encounter another slot ID,
  call its callback to handle the event.

Signed-off-by: Bin Meng <bmeng.cn at gmail.com>
---

 drivers/usb/host/xhci.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e64637b..8aff5b5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -890,11 +890,32 @@ unknown:
 static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe,
 				void *buffer, int length, int interval)
 {
+	if (usb_pipetype(pipe) != PIPE_INTERRUPT) {
+		printf("non-interrupt pipe (type=%lu)", usb_pipetype(pipe));
+		return -EINVAL;
+	}
+
 	/*
-	 * TODO: Not addressing any interrupt type transfer requests
-	 * Add support for it later.
+	 * xHCI uses normal TRBs for both bulk and interrupt. When the
+	 * interrupt endpoint is to be serviced, the xHC will consume
+	 * (at most) one TD. A TD (comprised of sg list entries) can
+	 * take several service intervals to transmit.
+	 *
+	 * Note: when interrupt transfer complets, the xHC generates an
+	 * event TRB with TRB type 'Transfer Event', which is exactly
+	 * the same as a control or bulk transfer. In our xHCI driver,
+	 * xhci_wait_for_event() checks the event TRB type and depending
+	 * on the timing, it may wrongly return an event TRB to the caller
+	 * which originates from another USB device (different slot ID is
+	 * checked by the driver and if different a "BUG" will be thrown).
+	 *
+	 * The following situation can cerntainly trigger such a "BUG":
+	 * - a USB keyboard is connected to xHC
+	 * - USB keyboard driver is successfully probed
+	 * - adding some debug output after a control or bulk transfer
+	 *   is initiated, but before xHC event is checked
 	 */
-	return -EINVAL;
+	return xhci_bulk_tx(udev, pipe, length, buffer);
 }
 
 /**
-- 
2.9.2



More information about the U-Boot mailing list