Browse Source

USB: make urb scatter-gather support more generic

The WHCI HCD will also support urbs with scatter-gather lists.  Add a
usb_bus field to indicated how many sg list elements are supported by
the HCD.  Use this to decide whether to pass the scatter-list to the HCD
or not.

Make the usb-storage driver use this new field.

Signed-off-by: David Vrabel <david.vrabel@csr.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
David Vrabel 16 years ago
parent
commit
4c1bd3d7a7
4 changed files with 14 additions and 7 deletions
  1. 1 7
      drivers/usb/core/message.c
  2. 2 0
      drivers/usb/host/xhci-pci.c
  3. 10 0
      drivers/usb/storage/usb.c
  4. 1 0
      include/linux/usb.h

+ 1 - 7
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)
 	if (io->entries <= 0)
 		return io->entries;
 		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);
 		io->urbs = kmalloc(sizeof *io->urbs, mem_flags);
 		use_sg = true;
 		use_sg = true;
 	} else {
 	} else {

+ 2 - 0
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);
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 	int			retval;
 	int			retval;
 
 
+	hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 1;
+
 	xhci->cap_regs = hcd->regs;
 	xhci->cap_regs = hcd->regs;
 	xhci->op_regs = hcd->regs +
 	xhci->op_regs = hcd->regs +
 		HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));
 		HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));

+ 10 - 0
drivers/usb/storage/usb.c

@@ -843,6 +843,15 @@ static int usb_stor_scan_thread(void * __us)
 	complete_and_exit(&us->scanning_done, 0);
 	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 */
 /* First part of general USB mass-storage probing */
 int usb_stor_probe1(struct us_data **pus,
 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
 	 * Allow 16-byte CDBs and thus > 2TB
 	 */
 	 */
 	host->max_cmd_len = 16;
 	host->max_cmd_len = 16;
+	host->sg_tablesize = usb_stor_sg_tablesize(intf);
 	*pus = us = host_to_us(host);
 	*pus = us = host_to_us(host);
 	memset(us, 0, sizeof(struct us_data));
 	memset(us, 0, sizeof(struct us_data));
 	mutex_init(&(us->dev_mutex));
 	mutex_init(&(us->dev_mutex));

+ 1 - 0
include/linux/usb.h

@@ -331,6 +331,7 @@ struct usb_bus {
 	u8 otg_port;			/* 0, or number of OTG/HNP port */
 	u8 otg_port;			/* 0, or number of OTG/HNP port */
 	unsigned is_b_host:1;		/* true during some HNP roleswitches */
 	unsigned is_b_host:1;		/* true during some HNP roleswitches */
 	unsigned b_hnp_enable:1;	/* OTG: did A-Host enable HNP? */
 	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
 	int devnum_next;		/* Next open device number in
 					 * round-robin allocation */
 					 * round-robin allocation */