Add a new module parameter to increase the bulk ring size. Matrix Vision has a libusb program for their USB 2.0 cameras that submits a number of very large transfers. The xHCI driver ends up rejecting some transfers because it doesn't have enough room on the one bulk ring segment. By experimentation, their program works if 20 bulk segments are allocated. We really need to fix this by adding dynamic ring segment allocation, but that code is a bit complex and will take a while to write. To ensure Matrix Vision's libusb program works when their device is connected under an xHCI host, add a module parameter to allow users to increase the number of bulk endpoint ring segments. This is a temporary fix, and should be removed once the xHCI driver has dynamic segment allocation. Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> Cc: Kruno Mrak <kruno.mrak@xxxxxxxxxxxxxxxx> --- Hi Kruno, Would you please try to apply this patch against Linus' latest tree and let me know if your program works when you load the xHCI driver with this command: sudo insmod drivers/usb/host/xhci-hcd.ko bulk_segs=20 Or something similar with modprobe, if you even up installing the driver and rebooting. Thanks, Sarah Sharp drivers/usb/host/xhci-mem.c | 4 ++++ drivers/usb/host/xhci.c | 8 ++++++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 13 insertions(+), 0 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fcb7f7e..ad99dd5 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1176,6 +1176,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, if (usb_endpoint_xfer_isoc(&ep->desc)) virt_dev->eps[ep_index].new_ring = xhci_ring_alloc(xhci, 8, true, mem_flags); + else if (usb_endpoint_xfer_bulk(&ep->desc)) + virt_dev->eps[ep_index].new_ring = + xhci_ring_alloc(xhci, xhci->num_bulk_segs, + true, mem_flags); else virt_dev->eps[ep_index].new_ring = xhci_ring_alloc(xhci, 1, true, mem_flags); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f5fe1ac..211dcca 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -37,6 +37,10 @@ static int link_quirk; module_param(link_quirk, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); +static int bulk_segs; +module_param(bulk_segs, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(bulk_segs, "Number of ring segments for bulk endpoints"); + /* TODO: copied from ehci-hcd.c - can this be refactored? */ /* * handshake - spin reading hc until handshake completes or fails @@ -322,6 +326,10 @@ int xhci_init(struct usb_hcd *hcd) } else { xhci_dbg(xhci, "xHCI doesn't need link TRB QUIRK\n"); } + if (bulk_segs > 1) + xhci->num_bulk_segs = bulk_segs; + else + xhci->num_bulk_segs = 1; retval = xhci_mem_init(xhci, GFP_KERNEL); xhci_dbg(xhci, "Finished xhci_init\n"); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d8bbf5c..e88d2fa 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1313,6 +1313,7 @@ struct xhci_hcd { #define XHCI_RESET_ON_RESUME (1 << 7) unsigned int num_active_eps; unsigned int limit_active_eps; + unsigned int num_bulk_segs; /* There are two roothubs to keep track of bus suspend info for */ struct xhci_bus_state bus_state[2]; /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */ -- 1.7.4.1 -- 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