]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.arch/ppc-powerpc-debug-pci-hotplug.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / ppc-powerpc-debug-pci-hotplug.patch
CommitLineData
2cb7cef9
BS
1Subject: Fix DLPAR
2From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
3References: 439491
4
5Signed-off-by: Olaf Hering <olh@suse.de>
6---
7 arch/powerpc/include/asm/pci-bridge.h | 4
8 arch/powerpc/include/asm/pci.h | 10 +
9 arch/powerpc/kernel/pci-common.c | 124 ++++++++++++----------
10 arch/powerpc/kernel/pci_32.c | 6 -
11 arch/powerpc/kernel/pci_64.c | 27 +++-
12 arch/powerpc/kernel/rtas_pci.c | 48 --------
13 arch/powerpc/platforms/pseries/eeh.c | 44 ++++---
14 arch/powerpc/platforms/pseries/pci_dlpar.c | 163 +++++++++++++++--------------
15 drivers/pci/hotplug/rpadlpar_core.c | 49 +++++---
16 drivers/pci/hotplug/rpaphp_slot.c | 4
17 10 files changed, 245 insertions(+), 234 deletions(-)
18
19--- a/arch/powerpc/include/asm/pci-bridge.h
20+++ b/arch/powerpc/include/asm/pci-bridge.h
21@@ -234,9 +234,7 @@ extern void pcibios_remove_pci_devices(s
22
23 /** Discover new pci devices under this bus, and add them */
24 extern void pcibios_add_pci_devices(struct pci_bus *bus);
25-extern void pcibios_fixup_new_pci_devices(struct pci_bus *bus);
26-
27-extern int pcibios_remove_root_bus(struct pci_controller *phb);
28+extern void pcibios_finish_adding_new_bus(struct pci_bus *bus);
29
30 static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
31 {
32--- a/arch/powerpc/include/asm/pci.h
33+++ b/arch/powerpc/include/asm/pci.h
34@@ -201,6 +201,7 @@ extern void pcibios_allocate_bus_resourc
35 extern void pcibios_resource_survey(void);
36
37 extern struct pci_controller *init_phb_dynamic(struct device_node *dn);
38+extern int remove_phb_dynamic(struct pci_controller *phb);
39
40 extern struct pci_dev *of_create_pci_dev(struct device_node *node,
41 struct pci_bus *bus, int devfn);
42@@ -208,7 +209,8 @@ extern struct pci_dev *of_create_pci_dev
43 extern void of_scan_pci_bridge(struct device_node *node,
44 struct pci_dev *dev);
45
46-extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
47+extern void of_scan_bus(struct device_node *node, struct pci_bus *bus,
48+ int rescan_existing);
49
50 extern int pci_read_irq_line(struct pci_dev *dev);
51
52@@ -223,8 +225,10 @@ extern void pci_resource_to_user(const s
53 const struct resource *rsrc,
54 resource_size_t *start, resource_size_t *end);
55
56-extern void pcibios_do_bus_setup(struct pci_bus *bus);
57-extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
58+extern void pcibios_do_bus_setup_self(struct pci_bus *bus);
59+extern void pcibios_do_bus_setup_devices(struct pci_bus *bus);
60+extern void pcibios_fixup_bus_self(struct pci_bus *bus);
61+extern void pcibios_fixup_bus_devices(struct pci_bus *bus);
62
63 #endif /* __KERNEL__ */
64 #endif /* __ASM_POWERPC_PCI_H */
65--- a/arch/powerpc/kernel/pci_32.c
66+++ b/arch/powerpc/kernel/pci_32.c
67@@ -418,7 +418,7 @@ static int __init pcibios_init(void)
68
69 subsys_initcall(pcibios_init);
70
71-void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
72+void __devinit pcibios_do_bus_setup_self(struct pci_bus *bus)
73 {
74 struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
75 unsigned long io_offset;
76@@ -459,6 +459,10 @@ void __devinit pcibios_do_bus_setup(stru
77 }
78 }
79
80+void __devinit pcibios_do_bus_setup_devices(struct pci_bus *bus)
81+{
82+}
83+
84 /* the next one is stolen from the alpha port... */
85 void __init
86 pcibios_update_irq(struct pci_dev *dev, int irq)
87--- a/arch/powerpc/kernel/pci_64.c
88+++ b/arch/powerpc/kernel/pci_64.c
89@@ -225,14 +225,16 @@ struct pci_dev *of_create_pci_dev(struct
90 EXPORT_SYMBOL(of_create_pci_dev);
91
92 void __devinit of_scan_bus(struct device_node *node,
93- struct pci_bus *bus)
94+ struct pci_bus *bus,
95+ int rescan_existing)
96 {
97 struct device_node *child;
98 const u32 *reg;
99 int reglen, devfn;
100 struct pci_dev *dev;
101
102- DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
103+ DBG("of_scan_bus(%s) %s bus no %d... \n", node->full_name,
104+ rescan_existing ? "existing" : "new", bus->number);
105
106 /* Scan direct children */
107 for_each_child_of_node(node, child) {
108@@ -249,8 +251,12 @@ void __devinit of_scan_bus(struct device
109 DBG(" dev header type: %x\n", dev->hdr_type);
110 }
111
112- /* Ally all fixups */
113- pcibios_fixup_of_probed_bus(bus);
114+ /* Apply all fixups necessary. We don't fixup the bus "self"
115+ * for an existing bridge that is being rescanned
116+ */
117+ if (!rescan_existing)
118+ pcibios_fixup_bus_self(bus);
119+ pcibios_fixup_bus_devices(bus);
120
121 /* Now scan child busses */
122 list_for_each_entry(dev, &bus->devices, bus_list) {
123@@ -346,7 +352,7 @@ void __devinit of_scan_pci_bridge(struct
124 DBG(" probe mode: %d\n", mode);
125
126 if (mode == PCI_PROBE_DEVTREE)
127- of_scan_bus(node, bus);
128+ of_scan_bus(node, bus, 0);
129 else if (mode == PCI_PROBE_NORMAL)
130 pci_scan_child_bus(bus);
131 }
132@@ -396,7 +402,7 @@ void __devinit scan_phb(struct pci_contr
133 DBG(" probe mode: %d\n", mode);
134 if (mode == PCI_PROBE_DEVTREE) {
135 bus->subordinate = hose->last_busno;
136- of_scan_bus(node, bus);
137+ of_scan_bus(node, bus, 0);
138 }
139
140 if (mode == PCI_PROBE_NORMAL)
141@@ -568,12 +574,15 @@ void __devinit pcibios_setup_new_device(
142 }
143 EXPORT_SYMBOL(pcibios_setup_new_device);
144
145-void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
146+void __devinit pcibios_do_bus_setup_self(struct pci_bus *bus)
147 {
148- struct pci_dev *dev;
149-
150 if (ppc_md.pci_dma_bus_setup)
151 ppc_md.pci_dma_bus_setup(bus);
152+}
153+
154+void __devinit pcibios_do_bus_setup_devices(struct pci_bus *bus)
155+{
156+ struct pci_dev *dev;
157
158 list_for_each_entry(dev, &bus->devices, bus_list)
159 pcibios_setup_new_device(dev);
160--- a/arch/powerpc/kernel/pci-common.c
161+++ b/arch/powerpc/kernel/pci-common.c
162@@ -789,63 +789,78 @@ static void __devinit pcibios_fixup_reso
163 }
164 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
165
166-static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
167+void __devinit pcibios_fixup_bus_self(struct pci_bus *bus)
168 {
169 struct pci_controller *hose = pci_bus_to_host(bus);
170 struct pci_dev *dev = bus->self;
171+ struct resource *res;
172+ int i;
173
174- pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
175+ pr_debug("PCI: Fixup bus resources %d (%s)\n",
176+ bus->number, dev ? pci_name(dev) : "PHB");
177
178 /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
179 * now differently between 32 and 64 bits.
180 */
181- if (dev != NULL) {
182- struct resource *res;
183- int i;
184-
185- for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
186- if ((res = bus->resource[i]) == NULL)
187- continue;
188- if (!res->flags)
189- continue;
190- if (i >= 3 && bus->self->transparent)
191- continue;
192- /* On PowerMac, Apple leaves bridge windows open over
193- * an inaccessible region of memory space (0...fffff)
194- * which is somewhat bogus, but that's what they think
195- * means disabled...
196- *
197- * We clear those to force them to be reallocated later
198- *
199- * We detect such regions by the fact that the base is
200- * equal to the pci_mem_offset of the host bridge and
201- * their size is smaller than 1M.
202- */
203- if (res->flags & IORESOURCE_MEM &&
204- res->start == hose->pci_mem_offset &&
205- res->end < 0x100000) {
206- printk(KERN_INFO
207- "PCI: Closing bogus Apple Firmware"
208- " region %d on bus 0x%02x\n",
209- i, bus->number);
210- res->flags = 0;
211- continue;
212- }
213+ if (dev == NULL)
214+ goto host_bridge;
215
216- pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
217- pci_name(dev), i,
218- (unsigned long long)res->start,\
219- (unsigned long long)res->end,
220- (unsigned int)res->flags);
221+ for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
222+ if ((res = bus->resource[i]) == NULL)
223+ continue;
224+ if (!res->flags)
225+ continue;
226+ if (i >= 3 && bus->self->transparent)
227+ continue;
228
229- fixup_resource(res, dev);
230+ /* On PowerMac, Apple leaves bridge windows open over
231+ * an inaccessible region of memory space (0...fffff)
232+ * which is somewhat bogus, but that's what they think
233+ * means disabled...
234+ *
235+ * We clear those to force them to be reallocated later
236+ *
237+ * We detect such regions by the fact that the base is
238+ * equal to the pci_mem_offset of the host bridge and
239+ * their size is smaller than 1M.
240+ */
241+ if (res->flags & IORESOURCE_MEM &&
242+ res->start == hose->pci_mem_offset &&
243+ res->end < 0x100000) {
244+ printk(KERN_INFO
245+ "PCI: Closing bogus Apple Firmware"
246+ " region %d on bus 0x%02x\n",
247+ i, bus->number);
248+ res->flags = 0;
249+ continue;
250 }
251+
252+ pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
253+ pci_name(dev), i,
254+ (unsigned long long)res->start,\
255+ (unsigned long long)res->end,
256+ (unsigned int)res->flags);
257+
258+ fixup_resource(res, dev);
259 }
260
261+host_bridge:
262+
263+ /* Additional setup that is different between 32 and 64 bits for now */
264+ pcibios_do_bus_setup_self(bus);
265+}
266+
267+void __devinit pcibios_fixup_bus_devices(struct pci_bus *bus)
268+{
269+ struct pci_dev *dev = bus->self;
270+
271+ pr_debug("PCI: Fixup bus devices %d (%s)\n",
272+ bus->number, dev ? pci_name(dev) : "PHB");
273+
274 /* Additional setup that is different between 32 and 64 bits for now */
275- pcibios_do_bus_setup(bus);
276+ pcibios_do_bus_setup_devices(bus);
277
278- /* Platform specific bus fixups */
279+ /* Platform specific bus fixups (XXX Get rid of these !) */
280 if (ppc_md.pcibios_fixup_bus)
281 ppc_md.pcibios_fixup_bus(bus);
282
283@@ -864,19 +879,11 @@ void __devinit pcibios_fixup_bus(struct
284 */
285 if (bus->self != NULL)
286 pci_read_bridge_bases(bus);
287- __pcibios_fixup_bus(bus);
288+ pcibios_fixup_bus_self(bus);
289+ pcibios_fixup_bus_devices(bus);
290 }
291 EXPORT_SYMBOL(pcibios_fixup_bus);
292
293-/* When building a bus from the OF tree rather than probing, we need a
294- * slightly different version of the fixup which doesn't read the
295- * bridge bases using config space accesses
296- */
297-void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
298-{
299- __pcibios_fixup_bus(bus);
300-}
301-
302 static int skip_isa_ioresource_align(struct pci_dev *dev)
303 {
304 if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
305@@ -992,9 +999,12 @@ void pcibios_allocate_bus_resources(stru
306 int i;
307 struct resource *res, *pr;
308
309+ DBG("PCI: Allocating bus resources for %04x:%02x...\n",
310+ pci_domain_nr(bus), bus->number);
311+
312 for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
313 if ((res = bus->resource[i]) == NULL || !res->flags
314- || res->start > res->end)
315+ || res->start > res->end || res->parent)
316 continue;
317 if (bus->parent == NULL)
318 pr = (res->flags & IORESOURCE_IO) ?
319@@ -1047,6 +1057,7 @@ clear_resource:
320 list_for_each_entry(b, &bus->children, node)
321 pcibios_allocate_bus_resources(b);
322 }
323+EXPORT_SYMBOL_GPL(pcibios_allocate_bus_resources);
324
325 static inline void __devinit alloc_resource(struct pci_dev *dev, int idx)
326 {
327@@ -1157,6 +1168,13 @@ void __devinit pcibios_claim_one_bus(str
328
329 if (r->parent || !r->start || !r->flags)
330 continue;
331+
332+ DBG("PCI: Claiming %s: Resource %d: %016llx..%016llx [%x]\n",
333+ pci_name(dev), i,
334+ (unsigned long long)r->start,
335+ (unsigned long long)r->end,
336+ (unsigned int)r->flags);
337+
338 pci_claim_resource(dev, i);
339 }
340 }
341--- a/arch/powerpc/kernel/rtas_pci.c
342+++ b/arch/powerpc/kernel/rtas_pci.c
343@@ -301,51 +301,3 @@ void __init find_and_init_phbs(void)
344 #endif /* CONFIG_PPC32 */
345 }
346 }
347-
348-/* RPA-specific bits for removing PHBs */
349-int pcibios_remove_root_bus(struct pci_controller *phb)
350-{
351- struct pci_bus *b = phb->bus;
352- struct resource *res;
353- int rc, i;
354-
355- res = b->resource[0];
356- if (!res->flags) {
357- printk(KERN_ERR "%s: no IO resource for PHB %s\n", __func__,
358- b->name);
359- return 1;
360- }
361-
362- rc = pcibios_unmap_io_space(b);
363- if (rc) {
364- printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
365- __func__, b->name);
366- return 1;
367- }
368-
369- if (release_resource(res)) {
370- printk(KERN_ERR "%s: failed to release IO on bus %s\n",
371- __func__, b->name);
372- return 1;
373- }
374-
375- for (i = 1; i < 3; ++i) {
376- res = b->resource[i];
377- if (!res->flags && i == 0) {
378- printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
379- __func__, b->name);
380- return 1;
381- }
382- if (res->flags && release_resource(res)) {
383- printk(KERN_ERR
384- "%s: failed to release IO %d on bus %s\n",
385- __func__, i, b->name);
386- return 1;
387- }
388- }
389-
390- pcibios_free_controller(phb);
391-
392- return 0;
393-}
394-EXPORT_SYMBOL(pcibios_remove_root_bus);
395--- a/arch/powerpc/platforms/pseries/eeh.c
396+++ b/arch/powerpc/platforms/pseries/eeh.c
397@@ -21,6 +21,8 @@
398 * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
399 */
400
401+#undef DEBUG
402+
403 #include <linux/delay.h>
404 #include <linux/init.h>
405 #include <linux/list.h>
406@@ -488,10 +490,8 @@ int eeh_dn_check_failure(struct device_n
407 if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
408 pdn->eeh_mode & EEH_MODE_NOCHECK) {
409 ignored_check++;
410-#ifdef DEBUG
411- printk ("EEH:ignored check (%x) for %s %s\n",
412- pdn->eeh_mode, pci_name (dev), dn->full_name);
413-#endif
414+ pr_debug("EEH: Ignored check (%x) for %s %s\n",
415+ pdn->eeh_mode, pci_name (dev), dn->full_name);
416 return 0;
417 }
418
419@@ -1014,10 +1014,9 @@ static void *early_enable_eeh(struct dev
420 eeh_subsystem_enabled = 1;
421 pdn->eeh_mode |= EEH_MODE_SUPPORTED;
422
423-#ifdef DEBUG
424- printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n",
425- dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr);
426-#endif
427+ pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
428+ dn->full_name, pdn->eeh_config_addr,
429+ pdn->eeh_pe_config_addr);
430 } else {
431
432 /* This device doesn't support EEH, but it may have an
433@@ -1161,13 +1160,17 @@ static void eeh_add_device_late(struct p
434 if (!dev || !eeh_subsystem_enabled)
435 return;
436
437-#ifdef DEBUG
438- printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev));
439-#endif
440+ pr_debug("EEH: Adding device %s\n", pci_name(dev));
441
442- pci_dev_get (dev);
443 dn = pci_device_to_OF_node(dev);
444 pdn = PCI_DN(dn);
445+ if (pdn->pcidev == dev) {
446+ pr_debug("EEH: Already referenced !\n");
447+ return;
448+ }
449+ WARN_ON(pdn->pcidev);
450+
451+ pci_dev_get (dev);
452 pdn->pcidev = dev;
453
454 pci_addr_cache_insert_device(dev);
455@@ -1206,17 +1209,18 @@ static void eeh_remove_device(struct pci
456 return;
457
458 /* Unregister the device with the EEH/PCI address search system */
459-#ifdef DEBUG
460- printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
461-#endif
462- pci_addr_cache_remove_device(dev);
463- eeh_sysfs_remove_device(dev);
464+ pr_debug("EEH: Removing device %s\n", pci_name(dev));
465
466 dn = pci_device_to_OF_node(dev);
467- if (PCI_DN(dn)->pcidev) {
468- PCI_DN(dn)->pcidev = NULL;
469- pci_dev_put (dev);
470+ if (PCI_DN(dn)->pcidev == NULL) {
471+ pr_debug("EEH: Not referenced !\n");
472+ return;
473 }
474+ PCI_DN(dn)->pcidev = NULL;
475+ pci_dev_put (dev);
476+
477+ pci_addr_cache_remove_device(dev);
478+ eeh_sysfs_remove_device(dev);
479 }
480
481 void eeh_remove_bus_device(struct pci_dev *dev)
482--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
483+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
484@@ -25,6 +25,8 @@
485 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
486 */
487
488+#undef DEBUG
489+
490 #include <linux/pci.h>
491 #include <asm/pci-bridge.h>
492 #include <asm/ppc-pci.h>
493@@ -69,73 +71,41 @@ EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
494 * Remove all of the PCI devices under this bus both from the
495 * linux pci device tree, and from the powerpc EEH address cache.
496 */
497-void
498-pcibios_remove_pci_devices(struct pci_bus *bus)
499+void pcibios_remove_pci_devices(struct pci_bus *bus)
500 {
501 struct pci_dev *dev, *tmp;
502+ struct pci_bus *child_bus;
503
504+ /* First go down child busses */
505+ list_for_each_entry(child_bus, &bus->children, node)
506+ pcibios_remove_pci_devices(child_bus);
507+
508+ pr_debug("PCI: Removing devices on bus %04x:%02x\n",
509+ pci_domain_nr(bus), bus->number);
510 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
511+ pr_debug(" * Removing %s...\n", pci_name(dev));
512 eeh_remove_bus_device(dev);
513 pci_remove_bus_device(dev);
514 }
515 }
516 EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
517
518-/* Must be called before pci_bus_add_devices */
519-void
520-pcibios_fixup_new_pci_devices(struct pci_bus *bus)
521-{
522- struct pci_dev *dev;
523-
524- list_for_each_entry(dev, &bus->devices, bus_list) {
525- /* Skip already-added devices */
526- if (!dev->is_added) {
527- int i;
528-
529- /* Fill device archdata and setup iommu table */
530- pcibios_setup_new_device(dev);
531-
532- pci_read_irq_line(dev);
533- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
534- struct resource *r = &dev->resource[i];
535-
536- if (r->parent || !r->start || !r->flags)
537- continue;
538- pci_claim_resource(dev, i);
539- }
540- }
541- }
542-}
543-EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
544-
545-static int
546-pcibios_pci_config_bridge(struct pci_dev *dev)
547+void pcibios_finish_adding_new_bus(struct pci_bus *bus)
548 {
549- u8 sec_busno;
550- struct pci_bus *child_bus;
551-
552- /* Get busno of downstream bus */
553- pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
554+ pr_debug("PCI: Finishing adding hotplug bus %04x:%02x\n",
555+ pci_domain_nr(bus), bus->number);
556
557- /* Add to children of PCI bridge dev->bus */
558- child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
559- if (!child_bus) {
560- printk (KERN_ERR "%s: could not add second bus\n", __func__);
561- return -EIO;
562- }
563- sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
564-
565- pci_scan_child_bus(child_bus);
566+ /* Allocate bus and devices resources */
567+ pcibios_allocate_bus_resources(bus);
568+ pcibios_claim_one_bus(bus);
569
570- /* Fixup new pci devices */
571- pcibios_fixup_new_pci_devices(child_bus);
572+ /* Add new devices to global lists. Register in proc, sysfs. */
573+ pci_bus_add_devices(bus);
574
575- /* Make the discovered devices available */
576- pci_bus_add_devices(child_bus);
577-
578- eeh_add_device_tree_late(child_bus);
579- return 0;
580+ /* Fixup EEH */
581+ eeh_add_device_tree_late(bus);
582 }
583+EXPORT_SYMBOL_GPL(pcibios_finish_adding_new_bus);
584
585 /**
586 * pcibios_add_pci_devices - adds new pci devices to bus
587@@ -147,10 +117,9 @@ pcibios_pci_config_bridge(struct pci_dev
588 * is how this routine differs from other, similar pcibios
589 * routines.)
590 */
591-void
592-pcibios_add_pci_devices(struct pci_bus * bus)
593+void pcibios_add_pci_devices(struct pci_bus * bus)
594 {
595- int slotno, num, mode;
596+ int slotno, num, mode, pass, max;
597 struct pci_dev *dev;
598 struct device_node *dn = pci_bus_to_OF_node(bus);
599
600@@ -162,25 +131,24 @@ pcibios_add_pci_devices(struct pci_bus *
601
602 if (mode == PCI_PROBE_DEVTREE) {
603 /* use ofdt-based probe */
604- of_scan_bus(dn, bus);
605- if (!list_empty(&bus->devices)) {
606- pcibios_fixup_new_pci_devices(bus);
607- pci_bus_add_devices(bus);
608- eeh_add_device_tree_late(bus);
609- }
610+ of_scan_bus(dn, bus, 1);
611+ if (!list_empty(&bus->devices))
612+ pcibios_finish_adding_new_bus(bus);
613 } else if (mode == PCI_PROBE_NORMAL) {
614 /* use legacy probe */
615 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
616 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
617- if (num) {
618- pcibios_fixup_new_pci_devices(bus);
619- pci_bus_add_devices(bus);
620- eeh_add_device_tree_late(bus);
621+ if (!num)
622+ return;
623+ pcibios_fixup_bus_devices(bus);
624+ max = bus->secondary;
625+ for (pass=0; pass < 2; pass++)
626+ list_for_each_entry(dev, &bus->devices, bus_list) {
627+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
628+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
629+ max = pci_scan_bridge(bus, dev, max, pass);
630 }
631-
632- list_for_each_entry(dev, &bus->devices, bus_list)
633- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
634- pcibios_pci_config_bridge(dev);
635+ pcibios_finish_adding_new_bus(bus);
636 }
637 }
638 EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
639@@ -189,7 +157,8 @@ struct pci_controller * __devinit init_p
640 {
641 struct pci_controller *phb;
642 int primary;
643- struct pci_bus *b;
644+
645+ pr_debug("PCI: Initializing new hotplug PHB %s\n", dn->full_name);
646
647 primary = list_empty(&hose_list);
648 phb = pcibios_alloc_controller(dn);
649@@ -204,11 +173,57 @@ struct pci_controller * __devinit init_p
650 eeh_add_device_tree_early(dn);
651
652 scan_phb(phb);
653- pcibios_allocate_bus_resources(phb->bus);
654- pcibios_fixup_new_pci_devices(phb->bus);
655- pci_bus_add_devices(phb->bus);
656- eeh_add_device_tree_late(phb->bus);
657+ pcibios_finish_adding_new_bus(phb->bus);
658
659 return phb;
660 }
661 EXPORT_SYMBOL_GPL(init_phb_dynamic);
662+
663+
664+
665+
666+/* RPA-specific bits for removing PHBs */
667+int remove_phb_dynamic(struct pci_controller *phb)
668+{
669+ struct pci_bus *b = phb->bus;
670+ struct resource *res;
671+ int rc, i;
672+
673+ pr_debug("PCI: Removing PHB %04x:%02x... \n", pci_domain_nr(b), b->number);
674+
675+ /* We -know- there aren't any child devices anymore at this stage
676+ * and thus, we can safely unmap the IO space as it's not in use
677+ */
678+ res = &phb->io_resource;
679+ if (res->flags & IORESOURCE_IO) {
680+ rc = pcibios_unmap_io_space(b);
681+ if (rc) {
682+ printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
683+ __func__, b->name);
684+ return 1;
685+ }
686+ }
687+
688+ /* Unregister the bridge device from sysfs and remove the PCI bus */
689+ device_unregister(b->bridge);
690+ phb->bus = NULL;
691+ pci_remove_bus(b);
692+
693+ /* Now release the IO resource */
694+ if (res->flags & IORESOURCE_IO)
695+ release_resource(res);
696+
697+ /* Release memory resources */
698+ for (i = 0; i < 3; ++i) {
699+ res = &phb->mem_resources[i];
700+ if (!(res->flags & IORESOURCE_MEM))
701+ continue;
702+ release_resource(res);
703+ }
704+
705+ /* Free pci_controller data structure */
706+ pcibios_free_controller(phb);
707+
708+ return 0;
709+}
710+EXPORT_SYMBOL_GPL(remove_phb_dynamic);
711--- a/drivers/pci/hotplug/rpadlpar_core.c
712+++ b/drivers/pci/hotplug/rpadlpar_core.c
713@@ -14,6 +14,8 @@
714 * as published by the Free Software Foundation; either version
715 * 2 of the License, or (at your option) any later version.
716 */
717+#undef DEBUG
718+
719 #include <linux/init.h>
720 #include <linux/pci.h>
721 #include <linux/string.h>
722@@ -155,16 +157,15 @@ static void dlpar_pci_add_bus(struct dev
723 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
724 of_scan_pci_bridge(dn, dev);
725
726- pcibios_fixup_new_pci_devices(dev->subordinate);
727-
728- /* Claim new bus resources */
729- pcibios_claim_one_bus(dev->bus);
730-
731 /* Map IO space for child bus, which may or may not succeed */
732 pcibios_map_io_space(dev->subordinate);
733
734- /* Add new devices to global lists. Register in proc, sysfs. */
735- pci_bus_add_devices(phb->bus);
736+ /* Finish adding it : resource allocation, adding devices, etc...
737+ * Note that we need to perform the finish pass on the -parent-
738+ * bus of the EADS bridge so the bridge device itself gets
739+ * properly added
740+ */
741+ pcibios_finish_adding_new_bus(phb->bus);
742 }
743
744 static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
745@@ -206,22 +207,19 @@ static int dlpar_add_pci_slot(char *drc_
746 static int dlpar_remove_root_bus(struct pci_controller *phb)
747 {
748 struct pci_bus *phb_bus;
749- int rc;
750
751 phb_bus = phb->bus;
752+ pr_debug("PCI: -> removing root bus %04x:%02x\n",
753+ pci_domain_nr(phb_bus), phb_bus->number);
754+
755+ /* We cannot to remove a root bus that has children */
756 if (!(list_empty(&phb_bus->children) &&
757 list_empty(&phb_bus->devices))) {
758+ pr_debug("PCI: PHB removal failed, bus not empty !\n");
759 return -EBUSY;
760 }
761
762- rc = pcibios_remove_root_bus(phb);
763- if (rc)
764- return -EIO;
765-
766- device_unregister(phb_bus->bridge);
767- pci_remove_bus(phb_bus);
768-
769- return 0;
770+ return remove_phb_dynamic(phb);
771 }
772
773 static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
774@@ -233,6 +231,8 @@ static int dlpar_remove_phb(char *drc_na
775 if (!pcibios_find_pci_bus(dn))
776 return -EINVAL;
777
778+ pr_debug("PCI: Removing PHB %s...\n", dn->full_name);
779+
780 /* If pci slot is hotplugable, use hotplug to remove it */
781 slot = find_php_slot(dn);
782 if (slot) {
783@@ -378,25 +378,36 @@ int dlpar_remove_pci_slot(char *drc_name
784 if (!bus)
785 return -EINVAL;
786
787- /* If pci slot is hotplugable, use hotplug to remove it */
788+ pr_debug("PCI: Removing PCI slot below EADS bridge %s\n",
789+ bus->self ? pci_name(bus->self) : "<!PHB!>");
790+
791+ /* If pci slot is hotplugable, remove hotplug data structures */
792 slot = find_php_slot(dn);
793 if (slot) {
794+ pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n",
795+ pci_domain_nr(bus), bus->number);
796 if (rpaphp_deregister_slot(slot)) {
797 printk(KERN_ERR
798 "%s: unable to remove hotplug slot %s\n",
799 __func__, drc_name);
800 return -EIO;
801 }
802- } else
803- pcibios_remove_pci_devices(bus);
804+ }
805+
806+ /* Remove all devices below slot */
807+ pcibios_remove_pci_devices(bus);
808
809+ /* Unmap PCI IO space */
810 if (pcibios_unmap_io_space(bus)) {
811 printk(KERN_ERR "%s: failed to unmap bus range\n",
812 __func__);
813 return -ERANGE;
814 }
815
816+ /* Remove the EADS bridge device itself */
817 BUG_ON(!bus->self);
818+ pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
819+ eeh_remove_bus_device(bus->self);
820 pci_remove_bus_device(bus->self);
821 return 0;
822 }
823--- a/drivers/pci/hotplug/rpaphp_slot.c
824+++ b/drivers/pci/hotplug/rpaphp_slot.c
825@@ -145,9 +145,5 @@ int rpaphp_register_slot(struct slot *sl
826 list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
827 info("Slot [%s] registered\n", slot->name);
828 return 0;
829-
830-sysfs_fail:
831- pci_hp_deregister(php_slot);
832- return retval;
833 }
834