Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: Parse and store the SuperSpeed endpoint companion descriptors.

The USB 3.0 bus specification added an "Endpoint Companion" descriptor that is
supposed to follow all SuperSpeed Endpoint descriptors. This descriptor is used
to extend the bus protocol to allow more packets to be sent to an endpoint per
"microframe". The word microframe was removed from the USB 3.0 specification
because the host controller does not send Start Of Frame (SOF) symbols down the
USB 3.0 wires.

The descriptor defines a bMaxBurst field, which indicates the number of packets
of wMaxPacketSize that a SuperSpeed device can send or recieve in a service
interval. All non-control endpoints may set this value as high as 16 packets
(bMaxBurst = 15).

The descriptor also allows isochronous endpoints to further specify that they
can send and receive multiple bursts per service interval. The bmAttributes
allows them to specify a "Mult" of up to 3 (bmAttributes = 2).

Bulk endpoints use bmAttributes to report the number of "Streams" they support.
This was an extension of the endpoint pipe concept to allow multiple mass
storage device commands to be outstanding for one bulk endpoint at a time. This
should allow USB 3.0 mass storage devices to support SCSI command queueing.
Bulk endpoints can say they support up to 2^16 (65,536) streams.

The information in the endpoint companion descriptor must be stored with the
other device, config, interface, and endpoint descriptors because the host
controller needs to access them quickly, and we need to install some default
values if a SuperSpeed device doesn't provide an endpoint companion descriptor.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Sarah Sharp and committed by
Greg Kroah-Hartman
663c30d0 d0e96f5a

