Kevin Owen wrote:
I have found a problem in linux-2.4.22 with resetting usb 1.1 devices that are attached through a transaction translator to an EHCI controller. My setup to produce this problem is to connect a usb 2.0 hub to a usb 2.0 port, then connect a usb 1.1 hub to the 2.0 hub, then connect a 1.1 device to the 1.1 hub. If at this point a usb device reset is sent to the 1.1 device, the 1.1 hub's port is reset, then a set_address is sent to the device, but this fails (-32). After some

It's too darn bad that's such a common configuration! ;)


But this issue looks generic; any device being reset might see
this particular problem, though maybe your hardware setup only
generated the need for a reset in this case.  And 2.6 will need
this fixed too.


analysis, the urb to send the set_address is fine, contains device address 0, however in the EHCI driver (ehci-q.c), the reuse of queue heads means that the set_address is sent out on the wire to device 4 (confirmed with usb 1.1 wire-level analyzer), which was the previous address of the device to be reset. As the device has just been reset, it really has address 0, so it is no wonder the set_address fails. The

Aha! So this is another subtle usb_device_reset() failure.


Thanks for tracking this down.


following patch seems to fix the problem, sensing when the urb is to device 0, and patching this into the re-used queue heads, then letting the existing code write the queue heads device address back to the just-set address on the next transfer.

Actually a "patch" would be "diff -u old new" output. Other than whitespace changes, I think your bugfix is much simpler, like the attached patch.

- Dave



--- 1.16/drivers/usb/host/ehci-q.c      Thu Jun 19 06:51:52 2003
+++ edited/drivers/usb/host/ehci-q.c    Wed Aug 13 09:58:53 2003
@@ -832,6 +832,10 @@
                                        qh->hw_info1 = cpu_to_le32 (info);
                                }
                        }
+
+                        /* usb_reset_device() briefly reverts to address 0 */
+                        if (usb_pipedevice (urb->pipe) == 0)
+                                qh->hw_info1 &= cpu_to_le32(~0x7f);
                }
 
                /* NOTE:  changing config or interface setting is not

Reply via email to