From 7b9617f5df756060667ca937a66785ea43b93312 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 8 Jan 2007 01:29:51 +0000 Subject: [PATCH] Add device to hierarchy before calling the driver's probe() function; this way everything remains consistent if the probe() ends up creating child devices. --- src/core/device.c | 33 ++++++++++++++++++--------------- src/drivers/bus/pci.c | 37 ++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/core/device.c b/src/core/device.c index e54ab297..567d9015 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -16,6 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -34,35 +35,32 @@ static struct root_device root_devices_end[0] __table_end ( root_devices ); static LIST_HEAD ( devices ); /** - * Register a root device + * Probe a root device * * @v rootdev Root device * @ret rc Return status code - * - * Calls the root device driver's probe() method, and adds it to the - * list of registered root devices if successful. */ -static int register_rootdev ( struct root_device *rootdev ) { +static int rootdev_probe ( struct root_device *rootdev ) { int rc; - DBG ( "Registering %s root bus\n", rootdev->name ); - - if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 ) + DBG ( "Adding %s root bus\n", rootdev->name ); + if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 ) { + DBG ( "Failed to add %s root bus: %s\n", + rootdev->name, strerror ( rc ) ); return rc; + } - list_add ( &rootdev->dev.siblings, &devices ); return 0; } /** - * Unregister a root device + * Remove a root device * * @v rootdev Root device */ -static void unregister_rootdev ( struct root_device *rootdev ) { +static void rootdev_remove ( struct root_device *rootdev ) { rootdev->driver->remove ( rootdev ); - list_del ( &rootdev->dev.siblings ); - DBG ( "Unregistered %s root bus\n", rootdev->name ); + DBG ( "Removed %s root bus\n", rootdev->name ); } /** @@ -76,9 +74,13 @@ static void unregister_rootdev ( struct root_device *rootdev ) { */ int probe_devices ( void ) { struct root_device *rootdev; + int rc; for ( rootdev = root_devices; rootdev < root_devices_end; rootdev++ ) { - register_rootdev ( rootdev ); + list_add ( &rootdev->dev.siblings, &devices ); + INIT_LIST_HEAD ( &rootdev->dev.children ); + if ( ( rc = rootdev_probe ( rootdev ) ) != 0 ) + list_del ( &rootdev->dev.siblings ); } return 0; } @@ -92,6 +94,7 @@ void remove_devices ( void ) { struct root_device *tmp; list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) { - unregister_rootdev ( rootdev ); + rootdev_remove ( rootdev ); + list_del ( &rootdev->dev.siblings ); } } diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c index c8dbb35d..0abc1e9c 100644 --- a/src/drivers/bus/pci.c +++ b/src/drivers/bus/pci.c @@ -165,23 +165,22 @@ void adjust_pci_device ( struct pci_device *pci ) { } /** - * Register PCI device + * Probe a PCI device * * @v pci PCI device * @ret rc Return status code * * Searches for a driver for the PCI device. If a driver is found, - * its probe() routine is called, and the device is added to the - * device hierarchy. + * its probe() routine is called. */ -static int register_pcidev ( struct pci_device *pci ) { +static int pci_probe ( struct pci_device *pci ) { struct pci_driver *driver; struct pci_device_id *id; unsigned int i; int rc; - DBG ( "Registering PCI device %02x:%02x.%x (%04x:%04x mem %lx " - "io %lx irq %d)\n", pci->bus, PCI_SLOT ( pci->devfn ), + DBG ( "Adding PCI device %02x:%02x.%x (%04x:%04x mem %lx io %lx " + "irq %d)\n", pci->bus, PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ), pci->vendor, pci->device, pci->membase, pci->ioaddr, pci->irq ); @@ -198,8 +197,6 @@ static int register_pcidev ( struct pci_device *pci ) { DBG ( "......probe failed\n" ); continue; } - list_add ( &pci->dev.siblings, - &pci->dev.parent->children ); return 0; } } @@ -209,17 +206,13 @@ static int register_pcidev ( struct pci_device *pci ) { } /** - * Unregister a PCI device + * Remove a PCI device * * @v pci PCI device - * - * Calls the device's driver's remove() routine, and removes the - * device from the device hierarchy. */ -static void unregister_pcidev ( struct pci_device *pci ) { +static void pci_remove ( struct pci_device *pci ) { pci->driver->remove ( pci ); - list_del ( &pci->dev.siblings ); - DBG ( "Unregistered PCI device %02x:%02x.%x\n", pci->bus, + DBG ( "Removed PCI device %02x:%02x.%x\n", pci->bus, PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ) ); } @@ -278,15 +271,19 @@ static int pcibus_probe ( struct root_device *rootdev ) { pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq ); pci_read_bases ( pci ); - INIT_LIST_HEAD ( &pci->dev.children ); + + /* Add to device hierarchy */ pci->dev.parent = &rootdev->dev; + list_add ( &pci->dev.siblings, &rootdev->dev.children); + INIT_LIST_HEAD ( &pci->dev.children ); /* Look for a driver */ - if ( register_pcidev ( pci ) == 0 ) { + if ( pci_probe ( pci ) == 0 ) { /* pcidev registered, we can drop our ref */ pci = NULL; } else { /* Not registered; re-use struct pci_device */ + list_del ( &pci->dev.siblings ); } } } @@ -311,7 +308,8 @@ static void pcibus_remove ( struct root_device *rootdev ) { list_for_each_entry_safe ( pci, tmp, &rootdev->dev.children, dev.siblings ) { - unregister_pcidev ( pci ); + pci_remove ( pci ); + list_del ( &pci->dev.siblings ); free ( pci ); } } @@ -326,7 +324,4 @@ static struct root_driver pci_root_driver = { struct root_device pci_root_device __root_device = { .name = "PCI", .driver = &pci_root_driver, - .dev = { - .children = LIST_HEAD_INIT ( pci_root_device.dev.children ), - }, };