Make pci_stop_dev actually detach driver only, and pci_remove_dev device will do device_del instead. Then also could make hostbridge to use device_unregister to be pair with device_register before. Add is_removed to record if device_del is called already. So mutliple calling will not cause false removing, only right put_device will get device removed at last. Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> --- drivers/pci/remove.c | 12 ++++++++---- include/linux/pci.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) Index: linux-2.6/drivers/pci/remove.c =================================================================== --- linux-2.6.orig/drivers/pci/remove.c +++ linux-2.6/drivers/pci/remove.c @@ -10,7 +10,7 @@ static void pci_stop_dev(struct pci_dev if (dev->is_added) { pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); - device_del(&dev->dev); + device_release_driver(&dev->dev); dev->is_added = 0; } @@ -20,7 +20,11 @@ static void pci_stop_dev(struct pci_dev static void pci_destroy_dev(struct pci_dev *dev) { - put_device(&dev->dev); + if (!dev->is_removed) { + device_del(&dev->dev); + dev->is_removed = 1; + put_device(&dev->dev); + } } void pci_remove_bus(struct pci_bus *bus) @@ -107,7 +111,7 @@ void pci_stop_root_bus(struct pci_bus *b pci_stop_bus_device(child); /* stop the host bridge */ - device_del(&host_bridge->dev); + device_release_driver(&host_bridge->dev); } void pci_remove_root_bus(struct pci_bus *bus) @@ -126,5 +130,5 @@ void pci_remove_root_bus(struct pci_bus host_bridge->bus = NULL; /* remove the host bridge */ - put_device(&host_bridge->dev); + device_unregister(&host_bridge->dev); } Index: linux-2.6/include/linux/pci.h =================================================================== --- linux-2.6.orig/include/linux/pci.h +++ linux-2.6/include/linux/pci.h @@ -307,7 +307,8 @@ struct pci_dev { unsigned int transparent:1; /* Transparent PCI bridge */ unsigned int multifunction:1;/* Part of multi-function device */ /* keep track of device state */ - unsigned int is_added:1; + unsigned int is_added:1; /* driver is attached */ + unsigned int is_removed:1; /* device_del is called */ unsigned int is_busmaster:1; /* device is busmaster */ unsigned int no_msi:1; /* device may not use msi */ unsigned int block_cfg_access:1; /* config space access is blocked */ -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html