powerpc: Use cpu_thread_in_core in smp_init for of_spin_map
[safe/jmp/linux-2.6] / arch / powerpc / platforms / pseries / pci_dlpar.c
index 283377a..21a6d55 100644 (file)
@@ -27,6 +27,9 @@
 
 #include <linux/pci.h>
 #include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+#include <asm/eeh.h>
 
 static struct pci_bus *
 find_bus_among_children(struct pci_bus *bus,
@@ -58,6 +61,7 @@ pcibios_find_pci_bus(struct device_node *dn)
 
        return find_bus_among_children(pdn->phb->bus, dn);
 }
+EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
 
 /**
  * pcibios_remove_pci_devices - remove all devices under this bus
@@ -75,26 +79,22 @@ pcibios_remove_pci_devices(struct pci_bus *bus)
                pci_remove_bus_device(dev);
        }
 }
+EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
 /* Must be called before pci_bus_add_devices */
-static void
-pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
+void
+pcibios_fixup_new_pci_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               /*
-                * Skip already-present devices (which are on the
-                * global device list.)
-                */
-               if (list_empty(&dev->global_list)) {
+               /* Skip already-added devices */
+               if (!dev->is_added) {
                        int i;
 
-                       /* Need to setup IOMMU tables */
-                       ppc_md.iommu_dev_setup(dev);
+                       /* Fill device archdata and setup iommu table */
+                       pcibios_setup_new_device(dev);
 
-                       if(fix_bus)
-                               pcibios_fixup_device_resources(dev, bus);
                        pci_read_irq_line(dev);
                        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
                                struct resource *r = &dev->resource[i];
@@ -106,13 +106,13 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
                }
        }
 }
+EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
 
 static int
 pcibios_pci_config_bridge(struct pci_dev *dev)
 {
        u8 sec_busno;
        struct pci_bus *child_bus;
-       struct pci_dev *child_dev;
 
        /* Get busno of downstream bus */
        pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
@@ -120,22 +120,20 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
        /* Add to children of PCI bridge dev->bus */
        child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
        if (!child_bus) {
-               printk (KERN_ERR "%s: could not add second bus\n", __FUNCTION__);
+               printk (KERN_ERR "%s: could not add second bus\n", __func__);
                return -EIO;
        }
        sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
 
        pci_scan_child_bus(child_bus);
 
-       list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
-               eeh_add_device_late(child_dev);
-       }
-
-       /* Fixup new pci devices without touching bus struct */
-       pcibios_fixup_new_pci_devices(child_bus, 0);
+       /* Fixup new pci devices */
+       pcibios_fixup_new_pci_devices(child_bus);
 
        /* Make the discovered devices available */
        pci_bus_add_devices(child_bus);
+
+       eeh_add_device_tree_late(child_bus);
        return 0;
 }
 
@@ -152,23 +150,63 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
 void
 pcibios_add_pci_devices(struct pci_bus * bus)
 {
-       int slotno, num;
+       int slotno, num, mode;
        struct pci_dev *dev;
        struct device_node *dn = pci_bus_to_OF_node(bus);
 
        eeh_add_device_tree_early(dn);
 
-       /* pci_scan_slot should find all children */
-       slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
-       num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
-       if (num) {
-               pcibios_fixup_new_pci_devices(bus, 1);
-               pci_bus_add_devices(bus);
-       }
+       mode = PCI_PROBE_NORMAL;
+       if (ppc_md.pci_probe_mode)
+               mode = ppc_md.pci_probe_mode(bus);
+
+       if (mode == PCI_PROBE_DEVTREE) {
+               /* use ofdt-based probe */
+               of_scan_bus(dn, bus);
+               if (!list_empty(&bus->devices)) {
+                       pcibios_fixup_new_pci_devices(bus);
+                       pci_bus_add_devices(bus);
+                       eeh_add_device_tree_late(bus);
+               }
+       } else if (mode == PCI_PROBE_NORMAL) {
+               /* use legacy probe */
+               slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+               num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
+               if (num) {
+                       pcibios_fixup_new_pci_devices(bus);
+                       pci_bus_add_devices(bus);
+                       eeh_add_device_tree_late(bus);
+               }
 
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               eeh_add_device_late (dev);
-               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-                       pcibios_pci_config_bridge(dev);
+               list_for_each_entry(dev, &bus->devices, bus_list)
+                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+                               pcibios_pci_config_bridge(dev);
        }
 }
+EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
+
+struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
+{
+       struct pci_controller *phb;
+       int primary;
+
+       primary = list_empty(&hose_list);
+       phb = pcibios_alloc_controller(dn);
+       if (!phb)
+               return NULL;
+       rtas_setup_phb(phb);
+       pci_process_bridge_OF_ranges(phb, dn, 0);
+
+       pci_devs_phb_init_dynamic(phb);
+
+       if (dn->child)
+               eeh_add_device_tree_early(dn);
+
+       scan_phb(phb);
+       pcibios_fixup_new_pci_devices(phb->bus);
+       pci_bus_add_devices(phb->bus);
+       eeh_add_device_tree_late(phb->bus);
+
+       return phb;
+}
+EXPORT_SYMBOL_GPL(init_phb_dynamic);