diff options
Diffstat (limited to 'target/linux/brcm47xx/patches-2.6.23/690-mips-allow-pciregister-after-boot.patch')
-rw-r--r-- | target/linux/brcm47xx/patches-2.6.23/690-mips-allow-pciregister-after-boot.patch | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-2.6.23/690-mips-allow-pciregister-after-boot.patch b/target/linux/brcm47xx/patches-2.6.23/690-mips-allow-pciregister-after-boot.patch new file mode 100644 index 0000000000..132b41dc5d --- /dev/null +++ b/target/linux/brcm47xx/patches-2.6.23/690-mips-allow-pciregister-after-boot.patch @@ -0,0 +1,163 @@ +Allow registering PCI devices after early boot. + +This is an ugly hack and needs to be rewritten before going upstream. +Index: linux-2.6.23.16/arch/mips/pci/pci.c +=================================================================== +--- linux-2.6.23.16.orig/arch/mips/pci/pci.c 2008-02-20 16:06:36.000000000 +0100 ++++ linux-2.6.23.16/arch/mips/pci/pci.c 2008-02-20 16:09:33.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.23.16/drivers/ssb/main.c +=================================================================== +--- linux-2.6.23.16.orig/drivers/ssb/main.c 2008-02-20 16:06:36.000000000 +0100 ++++ linux-2.6.23.16/drivers/ssb/main.c 2008-02-20 18:33:21.000000000 +0100 +@@ -1185,9 +1185,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) + { |