Re: [PATCH 0/3] USB: core: Don't overwrite device descriptor during reinitialization

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 09, 2023 at 09:47:14PM -0400, Alan Stern wrote:
> On Thu, Aug 10, 2023 at 12:28:27AM +0000, Thinh Nguyen wrote:

> > Testing from Greg's usb-next branch, this series causes problem with
> > device enumeration:
> > 
> > [   31.650759] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 2 using xhci_hcd
> > [   31.663107] usb 2-1: device descriptor read/8, error -71
> > [   31.952697] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 3 using xhci_hcd
> > [   31.965122] usb 2-1: device descriptor read/8, error -71
> > [   32.080991] usb usb2-port1: attempt power cycle
> > [   34.826893] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 5 using xhci_hcd
> > [   34.839241] usb 2-1: device descriptor read/8, error -71
> > [   35.129908] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 6 using xhci_hcd
> > [   35.142264] usb 2-1: device descriptor read/8, error -71
> > [   35.257155] usb usb2-port1: attempt power cycle
> > [   37.258922] usb 1-1: new high-speed USB device number 5 using xhci_hcd
> > [   38.115053] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 8 using xhci_hcd
> > [   38.127407] usb 2-1: device descriptor read/8, error -71
> > [   38.417066] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 9 using xhci_hcd
> > [   38.429428] usb 2-1: device descriptor read/8, error -71
> > [   38.545315] usb usb2-port1: attempt power cycle
> > [   43.347312] usb 2-2: new SuperSpeed Plus Gen 2x1 USB device number 11 using xhci_hcd
> > [   43.359659] usb 2-2: device descriptor read/8, error -71
> > [   43.649323] usb 2-2: new SuperSpeed Plus Gen 2x1 USB device number 12 using xhci_hcd
> > [   43.661681] usb 2-2: device descriptor read/8, error -71
> > [   43.777566] usb usb2-port2: attempt power cycle
> > 
> > I was testing with our host along with other common vendor hosts with a
> > few 3.x devices. Reverting this series resolves the issue. I didn't do
> > extensive tests for various speeds or debug it. I just want to notify
> > this first perhaps you can figure out the issue right away.
> > 
> > I can look into it and provide more info later this week. If you want to
> > print any debug, let me know and I can provide later this week.
> 
> Thanks for the notification.  The problem is almost certainly caused by 
> the first patch in the series, which changes the way that the initial 
> read/8 thing is done.  However, I have no idea what part of the patch 
> could be causing these errors.  I would appreciate anything you can find 
> out.
> 
> You should concentrate your initial investigation on the new 
> get_bMaxPacketSize0() routine.  In particular, does the -EPROTO error 
> value arise as the return value from the usb_control_msg() call, or does 
> it happen because of the values stored in buf?  In the first case, how 
> does this call differ from the one that used to be made by 
> usb_get_device_descriptor()?  And in the second case, what are the 
> values of rc, buf->bMaxPacketSize0, and buf->bDescriptorType?

Never mind; I found the problem.  I had forgotten that at SuperSpeed or 
faster, the device descriptor uses a logarithmic encoding for 
bMaxPacketSize0.

The patch below should fix things up.  Let me know how it goes.

Alan Stern



 drivers/usb/core/hub.c |   36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

Index: usb-devel/drivers/usb/core/hub.c
===================================================================
--- usb-devel.orig/drivers/usb/core/hub.c
+++ usb-devel/drivers/usb/core/hub.c
@@ -4705,7 +4705,7 @@ static int get_bMaxPacketSize0(struct us
 				buf, size,
 				initial_descriptor_timeout);
 		switch (buf->bMaxPacketSize0) {
-		case 8: case 16: case 32: case 64: case 255:
+		case 8: case 16: case 32: case 64: case 9:
 			if (buf->bDescriptorType == USB_DT_DEVICE) {
 				rc = buf->bMaxPacketSize0;
 				break;
@@ -4992,23 +4992,35 @@ hub_port_init(struct usb_hub *hub, struc
 	if (retval)
 		goto fail;
 
-	if (maxp0 == 0xff || udev->speed >= USB_SPEED_SUPER)
-		i = 512;
-	else
-		i = maxp0;
-	if (usb_endpoint_maxp(&udev->ep0.desc) != i) {
-		if (udev->speed == USB_SPEED_LOW ||
-				!(i == 8 || i == 16 || i == 32 || i == 64)) {
-			dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
-			retval = -EMSGSIZE;
-			goto fail;
-		}
+	/*
+	 * Check the ep0 maxpacket guess and correct it if necessary.
+	 * maxp0 is the value stored in the device descriptor;
+	 * i is the value it encodes (logarithmic for SuperSpeed or greater).
+	 */
+	i = maxp0;
+	if (udev->speed >= USB_SPEED_SUPER) {
+		if (maxp0 <= 16)
+			i = 1 << maxp0;
+		else
+			i = 0;		/* Invalid */
+	}
+	if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
+		;	/* Initial ep0 maxpacket guess is right */
+	} else if ((udev->speed == USB_SPEED_FULL ||
+				udev->speed == USB_SPEED_HIGH) &&
+			(i == 8 || i == 16 || i == 32 || i == 64)) {
+		/* Initial guess is wrong; use the descriptor's value */
 		if (udev->speed == USB_SPEED_FULL)
 			dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
 		else
 			dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
 		usb_ep0_reinit(udev);
+	} else {
+		/* Initial guess is wrong and descriptor's value is invalid */
+		dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", maxp0);
+		retval = -EMSGSIZE;
+		goto fail;
 	}
 
 	descr = usb_get_device_descriptor(udev);




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux