Commit bcc48f1a authored by Ming Lei's avatar Ming Lei Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarMing Lei <ming.lei@canonical.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 428aac8a
...@@ -416,7 +416,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -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].status = -EXDEV;
urb->iso_frame_desc[n].actual_length = 0; 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; struct scatterlist *sg;
int i; int i;
......
...@@ -337,6 +337,7 @@ struct usb_bus { ...@@ -337,6 +337,7 @@ struct usb_bus {
* the ep queue on a short transfer * the ep queue on a short transfer
* with the URB_SHORT_NOT_OK flag set. * 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 */ 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
...@@ -684,6 +685,11 @@ static inline bool usb_device_supports_ltm(struct usb_device *udev) ...@@ -684,6 +685,11 @@ static inline bool usb_device_supports_ltm(struct usb_device *udev)
return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT; 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 *); ...@@ -1253,7 +1259,7 @@ typedef void (*usb_complete_t)(struct urb *);
* transfer_buffer. * transfer_buffer.
* @sg: scatter gather buffer list, the buffer size of each element in * @sg: scatter gather buffer list, the buffer size of each element in
* the list (except the last) must be divisible by the endpoint's * 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_mapped_sgs: (internal) number of mapped sg entries
* @num_sgs: number of entries in the sg list * @num_sgs: number of entries in the sg list
* @transfer_buffer_length: How big is transfer_buffer. The transfer may * @transfer_buffer_length: How big is transfer_buffer. The transfer may
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment