ChangeSet 1.808.2.11, 2002/10/23 11:27:20-07:00, david-b@pacbell.net [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. diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Mon Oct 28 13:54:54 2002 +++ b/drivers/usb/core/usb.c Mon Oct 28 13:54:54 2002 @@ -942,12 +942,27 @@ int i; int j; - /* USB v1.1 5.5.3 */ - /* We read the first 8 bytes from the device descriptor to get to */ - /* the bMaxPacketSize0 field. Then we set the maximum packet size */ - /* for the control pipe, and retrieve the rest */ - dev->epmaxpacketin [0] = 8; - dev->epmaxpacketout[0] = 8; + /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... + * it's fixed size except for full speed devices. + */ + switch (dev->speed) { + case USB_SPEED_HIGH: /* fixed at 64 */ + 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) { @@ -967,6 +982,7 @@ 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); if (err >= 8) break; @@ -982,8 +998,10 @@ dev->devnum = -1; return 1; } - dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; - dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; + if (dev->speed == USB_SPEED_FULL) { + dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; + dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; + } err = usb_get_device_descriptor(dev); if (err < (signed)sizeof(dev->descriptor)) { diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Mon Oct 28 13:54:54 2002 +++ b/drivers/usb/host/ehci-q.c Mon Oct 28 13:54:54 2002 @@ -778,10 +778,26 @@ qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); - /* maybe patch the qh used for set_address */ - if (unlikely (epnum == 0 - && le32_to_cpu (qh->hw_info1 & 0x7f) == 0)) - qh->hw_info1 |= cpu_to_le32 (usb_pipedevice(urb->pipe)); + /* control qh may need patching after enumeration */ + if (unlikely (epnum == 0)) { + /* set_address changes the address */ + 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? */ if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {