aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-07-27 15:04:52 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-07-28 17:31:13 -0400
commit9f8e443816976edd68f415ea25c0223ea921e88c (patch)
tree3bf74326b6ee6e4256e3166a909d96d3e3569394 /drivers/usb
parentb7d6d99896a6cf38dc354d673afd3fbde10b86c2 (diff)
USB: Fix parsing of SuperSpeed Endpoint Companion descriptor.
usb_parse_ss_endpoint_companion() was supposed to allocate a structure to hold the SuperSpeed Endpoint Companion descriptor, and either copy the values the device returned, or fill in default values if the device descriptor did not include the companion descriptor. However, the previous code would miss the last endpoint in a configuration with no descriptors after it. Make usb_parse_endpoint() allocate the SS endpoint companion descriptor and fill it with default values, even if we've run out of buffer space in this configuration descriptor. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/config.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 24dfb33f90cb..a16c538d0132 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -80,38 +80,18 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
80 int max_tx; 80 int max_tx;
81 int i; 81 int i;
82 82
83 /* Allocate space for the SS endpoint companion descriptor */
84 ep->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
85 GFP_KERNEL);
86 if (!ep->ss_ep_comp)
87 return -ENOMEM;
88 desc = (struct usb_ss_ep_comp_descriptor *) buffer; 83 desc = (struct usb_ss_ep_comp_descriptor *) buffer;
89 if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) { 84 if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
90 dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " 85 dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
91 " interface %d altsetting %d ep %d: " 86 " interface %d altsetting %d ep %d: "
92 "using minimum values\n", 87 "using minimum values\n",
93 cfgno, inum, asnum, ep->desc.bEndpointAddress); 88 cfgno, inum, asnum, ep->desc.bEndpointAddress);
94 ep->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
95 ep->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
96 ep->ss_ep_comp->desc.bMaxBurst = 0;
97 /*
98 * Leave bmAttributes as zero, which will mean no streams for
99 * bulk, and isoc won't support multiple bursts of packets.
100 * With bursts of only one packet, and a Mult of 1, the max
101 * amount of data moved per endpoint service interval is one
102 * packet.
103 */
104 if (usb_endpoint_xfer_isoc(&ep->desc) ||
105 usb_endpoint_xfer_int(&ep->desc))
106 ep->ss_ep_comp->desc.wBytesPerInterval =
107 ep->desc.wMaxPacketSize;
108 /* 89 /*
109 * The next descriptor is for an Endpoint or Interface, 90 * The next descriptor is for an Endpoint or Interface,
110 * no extra descriptors to copy into the companion structure, 91 * no extra descriptors to copy into the companion structure,
111 * and we didn't eat up any of the buffer. 92 * and we didn't eat up any of the buffer.
112 */ 93 */
113 retval = 0; 94 return 0;
114 goto valid;
115 } 95 }
116 memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE); 96 memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
117 desc = &ep->ss_ep_comp->desc; 97 desc = &ep->ss_ep_comp->desc;
@@ -320,6 +300,28 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
320 buffer += i; 300 buffer += i;
321 size -= i; 301 size -= i;
322 302
303 /* Allocate space for the SS endpoint companion descriptor */
304 endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
305 GFP_KERNEL);
306 if (!endpoint->ss_ep_comp)
307 return -ENOMEM;
308
309 /* Fill in some default values (may be overwritten later) */
310 endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
311 endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
312 endpoint->ss_ep_comp->desc.bMaxBurst = 0;
313 /*
314 * Leave bmAttributes as zero, which will mean no streams for
315 * bulk, and isoc won't support multiple bursts of packets.
316 * With bursts of only one packet, and a Mult of 1, the max
317 * amount of data moved per endpoint service interval is one
318 * packet.
319 */
320 if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
321 usb_endpoint_xfer_int(&endpoint->desc))
322 endpoint->ss_ep_comp->desc.wBytesPerInterval =
323 endpoint->desc.wMaxPacketSize;
324
323 if (size > 0) { 325 if (size > 0) {
324 retval = usb_parse_ss_endpoint_companion(ddev, cfgno, 326 retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
325 inum, asnum, endpoint, num_ep, buffer, 327 inum, asnum, endpoint, num_ep, buffer,
@@ -329,6 +331,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
329 retval = buffer - buffer0; 331 retval = buffer - buffer0;
330 } 332 }
331 } else { 333 } else {
334 dev_warn(ddev, "config %d interface %d altsetting %d "
335 "endpoint 0x%X has no "
336 "SuperSpeed companion descriptor\n",
337 cfgno, inum, asnum, d->bEndpointAddress);
332 retval = buffer - buffer0; 338 retval = buffer - buffer0;
333 } 339 }
334 } else { 340 } else {