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)) {
