usb: Add streams support to the gadget framework
Subsystems (2)
PATCH v5 1/5 usb: Add streams support to the gadget framework
This patch defines necessary fields to support streaming for USB3.0. It implements a new function (usb_ep_autoconfig_ss) to be used instead of the existing usb_ep_autoconfig when working in SS mode and there is a need to search for an endpoint according to the number of required streams.
Signed-off-by Maya Erez <[email protected]>
Signed-off-by Tatyana Brokhman <[email protected]>
drivers/usb/gadget/epautoconf.c +101 -25
@@ -63,13 +63,16 @@ static intep_matches ( struct usb_gadget *gadget, struct usb_ep *ep, - struct usb_endpoint_descriptor *desc + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp ) { u8 type;const char *tmp;u16 max; +int num_req_streams =0 ; +/* endpoint already claimed? */ if (NULL != ep->driver_data)return 0 ;
@@ -128,6 +131,23 @@ ep_matches ( } } + +/* +* Get the number of required streams from the EP companion +* descriptor and see if the EP matches it +*/ +if (usb_endpoint_xfer_bulk (desc)) { +if (ep_comp) { + num_req_streams = ep_comp->bmAttributes &0x1f ; +if (num_req_streams > ep->num_supported_strms) +return 0 ; +/* Update the ep_comp descriptor if needed */ +if (num_req_streams != ep->num_supported_strms) + ep_comp->bmAttributes = ep->num_supported_strms; + } + + } +/* endpoint maxpacket size is an input parameter, except for bulk * where it's an output parameter representing the full speed limit. * the usb spec fixes high speed bulk maxpacket at 512 bytes.
@@ -201,38 +221,53 @@ find_ep (struct usb_gadget *gadget, const char *name) }/** -* usb_ep_autoconfig - choose an endpoint matching the descriptor +* usb_ep_autoconfig_ss() - choose an endpoint matching the ep +* descriptor and ep companion descriptor * @gadget: The device to which the endpoint must belong. * @desc: Endpoint descriptor, with endpoint direction and transfer mode -* initialized. For periodic transfers, the maximum packet -* size must also be initialized. This is modified on success. +* initialized. For periodic transfers, the maximum packet +* size must also be initialized. This is modified on +* success. +* @ep_comp: Endpoint companion descriptor, with the required +* number of streams. Will be modified when the chosen EP +* supports a different number of streams. * -* By choosing an endpoint to use with the specified descriptor, this -* routine simplifies writing gadget drivers that work with multiple -* USB device controllers. The endpoint would be passed later to -* usb_ep_enable(), along with some descriptor. +* This routine replaces the usb_ep_autoconfig when needed +* superspeed enhancments. If such enhancemnets are required, +* the FD should call usb_ep_autoconfig_ss directly and provide +* the additional ep_comp parameter. +* +* By choosing an endpoint to use with the specified descriptor, +* this routine simplifies writing gadget drivers that work with +* multiple USB device controllers. The endpoint would be +* passed later to usb_ep_enable(), along with some descriptor. * * That second descriptor won't always be the same as the first one. * For example, isochronous endpoints can be autoconfigured for high * bandwidth, and then used in several lower bandwidth altsettings. * Also, high and full speed descriptors will be different. * -* Be sure to examine and test the results of autoconfiguration on your -* hardware. This code may not make the best choices about how to use the -* USB controller, and it can't know all the restrictions that may apply. -* Some combinations of driver and hardware won't be able to autoconfigure. +* Be sure to examine and test the results of autoconfiguration +* on your hardware. This code may not make the best choices +* about how to use the USB controller, and it can't know all +* the restrictions that may apply. Some combinations of driver +* and hardware won't be able to autoconfigure. * * On success, this returns an un-claimed usb_ep, and modifies the endpoint * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value -* is initialized as if the endpoint were used at full speed. To prevent -* the endpoint from being returned by a later autoconfig call, claim it -* by assigning ep->driver_data to some non-null value. +* is initialized as if the endpoint were used at full speed and +* the bmAttribute field in the ep companion descriptor is +* updated with the assigned number of streams if it is +* different from the original value. To prevent the endpoint +* from being returned by a later autoconfig call, claim it by +* assigning ep->driver_data to some non-null value. * * On failure, this returns a null endpoint descriptor. */ -struct usb_ep *usb_ep_autoconfig ( +struct usb_ep *usb_ep_autoconfig_ss (struct usb_gadget *gadget, -struct usb_endpoint_descriptor *desc +struct usb_endpoint_descriptor *desc, +struct usb_ss_ep_comp_descriptor *ep_comp ) {struct usb_ep *ep;
@@ -246,23 +281,24 @@ struct usb_ep *usb_ep_autoconfig (if (gadget_is_net2280 (gadget) && type ==USB_ENDPOINT_XFER_INT ) {/* ep-e, ep-f are PIO with only 64 byte fifos */ ep =find_ep (gadget,"ep-e" ); -if (ep &&ep_matches (gadget, ep, desc)) +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return ep; ep =find_ep (gadget,"ep-f" ); -if (ep &&ep_matches (gadget, ep, desc)) +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return ep; }else if (gadget_is_goku (gadget)) {if (USB_ENDPOINT_XFER_INT == type) {/* single buffering is enough */ - ep =find_ep (gadget,"ep3-bulk" ); -if (ep &&ep_matches (gadget, ep, desc)) + ep =find_ep (gadget,"ep3-bulk" ); +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return ep; }else if (USB_ENDPOINT_XFER_BULK == type && (USB_DIR_IN & desc->bEndpointAddress)) {/* DMA may be available */ - ep =find_ep (gadget,"ep2-bulk" ); -if (ep &&ep_matches (gadget, ep, desc)) + ep =find_ep (gadget,"ep2-bulk" ); +if (ep &&ep_matches (gadget, ep, desc, + ep_comp))return ep; }
@@ -281,14 +317,14 @@ struct usb_ep *usb_ep_autoconfig ( ep = find_ep(gadget, "ep2out"); }else ep =NULL ; -if (ep &&ep_matches (gadget, ep, desc)) +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return ep;#endif }/* Second, look at endpoints until an unclaimed one looks usable */ list_for_each_entry (ep, &gadget->ep_list, ep_list) { -if (ep_matches (gadget, ep, desc)) +if (ep_matches (gadget, ep, desc, ep_comp))return ep; }
@@ -297,6 +333,46 @@ struct usb_ep *usb_ep_autoconfig ( }/** +* usb_ep_autoconfig() - choose an endpoint matching the +* descriptor +* @gadget: The device to which the endpoint must belong. +* @desc: Endpoint descriptor, with endpoint direction and transfer mode +* initialized. For periodic transfers, the maximum packet +* size must also be initialized. This is modified on success. +* +* By choosing an endpoint to use with the specified descriptor, this +* routine simplifies writing gadget drivers that work with multiple +* USB device controllers. The endpoint would be passed later to +* usb_ep_enable(), along with some descriptor. +* +* That second descriptor won't always be the same as the first one. +* For example, isochronous endpoints can be autoconfigured for high +* bandwidth, and then used in several lower bandwidth altsettings. +* Also, high and full speed descriptors will be different. +* +* Be sure to examine and test the results of autoconfiguration on your +* hardware. This code may not make the best choices about how to use the +* USB controller, and it can't know all the restrictions that may apply. +* Some combinations of driver and hardware won't be able to autoconfigure. +* +* On success, this returns an un-claimed usb_ep, and modifies the endpoint +* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value +* is initialized as if the endpoint were used at full speed. To prevent +* the endpoint from being returned by a later autoconfig call, claim it +* by assigning ep->driver_data to some non-null value. +* +* On failure, this returns a null endpoint descriptor. +*/ +struct usb_ep *usb_ep_autoconfig ( +struct usb_gadget *gadget, +struct usb_endpoint_descriptor *desc +) +{ +return usb_ep_autoconfig_ss (gadget, desc,NULL ); +} + + +/** * usb_ep_autoconfig_reset - reset endpoint autoconfig state * @gadget: device for which autoconfig state will be reset *
include/linux/usb/gadget.h +13 -0
@@ -34,6 +34,8 @@ struct usb_ep;* by adding a zero length packet as needed; * @short_not_ok: When reading data, makes short packets be * treated as errors (queue stops advancing till cleanup). +* @reserved: reserved bits +* @stream_id: the stream id * @complete: Function called when request completes, so this request and * its buffer may be re-used. The function will always be called with * interrupts disabled, and it must not sleep.
@@ -84,6 +86,9 @@ struct usb_request { unsigned no_interrupt:1; unsigned zero:1; unsigned short_not_ok:1; + unsigned reserved:13; + + unsigned stream_id:16;void (*complete)(struct usb_ep *ep,struct usb_request *req);
@@ -131,6 +136,8 @@ struct usb_ep_ops {* @maxpacket:The maximum packet size used on this endpoint. The initial * value can sometimes be reduced (hardware allowing), according to * the endpoint descriptor used to configure the endpoint. +* @num_supported_strms:The number of maximum streams supported +* by this EP (0 - 16, actual number is 2^n) * @mult: multiplier, 'mult' value for SS Isoc EPs * @maxburst: the maximum number of bursts supported by this EP (for usb3) * @driver_data:for use by the gadget driver.
@@ -152,6 +159,7 @@ struct usb_ep {const struct usb_ep_ops *ops;struct list_head ep_list; unsigned maxpacket:16; +int num_supported_strms; unsigned mult:2; unsigned pad:1; unsigned maxburst:4;
@@ -921,6 +929,11 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)extern struct usb_ep *usb_ep_autoconfig (struct usb_gadget *,struct usb_endpoint_descriptor *)__devinit ; + +extern struct usb_ep *usb_ep_autoconfig_ss (struct usb_gadget *, +struct usb_endpoint_descriptor *, +struct usb_ss_ep_comp_descriptor *)__devinit ; +extern void usb_ep_autoconfig_reset (struct usb_gadget *)__devinit ;#endif /* __LINUX_USB_GADGET_H */
Signature · 5 lines
1.7.0.4 -- Sent by a Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum