summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 4e7a311ff6d7..c12bc790a6a7 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 acb1b0aa77d8..001629cd1a97 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