mirror of https://github.com/ipxe/ipxe.git
Add device to hierarchy before calling the driver's probe() function; this
way everything remains consistent if the probe() ends up creating child devices.pull/1/head
parent
d3558fdd3a
commit
7b9617f5df
|
@ -16,6 +16,7 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <gpxe/list.h>
|
#include <gpxe/list.h>
|
||||||
#include <gpxe/tables.h>
|
#include <gpxe/tables.h>
|
||||||
#include <gpxe/device.h>
|
#include <gpxe/device.h>
|
||||||
|
@ -34,35 +35,32 @@ static struct root_device root_devices_end[0] __table_end ( root_devices );
|
||||||
static LIST_HEAD ( devices );
|
static LIST_HEAD ( devices );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a root device
|
* Probe a root device
|
||||||
*
|
*
|
||||||
* @v rootdev Root device
|
* @v rootdev Root device
|
||||||
* @ret rc Return status code
|
* @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;
|
int rc;
|
||||||
|
|
||||||
DBG ( "Registering %s root bus\n", rootdev->name );
|
DBG ( "Adding %s root bus\n", rootdev->name );
|
||||||
|
if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 ) {
|
||||||
if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 )
|
DBG ( "Failed to add %s root bus: %s\n",
|
||||||
|
rootdev->name, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
list_add ( &rootdev->dev.siblings, &devices );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister a root device
|
* Remove a root device
|
||||||
*
|
*
|
||||||
* @v rootdev 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 );
|
rootdev->driver->remove ( rootdev );
|
||||||
list_del ( &rootdev->dev.siblings );
|
DBG ( "Removed %s root bus\n", rootdev->name );
|
||||||
DBG ( "Unregistered %s root bus\n", rootdev->name );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,9 +74,13 @@ static void unregister_rootdev ( struct root_device *rootdev ) {
|
||||||
*/
|
*/
|
||||||
int probe_devices ( void ) {
|
int probe_devices ( void ) {
|
||||||
struct root_device *rootdev;
|
struct root_device *rootdev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
for ( rootdev = root_devices; rootdev < root_devices_end; rootdev++ ) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -92,6 +94,7 @@ void remove_devices ( void ) {
|
||||||
struct root_device *tmp;
|
struct root_device *tmp;
|
||||||
|
|
||||||
list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
|
list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
|
||||||
unregister_rootdev ( rootdev );
|
rootdev_remove ( rootdev );
|
||||||
|
list_del ( &rootdev->dev.siblings );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,23 +165,22 @@ void adjust_pci_device ( struct pci_device *pci ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register PCI device
|
* Probe a PCI device
|
||||||
*
|
*
|
||||||
* @v pci PCI device
|
* @v pci PCI device
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*
|
*
|
||||||
* Searches for a driver for the PCI device. If a driver is found,
|
* 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
|
* its probe() routine is called.
|
||||||
* device hierarchy.
|
|
||||||
*/
|
*/
|
||||||
static int register_pcidev ( struct pci_device *pci ) {
|
static int pci_probe ( struct pci_device *pci ) {
|
||||||
struct pci_driver *driver;
|
struct pci_driver *driver;
|
||||||
struct pci_device_id *id;
|
struct pci_device_id *id;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
DBG ( "Registering PCI device %02x:%02x.%x (%04x:%04x mem %lx "
|
DBG ( "Adding PCI device %02x:%02x.%x (%04x:%04x mem %lx io %lx "
|
||||||
"io %lx irq %d)\n", pci->bus, PCI_SLOT ( pci->devfn ),
|
"irq %d)\n", pci->bus, PCI_SLOT ( pci->devfn ),
|
||||||
PCI_FUNC ( pci->devfn ), pci->vendor, pci->device,
|
PCI_FUNC ( pci->devfn ), pci->vendor, pci->device,
|
||||||
pci->membase, pci->ioaddr, pci->irq );
|
pci->membase, pci->ioaddr, pci->irq );
|
||||||
|
|
||||||
|
@ -198,8 +197,6 @@ static int register_pcidev ( struct pci_device *pci ) {
|
||||||
DBG ( "......probe failed\n" );
|
DBG ( "......probe failed\n" );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
list_add ( &pci->dev.siblings,
|
|
||||||
&pci->dev.parent->children );
|
|
||||||
return 0;
|
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
|
* @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 );
|
pci->driver->remove ( pci );
|
||||||
list_del ( &pci->dev.siblings );
|
DBG ( "Removed PCI device %02x:%02x.%x\n", pci->bus,
|
||||||
DBG ( "Unregistered PCI device %02x:%02x.%x\n", pci->bus,
|
|
||||||
PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ) );
|
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_read_config_byte ( pci, PCI_INTERRUPT_LINE,
|
||||||
&pci->irq );
|
&pci->irq );
|
||||||
pci_read_bases ( pci );
|
pci_read_bases ( pci );
|
||||||
INIT_LIST_HEAD ( &pci->dev.children );
|
|
||||||
|
/* Add to device hierarchy */
|
||||||
pci->dev.parent = &rootdev->dev;
|
pci->dev.parent = &rootdev->dev;
|
||||||
|
list_add ( &pci->dev.siblings, &rootdev->dev.children);
|
||||||
|
INIT_LIST_HEAD ( &pci->dev.children );
|
||||||
|
|
||||||
/* Look for a driver */
|
/* Look for a driver */
|
||||||
if ( register_pcidev ( pci ) == 0 ) {
|
if ( pci_probe ( pci ) == 0 ) {
|
||||||
/* pcidev registered, we can drop our ref */
|
/* pcidev registered, we can drop our ref */
|
||||||
pci = NULL;
|
pci = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* Not registered; re-use struct pci_device */
|
/* 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,
|
list_for_each_entry_safe ( pci, tmp, &rootdev->dev.children,
|
||||||
dev.siblings ) {
|
dev.siblings ) {
|
||||||
unregister_pcidev ( pci );
|
pci_remove ( pci );
|
||||||
|
list_del ( &pci->dev.siblings );
|
||||||
free ( pci );
|
free ( pci );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,7 +324,4 @@ static struct root_driver pci_root_driver = {
|
||||||
struct root_device pci_root_device __root_device = {
|
struct root_device pci_root_device __root_device = {
|
||||||
.name = "PCI",
|
.name = "PCI",
|
||||||
.driver = &pci_root_driver,
|
.driver = &pci_root_driver,
|
||||||
.dev = {
|
|
||||||
.children = LIST_HEAD_INIT ( pci_root_device.dev.children ),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue