Some controllers support scatter/gather transfers and that might be very useful for some gadget drivers. Signed-off-by: Felipe Balbi <balbi@xxxxxx> --- include/linux/usb/gadget.h | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-) diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 22c37d2..fd61375 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -20,6 +20,7 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/slab.h> +#include <linux/scatterlist.h> #include <linux/types.h> #include <linux/usb/ch9.h> @@ -32,6 +33,8 @@ struct usb_ep; * @dma: DMA address corresponding to 'buf'. If you don't set this * field, and the usb controller needs one, it is responsible * for mapping and unmapping the buffer. + * @sg: a scatterlist for SG-capable controllers. + * @num_sgs: number of SG entries * @length: Length of that data * @stream_id: The stream id, when USB3.0 bulk streams are being used * @no_interrupt: If true, hints that no completion irq is needed. @@ -88,6 +91,9 @@ struct usb_request { unsigned length; dma_addr_t dma; + struct scatterlist *sg; + unsigned num_sgs; + unsigned stream_id:16; unsigned no_interrupt:1; unsigned zero:1; @@ -102,6 +108,22 @@ struct usb_request { unsigned actual; }; +struct usb_request_sg { + int status; + unsigned actual; + + void (*complete)(struct usb_ep *ep, + struct usb_request_sg *rsg); + void *context; + + /* + * Members below are private to the controller. Gadget + * drivers should not touch them. + */ + struct usb_request **requests; + int num_entries; +}; + /*-------------------------------------------------------------------------*/ /* endpoint-specific parts of the api to the usb controller hardware. @@ -120,6 +142,13 @@ struct usb_ep_ops { gfp_t gfp_flags); void (*free_request) (struct usb_ep *ep, struct usb_request *req); + int (*sg_prepare)(struct usb_ep *ep, struct usb_request_sg *rsg, + struct scatterlist *sg, unsigned int num_entries, + unsigned int length, gfp_t gfp_flags); + int (*sg_queue)(struct usb_ep *ep, struct usb_request_sg *rsg, + gfp_t gfp_flags); + int (*sg_dequeue)(struct usb_ep *ep, struct usb_request_sg *rsg); + int (*queue) (struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags); int (*dequeue) (struct usb_ep *ep, struct usb_request *req); @@ -250,6 +279,45 @@ static inline void usb_ep_free_request(struct usb_ep *ep, } /** + * usb_ep_sg_prepare - prepares a sg list to be queued to the endpoint + * @ep: the endpoint associated with the request + * @rsg: the SG request + * @sg: the scatterlist + * @num_entries: number of entries + * @length: total length of the SG transfer + * @gfp_flags: flags for memory allocations on this call + */ +static inline int usb_ep_sg_prepare(struct usb_ep *ep, + struct usb_request_sg *rsg, struct scatterlist *sg, + unsigned int num_entries, unsigned int length, gfp_t gfp_flags) +{ + return ep->ops->sg_prepare(ep, rsg, sg, num_entries, length, gfp_flags); +} + +/** + * usb_ep_sg_queue - queue a sg list to the endpoint + * @ep: the endpoint associated with the request + * @rsg: the SG request + * @gfp_flags: flags for memory allocations on this call + */ +static inline int usb_ep_sg_queue(struct usb_ep *ep, + struct usb_request_sg *rsg, gfp_t gfp_flags) +{ + return ep->ops->sg_queue(ep, rsg, gfp_flags); +} + +/** + * usb_ep_sg_dequeue - dequeues a sg ist from the endpoint + * @ep: the endpoint associated with the request + * @rsg: the SG request to the dequeued + */ +static inline int usb_ep_sg_dequeue(struct usb_ep *ep, + struct usb_request_sg *rsg) +{ + return ep->ops->sg_dequeue(ep, rsg); +} + +/** * usb_ep_queue - queues (submits) an I/O request to an endpoint. * @ep:the endpoint associated with the request * @req:the request being submitted @@ -479,6 +547,7 @@ struct usb_gadget_ops { * @speed: Speed of current connection to USB host. * @max_speed: Maximal speed the UDC can handle. UDC must support this * and all slower speeds. + * @sg_tablesize: largest number of sg list entries or 0. * @is_otg: True if the USB device port uses a Mini-AB jack, so that the * gadget driver must provide a USB OTG descriptor. * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable @@ -519,6 +588,7 @@ struct usb_gadget { struct list_head ep_list; /* of usb_ep */ enum usb_device_speed speed; enum usb_device_speed max_speed; + unsigned sg_tablesize; unsigned is_otg:1; unsigned is_a_peripheral:1; unsigned b_hnp_enable:1; -- 1.7.8.rc0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html