openwrtv3/target/linux/brcm47xx/patches-2.6.25/690-mips-allow-pciregister-after-boot.patch

164 lines
4.3 KiB
Diff
Raw Normal View History

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.4/arch/mips/pci/pci.c
===================================================================
--- linux-2.6.25.4.orig/arch/mips/pci/pci.c
+++ linux-2.6.25.4/arch/mips/pci/pci.c
@@ -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.4/drivers/ssb/main.c
===================================================================
--- linux-2.6.25.4.orig/drivers/ssb/main.c
+++ linux-2.6.25.4/drivers/ssb/main.c
@@ -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)
{