Subject: kern/36459: uhub_explore failure with slow device
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <mlelstv@serpens.de>
List: netbsd-bugs
Date: 06/08/2007 17:40:00
>Number: 36459
>Category: kern
>Synopsis: uhub_explore failure with slow device
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jun 08 17:40:00 +0000 2007
>Originator: Michael van Elst
>Release: NetBSD 4.0_BETA2
>Organization:
--
Michael van Elst
Internet: mlelstv@serpens.de
"A potential Snark may lurk in every tree."
>Environment:
System: NetBSD henery 4.0_BETA2 NetBSD 4.0_BETA2 (HENERY) #1: Sun Jun 3 12:09:36 CEST 2007 mlelstv@henery:/home/netbsd4/obj/home/netbsd4/src/sys/arch/i386/compile/HENERY i386
Architecture: i386
Machine: i386
>Description:
When testing a Fusion 3G card (cardbus UMTS/GPRS/WLAN) I got errors
from uhub_explore:
usb_new_device: set address 2 failed
uhub_explore: usb_new_device failed, error=SET_ADDR_FAILED
uhub5: device problem, disabling port 1
Apparently the device is too slow. FreeBSD does a few retries
in this case.
>How-To-Repeat:
Try to use the Fusion 3G card with NetBSD4.
>Fix:
After merging the relevant code from FreeBSD the card works fine.
Here is the patch:
Index: usb_subr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.146
diff -u -r1.146 usb_subr.c
--- usb_subr.c 30 Mar 2007 16:52:12 -0000 1.146
+++ usb_subr.c 15 Apr 2007 10:56:13 -0000
@@ -1044,8 +1044,19 @@
}
/* Set the address. Do this early; some devices need that. */
- err = usbd_set_address(dev, addr);
+ /* Try a few times in case the device is slow (i.e. outside specs) */
DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
+ for (i = 0; i < 15; i++) {
+ err = usbd_set_address(dev, addr);
+ if (!err)
+ break;
+ usbd_delay_ms(dev, 200);
+ if ((i % 3) == 3) {
+ DPRINTFN(-1,("usbd_new_device: set address %d "
+ "failed - trying a port reset\n", addr));
+ usbd_reset_port(up->parent, port, &ps);
+ }
+ }
if (err) {
DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
err = USBD_SET_ADDR_FAILED;
>Unformatted: