Allow registering PCI devices after early boot. This is an ugly hack and needs to be rewritten before going upstream. Index: linux-2.6.25/arch/mips/pci/pci.c =================================================================== --- linux-2.6.25.orig/arch/mips/pci/pci.c 2008-04-27 21:49:19.000000000 +0100 +++ linux-2.6.25/arch/mips/pci/pci.c 2008-04-27 21:58:31.000000000 +0100 @@ -21,6 +21,17 @@ */ int pci_probe_only; +/* + * Indicate whether PCI-bios init was already done. + */ +static int pcibios_init_done; + +/* + * The currently used busnumber. + */ +static int next_busno; +static int need_domain_info; + #define PCI_ASSIGN_ALL_BUSSES 1 unsigned int pci_probe = PCI_ASSIGN_ALL_BUSSES; @@ -75,8 +86,32 @@ pcibios_align_resource(void *data, struc res->start = start; } -void __devinit register_pci_controller(struct pci_controller *hose) +/* Most MIPS systems have straight-forward swizzling needs. */ + +static inline u8 bridge_swizzle(u8 pin, u8 slot) +{ + return (((pin - 1) + slot) % 4) + 1; +} + +static u8 common_swizzle(struct pci_dev *dev, u8 *pinp) { + u8 pin = *pinp; + + while (dev->bus->parent) { + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); + /* Move up the chain of bridges. */ + dev = dev->bus->self; + } + *pinp = pin; + + /* The slot is the slot of the last bridge. */ + return PCI_SLOT(dev->devfn); +} + +void register_pci_controller(struct pci_controller *hose) +{ + struct pci_bus *bus; + if (request_resource(&iomem_resource, hose->mem_resource) < 0) goto out; if (request_resource(&ioport_resource, hose->io_resource) < 0) { @@ -84,9 +119,6 @@ void __devinit register_pci_controller(s goto out; } - *hose_tail = hose; - hose_tail = &hose->next; - /* * Do not panic here but later - this might hapen before console init. */ @@ -94,41 +126,47 @@ void __devinit register_pci_controller(s printk(KERN_WARNING "registering PCI controller with io_map_base unset\n"); } - return; -out: - printk(KERN_WARNING - "Skipping PCI bus scan due to resource conflict\n"); -} + if (pcibios_init_done) { + //TODO -/* Most MIPS systems have straight-forward swizzling needs. */ + printk(KERN_INFO "Registering a PCI bus after boot\n"); -static inline u8 bridge_swizzle(u8 pin, u8 slot) -{ - return (((pin - 1) + slot) % 4) + 1; -} + if (!hose->iommu) + PCI_DMA_BUS_IS_PHYS = 1; -static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp) -{ - u8 pin = *pinp; + bus = pci_scan_bus(next_busno, hose->pci_ops, hose); + hose->bus = bus; + need_domain_info = need_domain_info || hose->index; + hose->need_domain_info = need_domain_info; + if (bus) { + next_busno = bus->subordinate + 1; + /* Don't allow 8-bit bus number overflow inside the hose - + reserve some space for bridges. */ + if (next_busno > 224) { + next_busno = 0; + need_domain_info = 1; + } + } + if (!pci_probe_only) + pci_assign_unassigned_resources(); + pci_fixup_irqs(common_swizzle, pcibios_map_irq); + } else { + *hose_tail = hose; + hose_tail = &hose->next; + } - while (dev->bus->parent) { - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - /* Move up the chain of bridges. */ - dev = dev->bus->self; - } - *pinp = pin; + return; - /* The slot is the slot of the last bridge. */ - return PCI_SLOT(dev->devfn); +out: + printk(KERN_WARNING + "Skipping PCI bus scan due to resource conflict\n"); } static int __init pcibios_init(void) { struct pci_controller *hose; struct pci_bus *bus; - int next_busno; - int need_domain_info = 0; /* Scan all of the recorded PCI controllers. */ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { @@ -157,6 +195,7 @@ static int __init pcibios_init(void) if (!pci_probe_only) pci_assign_unassigned_resources(); pci_fixup_irqs(common_swizzle, pcibios_map_irq); + pcibios_init_done = 1; return 0; } Index: linux-2.6.25/drivers/ssb/main.c =================================================================== --- linux-2.6.25.orig/drivers/ssb/main.c 2008-04-27 21:55:32.000000000 +0100 +++ linux-2.6.25/drivers/ssb/main.c 2008-04-27 21:58:31.000000000 +0100 @@ -1191,9 +1191,7 @@ static int __init ssb_modinit(void) /* ssb must be initialized after PCI but before the ssb drivers. * That means we must use some initcall between subsys_initcall * and device_initcall. */ -//FIXME on embedded we need to be early to make sure we can register -// a new PCI bus, if needed. -subsys_initcall(ssb_modinit); +fs_initcall(ssb_modinit); static void __exit ssb_modexit(void) {