Commit be75e771 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] ehci enumerating full speed devices

The EHCI driver was never adjusting the full speed maximum packet size up
(when enumerating through a transaction translating hub).  This broke the
enumeration of some devices (maxpacket != 8) pretty early.

This patch updates EHCI to fix the bug, and does minor cleanup to usbcore
logic that figures out ep0 maxpacket.  I left the partial read in for all
speeds, even though only full speed needs it.
parent 1200021c
...@@ -942,12 +942,27 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -942,12 +942,27 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
int i; int i;
int j; int j;
/* USB v1.1 5.5.3 */ /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
/* We read the first 8 bytes from the device descriptor to get to */ * it's fixed size except for full speed devices.
/* the bMaxPacketSize0 field. Then we set the maximum packet size */ */
/* for the control pipe, and retrieve the rest */ switch (dev->speed) {
dev->epmaxpacketin [0] = 8; case USB_SPEED_HIGH: /* fixed at 64 */
dev->epmaxpacketout[0] = 8; i = 64;
break;
case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
/* to determine the ep0 maxpacket size, read the first 8
* bytes from the device descriptor to get bMaxPacketSize0;
* then correct our initial (small) guess.
*/
// FALLTHROUGH
case USB_SPEED_LOW: /* fixed at 8 */
i = 8;
break;
default:
return -EINVAL;
}
dev->epmaxpacketin [0] = i;
dev->epmaxpacketout[0] = i;
for (i = 0; i < NEW_DEVICE_RETRYS; ++i) { for (i = 0; i < NEW_DEVICE_RETRYS; ++i) {
...@@ -967,6 +982,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -967,6 +982,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
wait_ms(10); /* Let the SET_ADDRESS settle */ wait_ms(10); /* Let the SET_ADDRESS settle */
/* high and low speed devices don't need this... */
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
if (err >= 8) if (err >= 8)
break; break;
...@@ -982,8 +998,10 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -982,8 +998,10 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
dev->devnum = -1; dev->devnum = -1;
return 1; return 1;
} }
dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; if (dev->speed == USB_SPEED_FULL) {
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
}
err = usb_get_device_descriptor(dev); err = usb_get_device_descriptor(dev);
if (err < (signed)sizeof(dev->descriptor)) { if (err < (signed)sizeof(dev->descriptor)) {
......
...@@ -778,10 +778,26 @@ static struct ehci_qh *qh_append_tds ( ...@@ -778,10 +778,26 @@ static struct ehci_qh *qh_append_tds (
qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd = list_entry (qtd_list->next, struct ehci_qtd,
qtd_list); qtd_list);
/* maybe patch the qh used for set_address */ /* control qh may need patching after enumeration */
if (unlikely (epnum == 0 if (unlikely (epnum == 0)) {
&& le32_to_cpu (qh->hw_info1 & 0x7f) == 0)) /* set_address changes the address */
qh->hw_info1 |= cpu_to_le32 (usb_pipedevice(urb->pipe)); if (le32_to_cpu (qh->hw_info1 & 0x7f) == 0)
qh->hw_info1 |= cpu_to_le32 (
usb_pipedevice (urb->pipe));
/* for full speed, ep0 maxpacket can grow */
else if (!(qh->hw_info1 & cpu_to_le32 (0x3 << 12))) {
u32 info, max;
info = le32_to_cpu (qh->hw_info1);
max = urb->dev->descriptor.bMaxPacketSize0;
if (max > (0x07ff & (info >> 16))) {
info &= ~(0x07ff << 16);
info |= max << 16;
qh->hw_info1 = cpu_to_le32 (info);
}
}
}
/* append to tds already queued to this qh? */ /* append to tds already queued to this qh? */
if (unlikely (!list_empty (&qh->qtd_list) && qtd)) { if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment