summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2013-08-08 21:48:22 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-12 11:56:16 -0700
commitbcc48f1a7a0d40ae2e5a26aff72c2b674fd8b596 (patch)
tree887e24d1dc2f7701dae13ec2d071ee71cdddccdc
parent428aac8a81058e2303677a8fbf26670229e51d3a (diff)
USB: introduce usb_device_no_sg_constraint() helper
Some host controllers(such as xHCI) can support building packet from discontinuous buffers, so introduce one flag and helper for this kind of host controllers, then the feature can help some applications(such as usbnet) by supporting arbitrary length of sg buffers. Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Ming Lei <ming.lei@canonical.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/urb.c3
-rw-r--r--include/linux/usb.h8
2 files changed, 9 insertions, 2 deletions
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 4e7a311ff6d..c12bc790a6a 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -416,7 +416,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
urb->iso_frame_desc[n].status = -EXDEV;
urb->iso_frame_desc[n].actual_length = 0;
}
- } else if (dev->speed != USB_SPEED_WIRELESS && urb->num_sgs) {
+ } else if (urb->num_sgs && !urb->dev->bus->no_sg_constraint &&
+ dev->speed != USB_SPEED_WIRELESS) {
struct scatterlist *sg;
int i;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index acb1b0aa77d..001629cd1a9 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -337,6 +337,7 @@ struct usb_bus {
* the ep queue on a short transfer
* with the URB_SHORT_NOT_OK flag set.
*/
+ unsigned no_sg_constraint:1; /* no sg constraint */
unsigned sg_tablesize; /* 0 or largest number of sg list entries */
int devnum_next; /* Next open device number in
@@ -684,6 +685,11 @@ static inline bool usb_device_supports_ltm(struct usb_device *udev)
return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT;
}
+static inline bool usb_device_no_sg_constraint(struct usb_device *udev)
+{
+ return udev && udev->bus && udev->bus->no_sg_constraint;
+}
+
/*-------------------------------------------------------------------------*/
@@ -1253,7 +1259,7 @@ typedef void (*usb_complete_t)(struct urb *);
* transfer_buffer.
* @sg: scatter gather buffer list, the buffer size of each element in
* the list (except the last) must be divisible by the endpoint's
- * max packet size
+ * max packet size if no_sg_constraint isn't set in 'struct usb_bus'
* @num_mapped_sgs: (internal) number of mapped sg entries
* @num_sgs: number of entries in the sg list
* @transfer_buffer_length: How big is transfer_buffer. The transfer may