summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/message.c8
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--drivers/usb/storage/usb.c10
-rw-r--r--include/linux/usb.h1
4 files changed, 14 insertions, 7 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index e80f1af438c8..8d874cad6581 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -393,13 +393,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
if (io->entries <= 0)
return io->entries;
- /* If we're running on an xHCI host controller, queue the whole scatter
- * gather list with one call to urb_enqueue(). This is only for bulk,
- * as that endpoint type does not care how the data gets broken up
- * across frames.
- */
- if (usb_pipebulk(pipe) &&
- bus_to_hcd(dev->bus)->driver->flags & HCD_USB3) {
+ if (dev->bus->sg_tablesize > 0) {
io->urbs = kmalloc(sizeof *io->urbs, mem_flags);
use_sg = true;
} else {
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 06595ec27bb7..e097008d6fb1 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -54,6 +54,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int retval;
+ hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 1;
+
xhci->cap_regs = hcd->regs;
xhci->op_regs = hcd->regs +
HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 01e43a13a6bf..1599d86154c4 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -843,6 +843,15 @@ static int usb_stor_scan_thread(void * __us)
complete_and_exit(&us->scanning_done, 0);
}
+static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+
+ if (usb_dev->bus->sg_tablesize) {
+ return usb_dev->bus->sg_tablesize;
+ }
+ return SG_ALL;
+}
/* First part of general USB mass-storage probing */
int usb_stor_probe1(struct us_data **pus,
@@ -871,6 +880,7 @@ int usb_stor_probe1(struct us_data **pus,
* Allow 16-byte CDBs and thus > 2TB
*/
host->max_cmd_len = 16;
+ host->sg_tablesize = usb_stor_sg_tablesize(intf);
*pus = us = host_to_us(host);
memset(us, 0, sizeof(struct us_data));
mutex_init(&(us->dev_mutex));
diff --git a/include/linux/usb.h b/include/linux/usb.h
index a34fa89f1474..6e91ee4f5b81 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -331,6 +331,7 @@ struct usb_bus {
u8 otg_port; /* 0, or number of OTG/HNP port */
unsigned is_b_host:1; /* true during some HNP roleswitches */
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
+ unsigned sg_tablesize; /* 0 or largest number of sg list entries */
int devnum_next; /* Next open device number in
* round-robin allocation */
OpenPOWER on IntegriCloud