aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Shah <rajesh.shah@intel.com>2005-04-28 03:25:45 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-28 00:52:39 -0400
commitc431ada45d65b305a6aab4557067e564b23ce5a5 (patch)
tree3fefb8a354860d9c39781dbbf042c992da5a9cd5
parentefe1ec27837d6639eae82e1f5876910ba6433c3f (diff)
[PATCH] acpi bridge hotadd: ACPI based root bridge hot-add
When you hot-plug a (root) bridge hierarchy, it may have p2p bridges and devices attached to it that have not been configured by firmware. In this case, we need to configure the devices before starting them. This patch separates device start from device scan so that we can introduce the configuration step in the middle. I kept the existing semantics for pci_scan_bus() since there are a huge number of callers to that function. Also, I have no way of testing the changes I made to the parisc files, so this needs review by those folks. Sorry for the massive cross-post, this touches files in many different places. Signed-off-by: Rajesh Shah <rajesh.shah@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/i386/pci/common.c2
-rw-r--r--arch/i386/pci/legacy.c2
-rw-r--r--arch/i386/pci/numa.c2
-rw-r--r--arch/ia64/pci/pci.c2
-rw-r--r--drivers/acpi/pci_bind.c16
-rw-r--r--drivers/acpi/pci_root.c24
-rw-r--r--drivers/parisc/dino.c1
-rw-r--r--drivers/parisc/lba_pci.c2
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--include/linux/pci.h8
10 files changed, 53 insertions, 8 deletions
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 2a2e79fbfef8..87325263cd4f 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -134,7 +134,7 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
134 134
135 printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); 135 printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
136 136
137 return pci_scan_bus(busnum, &pci_root_ops, NULL); 137 return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, NULL);
138} 138}
139 139
140extern u8 pci_cache_line_size; 140extern u8 pci_cache_line_size;
diff --git a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c
index 1492e3753869..149a9588c256 100644
--- a/arch/i386/pci/legacy.c
+++ b/arch/i386/pci/legacy.c
@@ -45,6 +45,8 @@ static int __init pci_legacy_init(void)
45 45
46 printk("PCI: Probing PCI hardware\n"); 46 printk("PCI: Probing PCI hardware\n");
47 pci_root_bus = pcibios_scan_root(0); 47 pci_root_bus = pcibios_scan_root(0);
48 if (pci_root_bus)
49 pci_bus_add_devices(pci_root_bus);
48 50
49 pcibios_fixup_peer_bridges(); 51 pcibios_fixup_peer_bridges();
50 52
diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
index 9e3695461899..adbe17a38f6f 100644
--- a/arch/i386/pci/numa.c
+++ b/arch/i386/pci/numa.c
@@ -115,6 +115,8 @@ static int __init pci_numa_init(void)
115 return 0; 115 return 0;
116 116
117 pci_root_bus = pcibios_scan_root(0); 117 pci_root_bus = pcibios_scan_root(0);
118 if (pci_root_bus)
119 pci_bus_add_devices(pci_root_bus);
118 if (num_online_nodes() > 1) 120 if (num_online_nodes() > 1)
119 for_each_online_node(quad) { 121 for_each_online_node(quad) {
120 if (quad == 0) 122 if (quad == 0)
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index e3fc4edea113..c0661d3382e4 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -312,7 +312,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
312 acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, 312 acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
313 &info); 313 &info);
314 314
315 pbus = pci_scan_bus(bus, &pci_root_ops, controller); 315 pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller);
316 if (pbus) 316 if (pbus)
317 pcibios_setup_root_windows(pbus, controller); 317 pcibios_setup_root_windows(pbus, controller);
318 318
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 5d19b39e9e2b..7753df1f9fb8 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -129,6 +129,8 @@ acpi_pci_bind (
129 char *pathname = NULL; 129 char *pathname = NULL;
130 struct acpi_buffer buffer = {0, NULL}; 130 struct acpi_buffer buffer = {0, NULL};
131 acpi_handle handle = NULL; 131 acpi_handle handle = NULL;
132 struct pci_dev *dev;
133 struct pci_bus *bus;
132 134
133 ACPI_FUNCTION_TRACE("acpi_pci_bind"); 135 ACPI_FUNCTION_TRACE("acpi_pci_bind");
134 136
@@ -193,8 +195,20 @@ acpi_pci_bind (
193 * Locate matching device in PCI namespace. If it doesn't exist 195 * Locate matching device in PCI namespace. If it doesn't exist
194 * this typically means that the device isn't currently inserted 196 * this typically means that the device isn't currently inserted
195 * (e.g. docking station, port replicator, etc.). 197 * (e.g. docking station, port replicator, etc.).
198 * We cannot simply search the global pci device list, since
199 * PCI devices are added to the global pci list when the root
200 * bridge start ops are run, which may not have happened yet.
196 */ 201 */
197 data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function)); 202 bus = pci_find_bus(data->id.segment, data->id.bus);
203 if (bus) {
204 list_for_each_entry(dev, &bus->devices, bus_list) {
205 if (dev->devfn == PCI_DEVFN(data->id.device,
206 data->id.function)) {
207 data->dev = dev;
208 break;
209 }
210 }
211 }
198 if (!data->dev) { 212 if (!data->dev) {
199 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 213 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
200 "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", 214 "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 7e6b8e3b2ed4..5d2f77fcd50c 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -46,6 +46,7 @@ ACPI_MODULE_NAME ("pci_root")
46 46
47static int acpi_pci_root_add (struct acpi_device *device); 47static int acpi_pci_root_add (struct acpi_device *device);
48static int acpi_pci_root_remove (struct acpi_device *device, int type); 48static int acpi_pci_root_remove (struct acpi_device *device, int type);
49static int acpi_pci_root_start (struct acpi_device *device);
49 50
50static struct acpi_driver acpi_pci_root_driver = { 51static struct acpi_driver acpi_pci_root_driver = {
51 .name = ACPI_PCI_ROOT_DRIVER_NAME, 52 .name = ACPI_PCI_ROOT_DRIVER_NAME,
@@ -54,6 +55,7 @@ static struct acpi_driver acpi_pci_root_driver = {
54 .ops = { 55 .ops = {
55 .add = acpi_pci_root_add, 56 .add = acpi_pci_root_add,
56 .remove = acpi_pci_root_remove, 57 .remove = acpi_pci_root_remove,
58 .start = acpi_pci_root_start,
57 }, 59 },
58}; 60};
59 61
@@ -169,6 +171,7 @@ acpi_pci_root_add (
169 if (!root) 171 if (!root)
170 return_VALUE(-ENOMEM); 172 return_VALUE(-ENOMEM);
171 memset(root, 0, sizeof(struct acpi_pci_root)); 173 memset(root, 0, sizeof(struct acpi_pci_root));
174 INIT_LIST_HEAD(&root->node);
172 175
173 root->handle = device->handle; 176 root->handle = device->handle;
174 strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); 177 strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
@@ -298,12 +301,31 @@ acpi_pci_root_add (
298 root->id.bus); 301 root->id.bus);
299 302
300end: 303end:
301 if (result) 304 if (result) {
305 if (!list_empty(&root->node))
306 list_del(&root->node);
302 kfree(root); 307 kfree(root);
308 }
303 309
304 return_VALUE(result); 310 return_VALUE(result);
305} 311}
306 312
313static int
314acpi_pci_root_start (
315 struct acpi_device *device)
316{
317 struct acpi_pci_root *root;
318
319 ACPI_FUNCTION_TRACE("acpi_pci_root_start");
320
321 list_for_each_entry(root, &acpi_pci_roots, node) {
322 if (root->handle == device->handle) {
323 pci_bus_add_devices(root->bus);
324 return_VALUE(0);
325 }
326 }
327 return_VALUE(-ENODEV);
328}
307 329
308static int 330static int
309acpi_pci_root_remove ( 331acpi_pci_root_remove (
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index b0d2a73d1d47..2f2dbef2c3b7 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -993,6 +993,7 @@ dino_driver_callback(struct parisc_device *dev)
993 bus = pci_scan_bus_parented(&dev->dev, dino_current_bus, 993 bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,
994 &dino_cfg_ops, NULL); 994 &dino_cfg_ops, NULL);
995 if(bus) { 995 if(bus) {
996 pci_bus_add_devices(bus);
996 /* This code *depends* on scanning being single threaded 997 /* This code *depends* on scanning being single threaded
997 * if it isn't, this global bus number count will fail 998 * if it isn't, this global bus number count will fail
998 */ 999 */
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index dc838804c0dd..7fdd80b7eb47 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1570,6 +1570,8 @@ lba_driver_probe(struct parisc_device *dev)
1570 lba_bus = lba_dev->hba.hba_bus = 1570 lba_bus = lba_dev->hba.hba_bus =
1571 pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, 1571 pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
1572 cfg_ops, NULL); 1572 cfg_ops, NULL);
1573 if (lba_bus)
1574 pci_bus_add_devices(lba_bus);
1573 1575
1574 /* This is in lieu of calling pci_assign_unassigned_resources() */ 1576 /* This is in lieu of calling pci_assign_unassigned_resources() */
1575 if (is_pdc_pat()) { 1577 if (is_pdc_pat()) {
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index fd48b201eb53..3dc00f0ca8a0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -911,8 +911,6 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
911 911
912 b->subordinate = pci_scan_child_bus(b); 912 b->subordinate = pci_scan_child_bus(b);
913 913
914 pci_bus_add_devices(b);
915
916 return b; 914 return b;
917 915
918sys_create_link_err: 916sys_create_link_err:
diff --git a/include/linux/pci.h b/include/linux/pci.h
index b5238bd18830..0e9844929fe3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -734,16 +734,20 @@ void pcibios_update_irq(struct pci_dev *, int irq);
734/* Generic PCI functions used internally */ 734/* Generic PCI functions used internally */
735 735
736extern struct pci_bus *pci_find_bus(int domain, int busnr); 736extern struct pci_bus *pci_find_bus(int domain, int busnr);
737void pci_bus_add_devices(struct pci_bus *bus);
737struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata); 738struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
738static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata) 739static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
739{ 740{
740 return pci_scan_bus_parented(NULL, bus, ops, sysdata); 741 struct pci_bus *root_bus;
742 root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
743 if (root_bus)
744 pci_bus_add_devices(root_bus);
745 return root_bus;
741} 746}
742int pci_scan_slot(struct pci_bus *bus, int devfn); 747int pci_scan_slot(struct pci_bus *bus, int devfn);
743struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn); 748struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
744unsigned int pci_scan_child_bus(struct pci_bus *bus); 749unsigned int pci_scan_child_bus(struct pci_bus *bus);
745void pci_bus_add_device(struct pci_dev *dev); 750void pci_bus_add_device(struct pci_dev *dev);
746void pci_bus_add_devices(struct pci_bus *bus);
747void pci_name_device(struct pci_dev *dev); 751void pci_name_device(struct pci_dev *dev);
748char *pci_class_name(u32 class); 752char *pci_class_name(u32 class);
749void pci_read_bridge_bases(struct pci_bus *child); 753void pci_read_bridge_bases(struct pci_bus *child);