Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Jan 2007 00:16:10 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 112964 for review
Message-ID:  <200701160016.l0G0GAVC048798@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=112964

Change 112964 by hselasky@hselasky_mini_itx on 2007/01/16 00:16:00

	New USB detach order: Top to bottom instead of bottom to top.
	This lets the USB device drivers choose when to detach the
	children from the "device_detach" bus method. For example
	some APIs like the MII-bus API requires certain steps to
	be taken before it can be detached. In general this is
	about preventing "downcalls" after that the child has
	been detached. If the child is detached before the
	"device_detach" method of the parent is invoked,
	there is no easy way to know when to stop "downcalls"
	in the device hierarchy.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/ehci_pci.c#11 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci_pci.c#11 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci_pci.c#10 edit
.. //depot/projects/usb/src/sys/dev/usb/uhub.c#8 edit
.. //depot/projects/usb/src/sys/dev/usb/usb.c#9 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#22 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#26 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/ehci_pci.c#11 (text+ko) ====

@@ -88,6 +88,13 @@
 static void ehci_pci_givecontroller(device_t self);
 static void ehci_pci_takecontroller(device_t self);
 
+static device_probe_t ehci_pci_probe;
+static device_attach_t ehci_pci_attach;
+static device_detach_t ehci_pci_detach;
+static device_suspend_t ehci_pci_suspend;
+static device_resume_t ehci_pci_resume;
+static device_shutdown_t ehci_pci_shutdown;
+
 static int
 ehci_pci_suspend(device_t self)
 {
@@ -200,9 +207,6 @@
 }
 
 static int
-ehci_pci_detach(device_t self);
-
-static int
 ehci_pci_attach(device_t self)
 {
 	ehci_softc_t *sc = device_get_softc(self);
@@ -364,10 +368,14 @@
 
 	if(sc->sc_bus.bdev)
 	{
+		device_detach(sc->sc_bus.bdev);
 		device_delete_child(self, sc->sc_bus.bdev);
 		sc->sc_bus.bdev = NULL;
 	}
 
+	/* during module unload there are lots of children leftover */
+	device_delete_all_children(self);
+
 	pci_disable_busmaster(self);
 
 	/*

==== //depot/projects/usb/src/sys/dev/usb/ohci_pci.c#11 (text+ko) ====

@@ -80,10 +80,11 @@
 
 #define PCI_OHCI_BASE_REG	0x10
 
-static int ohci_pci_attach(device_t self);
-static int ohci_pci_detach(device_t self);
-static int ohci_pci_suspend(device_t self);
-static int ohci_pci_resume(device_t self);
+static device_probe_t ohci_pci_probe;
+static device_attach_t ohci_pci_attach;
+static device_detach_t ohci_pci_detach;
+static device_suspend_t ohci_pci_suspend;
+static device_resume_t ohci_pci_resume;
 
 static int
 ohci_pci_suspend(device_t self)
@@ -331,10 +332,14 @@
 
 	if(sc->sc_bus.bdev)
 	{
+		device_detach(sc->sc_bus.bdev);
 		device_delete_child(self, sc->sc_bus.bdev);
 		sc->sc_bus.bdev = NULL;
 	}
 
+	/* during module unload there are lots of children leftover */
+	device_delete_all_children(self);
+
 	pci_disable_busmaster(self);
 
 	if(sc->irq_res && sc->ih)

==== //depot/projects/usb/src/sys/dev/usb/uhci_pci.c#10 (text+ko) ====

@@ -73,10 +73,11 @@
 
 #define PCI_UHCI_BASE_REG               0x20
 
-static int uhci_pci_attach(device_t self);
-static int uhci_pci_detach(device_t self);
-static int uhci_pci_suspend(device_t self);
-static int uhci_pci_resume(device_t self);
+static device_probe_t uhci_pci_probe;
+static device_attach_t uhci_pci_attach;
+static device_detach_t uhci_pci_detach;
+static device_suspend_t uhci_pci_suspend;
+static device_resume_t uhci_pci_resume;
 
 static int
 uhci_pci_suspend(device_t self)
@@ -330,10 +331,14 @@
 
 	if(sc->sc_bus.bdev)
 	{
+		device_detach(sc->sc_bus.bdev);
 		device_delete_child(self, sc->sc_bus.bdev);
 		sc->sc_bus.bdev = NULL;
 	}
 
+	/* during module unload there are lots of children leftover */
+	device_delete_all_children(self);
+
 	/*
 	 * disable interrupts that might have been switched on in
 	 * uhci_init.

==== //depot/projects/usb/src/sys/dev/usb/uhub.c#8 (text+ko) ====

@@ -599,6 +599,9 @@
 
 	DPRINTF(("sc=%port\n", sc));
 
+	/* detach all children first */
+	bus_generic_detach(dev);
+
 	if(hub == NULL)		/* must be partially working */
 	{
 		return (0);

==== //depot/projects/usb/src/sys/dev/usb/usb.c#9 (text+ko) ====

@@ -587,6 +587,9 @@
 		       "usb wait explore", 0);
 	}
 
+	/* detach children first */
+	bus_generic_detach(dev);
+
 	if(bus->root_port.device != NULL)
 	{
 		/* free device, but not sub-devices,

==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#22 (text+ko) ====

@@ -1439,8 +1439,12 @@
 
 			printf("(addr %d) disconnected\n", udev->address);
 
-			/* device_delete_child() will detach all sub-devices ! */
-			if(device_delete_child
+			/* first detach the child to give the child's detach routine
+			 * a chance to detach the sub-devices in the correct order.
+			 * Then delete the child using "device_delete_child()" which
+			 * will detach all sub-devices from the bottom and upwards!
+			 */
+			if (device_detach(subdev[0]) || device_delete_child
 				(device_get_parent(subdev[0]), subdev[0]))
 			{
 				/* if detach fails sub-devices will still
@@ -2650,3 +2654,26 @@
 	}
 	return (m_new);
 }
+
+/*---------------------------------------------------------------------------*
+ * device_delete_all_children - delete all children of a device
+ *---------------------------------------------------------------------------*/
+int32_t
+device_delete_all_children(device_t dev)
+{
+	device_t *devlist;
+	int32_t devcount;
+	int32_t error;
+
+	error = device_get_children(dev, &devlist, &devcount);
+	if (error == 0) {
+	    while (devcount-- > 0) {
+	        error = device_delete_child(dev, devlist[devcount]);
+		if (error) {
+		    break;
+		}
+	    }
+	    free(devlist, M_TEMP);
+	}
+	return error;
+}

==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#26 (text+ko) ====

@@ -739,6 +739,8 @@
 struct mbuf *
 usbd_ether_get_mbuf(void);
 
+int32_t device_delete_all_children(device_t dev);
+
 /* routines from usb.c */
 
 #if 0



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