Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 08 Sep 2004 11:37:07 -0600 (MDT)
From:      "M. Warner Losh" <imp@bsdimp.com>
To:        roam@ringlet.net
Cc:        freebsd-current@freebsd.org
Subject:   Re: [PATCH] Fix USB panics
Message-ID:  <20040908.113707.54185659.imp@bsdimp.com>
In-Reply-To: <20040908150943.GA1924@straylight.m.ringlet.net>
References:  <20040908150943.GA1924@straylight.m.ringlet.net>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Wed_Sep__8_11:37:07_2004_385)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Peter,

thanks again for the excellent anaylsis of the problem.  I introduced
this when I cleaned up the load a driver will now cause usb to attach
a device case.  You are correct as far as I can tell and can test.
Here's the patch that I've come up with.  Does it work for you?

Warner

----Next_Part(Wed_Sep__8_11:37:07_2004_385)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename=usb-diff

? P
? PP
Index: uhub.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/uhub.c,v
retrieving revision 1.62
diff -u -r1.62 uhub.c
--- uhub.c	15 Aug 2004 23:39:18 -0000	1.62
+++ uhub.c	8 Sep 2004 17:34:21 -0000
@@ -90,7 +90,6 @@
 Static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status);
 
 #if defined(__FreeBSD__)
-Static bus_child_detached_t uhub_child_detached;
 Static bus_child_location_str_t uhub_child_location_str;
 Static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str;
 #endif
@@ -110,7 +109,6 @@
     uhub_match, uhub_attach, uhub_detach, uhub_activate);
 #elif defined(__FreeBSD__)
 USB_DECLARE_DRIVER_INIT(uhub,
-	DEVMETHOD(bus_child_detached, uhub_child_detached),
 	DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
 	DEVMETHOD(bus_child_location_str, uhub_child_location_str),
 	DEVMETHOD(bus_driver_added, bus_generic_driver_added),
@@ -123,7 +121,6 @@
 devclass_t uhubroot_devclass;
 
 Static device_method_t uhubroot_methods[] = {
-	DEVMETHOD(bus_child_detached, uhub_child_detached),
 	DEVMETHOD(bus_child_location_str, uhub_child_location_str),
 	DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
 	DEVMETHOD(bus_driver_added, bus_generic_driver_added),
@@ -378,15 +375,17 @@
 		DPRINTFN(3,("uhub_explore: %s port %d status 0x%04x 0x%04x\n",
 			    USBDEVNAME(sc->sc_dev), port, status, change));
 		if (change & UPS_C_PORT_ENABLED) {
-			DPRINTF(("uhub_explore: C_PORT_ENABLED\n"));
+			DPRINTF(("uhub_explore: C_PORT_ENABLED 0x%x\n", change));
 			usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);
 			if (change & UPS_C_CONNECT_STATUS) {
+			    printf("Change is 0x%x\n", change);
 				/* Ignore the port error if the device
 				   vanished. */
 			} else if (status & UPS_PORT_ENABLED) {
 				printf("%s: illegal enable change, port %d\n",
 				       USBDEVNAME(sc->sc_dev), port);
 			} else {
+			    printf("up->restartcnt is %d change is %x\n", up->restartcnt, change);
 				/* Port error condition. */
 				if (up->restartcnt) /* no message first time */
 					printf("%s: port error, restarting "
@@ -398,7 +397,7 @@
 				else
 					printf("%s: port error, giving up "
 					       "port %d\n",
-					       USBDEVNAME(sc->sc_dev), port);
+					  USBDEVNAME(sc->sc_dev), port);
 			}
 		}
 		if (!(change & UPS_C_CONNECT_STATUS)) {
@@ -683,35 +682,6 @@
 		    iface->idesc->bInterfaceSubClass);
 	}
 	return (0);
-}
-
-/* Called when a device has been detached from it */
-Static void
-uhub_child_detached(device_t self, device_t child)
-{
-	struct uhub_softc *sc = device_get_softc(self);
-	usbd_device_handle devhub = sc->sc_hub;
-	usbd_device_handle dev;
-	int nports;
-	int port;
-	int i;
-
-	if (!devhub->hub)
-		/* should never happen; children are only created after init */
-		panic("hub not fully initialised, but child deleted?");
-
-	nports = devhub->hub->hubdesc.bNbrPorts;
-	for (port = 0; port < nports; port++) {
-		dev = devhub->hub->ports[port].device;
-		if (dev == NULL || dev->subdevs == NULL)
-			continue;
-		for (i = 0; dev->subdevs[i]; i++) {
-			if (dev->subdevs[i] == child) {
-				dev->subdevs[i] = NULL;
-				return;
-			}
-		}
-	}
 }
 #endif
 
Index: usb_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.69
diff -u -r1.69 usb_subr.c
--- usb_subr.c	15 Aug 2004 23:39:18 -0000	1.69
+++ usb_subr.c	8 Sep 2004 17:34:21 -0000
@@ -905,6 +905,10 @@
 	if (dv) {
 		return (USBD_NORMAL_COMPLETION);
 	}
+	/*
+	 * Free subdevs so we can reallocate it larger for the number of
+	 * interfaces 
+	 */
 	tmpdv = dev->subdevs;
 	dev->subdevs = NULL;
 	free(tmpdv, M_USB);
@@ -1016,9 +1020,6 @@
 	if (dv != NULL) {
 		return (USBD_NORMAL_COMPLETION);
 	}
-	tmpdv = dev->subdevs;
-	dev->subdevs = 0;
-	free(tmpdv, M_USB);
 
 	/*
 	 * The generic attach failed, but leave the device as it is.
@@ -1346,11 +1347,13 @@
 	di->udi_speed = dev->speed;
 
 	if (dev->subdevs != NULL) {
-		for (i = 0; dev->subdevs[i] &&
-			     i < USB_MAX_DEVNAMES; i++) {
-			strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
-				USB_MAX_DEVNAMELEN);
-			di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
+		for (i = 0; dev->subdevs[i] && i < USB_MAX_DEVNAMES; i++) {
+			if (device_is_attached(dev->subdevs[i]))
+				strlcpy(di->udi_devnames[i],
+				    USBDEVPTRNAME(dev->subdevs[i]),
+				    USB_MAX_DEVNAMELEN);
+			else
+				di->udi_devnames[i][0] = 0;
                 }
         } else {
                 i = 0;

----Next_Part(Wed_Sep__8_11:37:07_2004_385)----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040908.113707.54185659.imp>