From owner-p4-projects@FreeBSD.ORG Tue Jan 16 00:16:11 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 111C116A417; Tue, 16 Jan 2007 00:16:11 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id D4D1C16A407 for ; Tue, 16 Jan 2007 00:16:10 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id C679013C459 for ; Tue, 16 Jan 2007 00:16:10 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id l0G0GAl1048801 for ; Tue, 16 Jan 2007 00:16:10 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id l0G0GAVC048798 for perforce@freebsd.org; Tue, 16 Jan 2007 00:16:10 GMT (envelope-from hselasky@FreeBSD.org) Date: Tue, 16 Jan 2007 00:16:10 GMT Message-Id: <200701160016.l0G0GAVC048798@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 112964 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Jan 2007 00:16:11 -0000 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