Hi, On Fri, Aug 12, 2011 at 11:44:17AM -0400, Alan Stern wrote: > On Fri, 12 Aug 2011, Felipe Balbi wrote: > > > > Does the driver need to do anything at all? As far as I can tell, > > > bursting is controlled by the NumP field in the ACK transaction packet. > > > This value is set automatically by the UDC driver or hardware; the > > > gadget driver has nothing to do with it. Therefore the mass-storage > > > gadget drivers shouldn't need any changes to support bursting. > > > > In that case, I'll change that to a non-zero value (2) and later we go > > the exercise of finding the best number to stick in there. > > I think the best value would be FSG_BUFLEN / the bulk maxpacket size > (always 1024 for SuperSpeed) -- but no more than the maximum allowed > value (either 15 or 16, I forget which). > > We also need to figure out whether the UDC driver should pay attention > to the bMaxBurst value. If it doesn't support bursting, it would have > to set that field to 0. ok... how about the below: From c7176d97fe781f7fe0b21ca15ef7f449e5a7598e Mon Sep 17 00:00:00 2001 From: Felipe Balbi <balbi@xxxxxx> Date: Wed, 3 Aug 2011 14:33:27 +0300 Subject: [PATCH] usb: gadget: storage: add superspeed support Organization: Texas Instruments\n this patch adds superspeed descriptors for the storage gadgets. Signed-off-by: Felipe Balbi <balbi@xxxxxx> --- drivers/usb/gadget/f_mass_storage.c | 24 ++++++++++ drivers/usb/gadget/file_storage.c | 29 +++++++++++- drivers/usb/gadget/mass_storage.c | 2 +- drivers/usb/gadget/storage_common.c | 85 ++++++++++++++++++++++++++++++++++- 4 files changed, 134 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 5b93395..9c12234 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -3019,6 +3019,30 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) } } + if (gadget_is_superspeed(gadget)) { + u8 max_burst; + + /* Calculate bMaxBurst, we know packet size is 1024 */ + max_burst = (FSG_BUFLEN << (FSG_NUM_BUFFERS - 1) >> + (__ffs(1024))); + max_burst = min_t(u8, max_burst, 15); + + fsg_ss_bulk_in_desc.bEndpointAddress = + fsg_fs_bulk_in_desc.bEndpointAddress; + fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; + + fsg_ss_bulk_out_desc.bEndpointAddress = + fsg_fs_bulk_out_desc.bEndpointAddress; + fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; + + f->ss_descriptors = usb_copy_descriptors(fsg_ss_function); + if (unlikely(!f->ss_descriptors)) { + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + return -ENOMEM; + } + } + return 0; autoconf_fail: diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 639e14a..1f5b74b 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -2791,13 +2791,15 @@ reset: /* Enable the endpoints */ d = fsg_ep_desc(fsg->gadget, - &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc, + &fsg_ss_bulk_in_desc); if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) goto reset; fsg->bulk_in_enabled = 1; d = fsg_ep_desc(fsg->gadget, - &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc, + &fsg_ss_bulk_out_desc); if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) goto reset; fsg->bulk_out_enabled = 1; @@ -2806,7 +2808,8 @@ reset: if (transport_is_cbi()) { d = fsg_ep_desc(fsg->gadget, - &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc); + &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc, + &fsg_ss_intr_in_desc); if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) goto reset; fsg->intr_in_enabled = 1; @@ -3445,6 +3448,26 @@ static int __init fsg_bind(struct usb_gadget *gadget) fsg_fs_intr_in_desc.bEndpointAddress; } + if (gadget_is_superspeed(gadget)) { + u8 max_burst; + + fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL; + + /* Calculate bMaxBurst, we know packet size is 1024 */ + max_burst = (mod_data.buflen << (FSG_NUM_BUFFERS - 1) >> + (__ffs(1024))); + max_burst = min_t(u8,max_burst, 15); + + /* Assume endpoint addresses are the same for both speeds */ + fsg_ss_bulk_in_desc.bEndpointAddress = + fsg_fs_bulk_in_desc.bEndpointAddress; + fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; + + fsg_ss_bulk_out_desc.bEndpointAddress = + fsg_fs_bulk_out_desc.bEndpointAddress; + fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; + } + if (gadget_is_otg(gadget)) fsg_otg_desc.bmAttributes |= USB_OTG_HNP; diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index d3eb274..1b2d135 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -169,7 +169,7 @@ static struct usb_composite_driver msg_driver = { .name = "g_mass_storage", .dev = &msg_device_desc, .iProduct = DRIVER_DESC, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .needs_serial = 1, }; diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index d3dd227..527514e 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -493,12 +493,93 @@ static struct usb_descriptor_header *fsg_hs_function[] = { NULL, }; +static struct usb_endpoint_descriptor +fsg_ss_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ +}; + +static struct usb_endpoint_descriptor +fsg_ss_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_ss_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .wBytesPerInterval = cpu_to_le16(2), +}; + +#ifndef FSG_NO_OTG +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static struct usb_descriptor_header *fsg_ss_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_out_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_ss_intr_in_desc, + (struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc, +#endif + NULL, +}; + /* Maxpacket and other transfer characteristics vary by speed. */ static __maybe_unused struct usb_endpoint_descriptor * fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, - struct usb_endpoint_descriptor *hs) + struct usb_endpoint_descriptor *hs, + struct usb_endpoint_descriptor *ss) { - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) + return ss; + else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) return hs; return fs; } -- 1.7.6.396.ge0613 -- balbi
Attachment:
signature.asc
Description: Digital signature