+211 -8
+179 -8
drivers/usb/core/config.c
··· 19 19 return (n == 1 ? "" : "s"); 20 20 } 21 21 22 + /* FIXME: this is a kludge */ 23 + static int find_next_descriptor_more(unsigned char *buffer, int size, 24 + int dt1, int dt2, int dt3, int *num_skipped) 25 + { 26 + struct usb_descriptor_header *h; 27 + int n = 0; 28 + unsigned char *buffer0 = buffer; 29 + 30 + /* Find the next descriptor of type dt1 or dt2 or dt3 */ 31 + while (size > 0) { 32 + h = (struct usb_descriptor_header *) buffer; 33 + if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2 || 34 + h->bDescriptorType == dt3) 35 + break; 36 + buffer += h->bLength; 37 + size -= h->bLength; 38 + ++n; 39 + } 40 + 41 + /* Store the number of descriptors skipped and return the 42 + * number of bytes skipped */ 43 + if (num_skipped) 44 + *num_skipped = n; 45 + return buffer - buffer0; 46 + } 47 + 22 48 static int find_next_descriptor(unsigned char *buffer, int size, 23 49 int dt1, int dt2, int *num_skipped) 24 50 { ··· 69 43 return buffer - buffer0; 70 44 } 71 45 46 + static int usb_parse_endpoint_companion(struct device *ddev, int cfgno, 47 + int inum, int asnum, struct usb_host_endpoint *ep, 48 + int num_ep, unsigned char *buffer, int size) 49 + { 50 + unsigned char *buffer_start = buffer; 51 + struct usb_ep_comp_descriptor *desc; 52 + int retval; 53 + int num_skipped; 54 + int max_tx; 55 + int i; 56 + 57 + /* Allocate space for the companion descriptor */ 58 + ep->ep_comp = kzalloc(sizeof(struct usb_host_ep_comp), GFP_KERNEL); 59 + if (!ep->ep_comp) 60 + return -ENOMEM; 61 + desc = (struct usb_ep_comp_descriptor *) buffer; 62 + if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) { 63 + dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " 64 + " interface %d altsetting %d ep %d: " 65 + "using minimum values\n", 66 + cfgno, inum, asnum, ep->desc.bEndpointAddress); 67 + ep->ep_comp->desc.bLength = USB_DT_EP_COMP_SIZE; 68 + ep->ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; 69 + ep->ep_comp->desc.bMaxBurst = 0; 70 + /* 71 + * Leave bmAttributes as zero, which will mean no streams for 72 + * bulk, and isoc won't support multiple bursts of packets. 73 + * With bursts of only one packet, and a Mult of 1, the max 74 + * amount of data moved per endpoint service interval is one 75 + * packet. 76 + */ 77 + if (usb_endpoint_xfer_isoc(&ep->desc) || 78 + usb_endpoint_xfer_int(&ep->desc)) 79 + ep->ep_comp->desc.wBytesPerInterval = 80 + ep->desc.wMaxPacketSize; 81 + /* 82 + * The next descriptor is for an Endpoint or Interface, 83 + * no extra descriptors to copy into the companion structure, 84 + * and we didn't eat up any of the buffer. 85 + */ 86 + retval = 0; 87 + goto valid; 88 + } 89 + memcpy(&ep->ep_comp->desc, desc, USB_DT_EP_COMP_SIZE); 90 + desc = &ep->ep_comp->desc; 91 + buffer += desc->bLength; 92 + size -= desc->bLength; 93 + 94 + /* Eat up the other descriptors we don't care about */ 95 + ep->ep_comp->extra = buffer; 96 + i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, 97 + USB_DT_INTERFACE, &num_skipped); 98 + ep->ep_comp->extralen = i; 99 + buffer += i; 100 + size -= i; 101 + retval = buffer - buffer_start + i; 102 + if (num_skipped > 0) 103 + dev_dbg(ddev, "skipped %d descriptor%s after %s\n", 104 + num_skipped, plural(num_skipped), 105 + "SuperSpeed endpoint companion"); 106 + 107 + /* Check the various values */ 108 + if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) { 109 + dev_warn(ddev, "Control endpoint with bMaxBurst = %d in " 110 + "config %d interface %d altsetting %d ep %d: " 111 + "setting to zero\n", desc->bMaxBurst, 112 + cfgno, inum, asnum, ep->desc.bEndpointAddress); 113 + desc->bMaxBurst = 0; 114 + } 115 + if (desc->bMaxBurst > 15) { 116 + dev_warn(ddev, "Endpoint with bMaxBurst = %d in " 117 + "config %d interface %d altsetting %d ep %d: " 118 + "setting to 15\n", desc->bMaxBurst, 119 + cfgno, inum, asnum, ep->desc.bEndpointAddress); 120 + desc->bMaxBurst = 15; 121 + } 122 + if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) 123 + && desc->bmAttributes != 0) { 124 + dev_warn(ddev, "%s endpoint with bmAttributes = %d in " 125 + "config %d interface %d altsetting %d ep %d: " 126 + "setting to zero\n", 127 + usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk", 128 + desc->bmAttributes, 129 + cfgno, inum, asnum, ep->desc.bEndpointAddress); 130 + desc->bmAttributes = 0; 131 + } 132 + if (usb_endpoint_xfer_bulk(&ep->desc) && desc->bmAttributes > 16) { 133 + dev_warn(ddev, "Bulk endpoint with more than 65536 streams in " 134 + "config %d interface %d altsetting %d ep %d: " 135 + "setting to max\n", 136 + cfgno, inum, asnum, ep->desc.bEndpointAddress); 137 + desc->bmAttributes = 16; 138 + } 139 + if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) { 140 + dev_warn(ddev, "Isoc endpoint has Mult of %d in " 141 + "config %d interface %d altsetting %d ep %d: " 142 + "setting to 3\n", desc->bmAttributes + 1, 143 + cfgno, inum, asnum, ep->desc.bEndpointAddress); 144 + desc->bmAttributes = 2; 145 + } 146 + if (usb_endpoint_xfer_isoc(&ep->desc)) { 147 + max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1) * 148 + (desc->bmAttributes + 1); 149 + } else if (usb_endpoint_xfer_int(&ep->desc)) { 150 + max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1); 151 + } else { 152 + goto valid; 153 + } 154 + if (desc->wBytesPerInterval > max_tx) { 155 + dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in " 156 + "config %d interface %d altsetting %d ep %d: " 157 + "setting to %d\n", 158 + usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int", 159 + desc->wBytesPerInterval, 160 + cfgno, inum, asnum, ep->desc.bEndpointAddress, 161 + max_tx); 162 + desc->wBytesPerInterval = max_tx; 163 + } 164 + valid: 165 + return retval; 166 + } 167 + 72 168 static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, 73 169 int asnum, struct usb_host_interface *ifp, int num_ep, 74 170 unsigned char *buffer, int size) ··· 198 50 unsigned char *buffer0 = buffer; 199 51 struct usb_endpoint_descriptor *d; 200 52 struct usb_host_endpoint *endpoint; 201 - int n, i, j; 53 + int n, i, j, retval; 202 54 203 55 d = (struct usb_endpoint_descriptor *) buffer; 204 56 buffer += d->bLength; ··· 310 162 cfgno, inum, asnum, d->bEndpointAddress, 311 163 maxp); 312 164 } 165 + /* Allocate room for and parse any endpoint companion descriptors */ 166 + if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) { 167 + endpoint->extra = buffer; 168 + i = find_next_descriptor_more(buffer, size, USB_DT_SS_ENDPOINT_COMP, 169 + USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); 170 + endpoint->extralen = i; 171 + buffer += i; 172 + size -= i; 313 173 314 - /* Skip over any Class Specific or Vendor Specific descriptors; 315 - * find the next endpoint or interface descriptor */ 316 - endpoint->extra = buffer; 317 - i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, 318 - USB_DT_INTERFACE, &n); 319 - endpoint->extralen = i; 174 + if (size > 0) { 175 + retval = usb_parse_endpoint_companion(ddev, cfgno, inum, asnum, 176 + endpoint, num_ep, buffer, size); 177 + if (retval >= 0) { 178 + buffer += retval; 179 + retval = buffer - buffer0; 180 + } 181 + } else { 182 + retval = buffer - buffer0; 183 + } 184 + } else { 185 + /* Skip over any Class Specific or Vendor Specific descriptors; 186 + * find the next endpoint or interface descriptor */ 187 + endpoint->extra = buffer; 188 + i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, 189 + USB_DT_INTERFACE, &n); 190 + endpoint->extralen = i; 191 + retval = buffer - buffer0 + i; 192 + } 320 193 if (n > 0) 321 194 dev_dbg(ddev, "skipped %d descriptor%s after %s\n", 322 195 n, plural(n), "endpoint"); 323 - return buffer - buffer0 + i; 196 + return retval; 324 197 325 198 skip_to_next_endpoint_or_interface_descriptor: 326 199 i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, ··· 621 452 return -ENOMEM; 622 453 kref_init(&intfc->ref); 623 454 } 455 + 456 + /* FIXME: parse the BOS descriptor */ 624 457 625 458 /* Skip over any Class Specific or Vendor Specific descriptors; 626 459 * find the first interface descriptor */
+16
include/linux/usb.h
··· 36 36 * - configs have one (often) or more interfaces; 37 37 * - interfaces have one (usually) or more settings; 38 38 * - each interface setting has zero or (usually) more endpoints. 39 + * - a SuperSpeed endpoint has a companion descriptor 39 40 * 40 41 * And there might be other descriptors mixed in with those. 41 42 * ··· 45 44 46 45 struct ep_device; 47 46 47 + /* For SS devices */ 48 + /** 49 + * struct usb_host_ep_comp - Valid for SuperSpeed devices only 50 + * @desc: endpoint companion descriptor, wMaxPacketSize in native byteorder 51 + * @extra: descriptors following this endpoint companion descriptor 52 + * @extralen: how many bytes of "extra" are valid 53 + */ 54 + struct usb_host_ep_comp { 55 + struct usb_ep_comp_descriptor desc; 56 + unsigned char *extra; /* Extra descriptors */ 57 + int extralen; 58 + }; 59 + 48 60 /** 49 61 * struct usb_host_endpoint - host-side endpoint descriptor and queue 50 62 * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder ··· 65 51 * @hcpriv: for use by HCD; typically holds hardware dma queue head (QH) 66 52 * with one or more transfer descriptors (TDs) per urb 67 53 * @ep_dev: ep_device for sysfs info 54 + * @ep_comp: companion descriptor information for this endpoint 68 55 * @extra: descriptors following this endpoint in the configuration 69 56 * @extralen: how many bytes of "extra" are valid 70 57 * @enabled: URBs may be submitted to this endpoint ··· 78 63 struct list_head urb_list; 79 64 void *hcpriv; 80 65 struct ep_device *ep_dev; /* For sysfs info */ 66 + struct usb_host_ep_comp *ep_comp; /* For SS devices */ 81 67 82 68 unsigned char *extra; /* Extra descriptors */ 83 69 int extralen;
+16
include/linux/usb/ch9.h
··· 191 191 #define USB_DT_WIRE_ADAPTER 0x21 192 192 #define USB_DT_RPIPE 0x22 193 193 #define USB_DT_CS_RADIO_CONTROL 0x23 194 + /* From the USB 3.0 spec */ 195 + #define USB_DT_SS_ENDPOINT_COMP 0x30 194 196 195 197 /* Conventional codes for class-specific descriptors. The convention is 196 198 * defined in the USB "Common Class" Spec (3.11). Individual class specs ··· 534 532 { 535 533 return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); 536 534 } 535 + 536 + /*-------------------------------------------------------------------------*/ 537 + 538 + /* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ 539 + struct usb_ep_comp_descriptor { 540 + __u8 bLength; 541 + __u8 bDescriptorType; 542 + 543 + __u8 bMaxBurst; 544 + __u8 bmAttributes; 545 + __u16 wBytesPerInterval; 546 + } __attribute__ ((packed)); 547 + 548 + #define USB_DT_EP_COMP_SIZE 6 537 549 538 550 /*-------------------------------------------------------------------------*/ 539 551