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>
This commit is contained in:
parent
b7d6d99896
commit
9f8e443816
|
@ -80,38 +80,18 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
|
||||||
int max_tx;
|
int max_tx;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Allocate space for the SS endpoint companion descriptor */
|
|
||||||
ep->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!ep->ss_ep_comp)
|
|
||||||
return -ENOMEM;
|
|
||||||
desc = (struct usb_ss_ep_comp_descriptor *) buffer;
|
desc = (struct usb_ss_ep_comp_descriptor *) buffer;
|
||||||
if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
|
if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
|
||||||
dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
|
dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
|
||||||
" interface %d altsetting %d ep %d: "
|
" interface %d altsetting %d ep %d: "
|
||||||
"using minimum values\n",
|
"using minimum values\n",
|
||||||
cfgno, inum, asnum, ep->desc.bEndpointAddress);
|
cfgno, inum, asnum, ep->desc.bEndpointAddress);
|
||||||
ep->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
|
|
||||||
ep->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
|
|
||||||
ep->ss_ep_comp->desc.bMaxBurst = 0;
|
|
||||||
/*
|
|
||||||
* Leave bmAttributes as zero, which will mean no streams for
|
|
||||||
* bulk, and isoc won't support multiple bursts of packets.
|
|
||||||
* With bursts of only one packet, and a Mult of 1, the max
|
|
||||||
* amount of data moved per endpoint service interval is one
|
|
||||||
* packet.
|
|
||||||
*/
|
|
||||||
if (usb_endpoint_xfer_isoc(&ep->desc) ||
|
|
||||||
usb_endpoint_xfer_int(&ep->desc))
|
|
||||||
ep->ss_ep_comp->desc.wBytesPerInterval =
|
|
||||||
ep->desc.wMaxPacketSize;
|
|
||||||
/*
|
/*
|
||||||
* The next descriptor is for an Endpoint or Interface,
|
* The next descriptor is for an Endpoint or Interface,
|
||||||
* no extra descriptors to copy into the companion structure,
|
* no extra descriptors to copy into the companion structure,
|
||||||
* and we didn't eat up any of the buffer.
|
* and we didn't eat up any of the buffer.
|
||||||
*/
|
*/
|
||||||
retval = 0;
|
return 0;
|
||||||
goto valid;
|
|
||||||
}
|
}
|
||||||
memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
|
memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
|
||||||
desc = &ep->ss_ep_comp->desc;
|
desc = &ep->ss_ep_comp->desc;
|
||||||
|
@ -320,6 +300,28 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
||||||
buffer += i;
|
buffer += i;
|
||||||
size -= i;
|
size -= i;
|
||||||
|
|
||||||
|
/* Allocate space for the SS endpoint companion descriptor */
|
||||||
|
endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!endpoint->ss_ep_comp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Fill in some default values (may be overwritten later) */
|
||||||
|
endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
|
||||||
|
endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
|
||||||
|
endpoint->ss_ep_comp->desc.bMaxBurst = 0;
|
||||||
|
/*
|
||||||
|
* Leave bmAttributes as zero, which will mean no streams for
|
||||||
|
* bulk, and isoc won't support multiple bursts of packets.
|
||||||
|
* With bursts of only one packet, and a Mult of 1, the max
|
||||||
|
* amount of data moved per endpoint service interval is one
|
||||||
|
* packet.
|
||||||
|
*/
|
||||||
|
if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
|
||||||
|
usb_endpoint_xfer_int(&endpoint->desc))
|
||||||
|
endpoint->ss_ep_comp->desc.wBytesPerInterval =
|
||||||
|
endpoint->desc.wMaxPacketSize;
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
|
retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
|
||||||
inum, asnum, endpoint, num_ep, buffer,
|
inum, asnum, endpoint, num_ep, buffer,
|
||||||
|
@ -329,6 +331,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
||||||
retval = buffer - buffer0;
|
retval = buffer - buffer0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
dev_warn(ddev, "config %d interface %d altsetting %d "
|
||||||
|
"endpoint 0x%X has no "
|
||||||
|
"SuperSpeed companion descriptor\n",
|
||||||
|
cfgno, inum, asnum, d->bEndpointAddress);
|
||||||
retval = buffer - buffer0;
|
retval = buffer - buffer0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue