usb/103167: Transcend JetFlash120 memory stick problem (with fix)

Ian Dowse iedowse at iedowse.com
Sat Sep 30 05:19:18 PDT 2006


In message <200609270350.k8R3oLN6026871 at freefall.freebsd.org>, Tor Egge writes:
> I had a similar problem (getting first desc failed).  Setting ehcidebug to a
> high value hid the problem due to timing changes.
> 
> I first thought it was the race described in
> <URL:http://lkml.org/lkml/2004/12/1/131>, but the system behavior didn't match
> that race.
> 
> Address changes in the queue head might not have an immediate effect.  I ended
> up adding a 1ms delay after any address change as a workaround.

Good catch - hardware caching of the old address would certainly
explain the errors. Maybe it is safer to just close and reopen the
default pipe after changing important parameters - could someone
try the following patch instead to see if it works?

This would avoid the need to change the QH while it is visible to
the hardware, so the code and XXX comments in [eo]hci_device_request()
for doing this could be removed.

Ian

Index: usb_subr.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.86
diff -u -r1.86 usb_subr.c
--- usb_subr.c	10 Sep 2006 15:20:39 -0000	1.86
+++ usb_subr.c	30 Sep 2006 12:04:42 -0000
@@ -1110,6 +1110,15 @@
 	dev->address = addr;	/* New device address now */
 	bus->devices[addr] = dev;
 
+	/* Re-establish the default pipe with the new address. */
+	usbd_kill_pipe(dev->default_pipe);
+	err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+	    &dev->default_pipe);
+	if (err) {
+		usbd_remove_device(dev, up);
+		return (err);
+	}
+
 	dd = &dev->ddesc;
 	/* Get the first 8 bytes of the device descriptor. */
 	err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
@@ -1153,6 +1162,15 @@
 
 	USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
 
+	/* Re-establish the default pipe with the new max packet size. */
+	usbd_kill_pipe(dev->default_pipe);
+	err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+	    &dev->default_pipe);
+	if (err) {
+		usbd_remove_device(dev, up);
+		return (err);
+	}
+
 	err = usbd_reload_device_desc(dev);
 	if (err) {
 		DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "


More information about the freebsd-usb mailing list