diff options
author | Tomasz Nowicki <tn@semihalf.com> | 2016-01-22 12:16:59 +0100 |
---|---|---|
committer | Tomasz Nowicki <tn@semihalf.com> | 2016-01-22 12:16:59 +0100 |
commit | 2c0d7f690c060ea8c7f1b469fa29a2684f55df53 (patch) | |
tree | 136993a8de630c16f5ea87301a98b00d2ea250be /arch | |
parent | afd2ff9b7e1b367172f18ba7f693dfb62bdcb2dc (diff) | |
parent | 9241797c2416068120928c716b6b1c8ccc5ce2ee (diff) |
Merge remote-tracking branch 'vality/pci-fixes' into pci-acpi-v3
Diffstat (limited to 'arch')
34 files changed, 204 insertions, 168 deletions
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 5f387ee5b5c5..1c3c51392fad 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -354,7 +354,6 @@ common_init_pci(void) pcibios_claim_console_setup(); pci_assign_unassigned_resources(); - pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); for (hose = hose_head; hose; hose = hose->next) { bus = hose->bus; if (bus) @@ -362,6 +361,12 @@ common_init_pci(void) } } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = alpha_mv.pci_swizzle; + bridge->map_irq = alpha_mv.pci_map_irq; + return 0; +} struct pci_controller * __init alloc_pci_controller(void) diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c index 2cfaa0e5c577..a3086dc8135c 100644 --- a/arch/alpha/kernel/sys_nautilus.c +++ b/arch/alpha/kernel/sys_nautilus.c @@ -254,7 +254,6 @@ nautilus_init_pci(void) /* pci_common_swizzle() relies on bus->self being NULL for the root bus, so just clear it. */ bus->self = NULL; - pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); pci_bus_add_devices(bus); } diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 066f7f9ba411..962d05bcef4f 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -410,6 +410,13 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return irq; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pcibios_swizzle; + bridge->map_irq = pcibios_map_irq; + return 0; +} + static int pcibios_init_resources(int busnr, struct pci_sys_data *sys) { int ret; @@ -510,8 +517,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw) if (hw->postinit) hw->postinit(); - pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq); - list_for_each_entry(sys, &head, node) { struct pci_bus *bus = sys->bus; diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c index 64a5fb93767d..2b7b79f7447e 100644 --- a/arch/cris/arch-v32/drivers/pci/bios.c +++ b/arch/cris/arch-v32/drivers/pci/bios.c @@ -80,9 +80,10 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) return 0; } -int pcibios_enable_irq(struct pci_dev *dev) +int pcibios_enable_irq(struct pci_dev *dev, u8 slot, u8 pin) { - dev->irq = EXT_INTR_VECT; + if (!dev->msi_enabled) + dev->irq = EXT_INTR_VECT; return 0; } @@ -92,8 +93,11 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) if ((err = pcibios_enable_resources(dev, mask)) < 0) return err; + return 0; +} - if (!dev->msi_enabled) - pcibios_enable_irq(dev); +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->map_irq = pcibios_enable_irq; return 0; } diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h index d51992ff5a61..1537700c04b0 100644 --- a/arch/frv/mb93090-mb00/pci-frv.h +++ b/arch/frv/mb93090-mb00/pci-frv.h @@ -28,5 +28,4 @@ extern struct pci_ops *__nongpreldata pci_root_ops; extern unsigned int pcibios_irq_mask; void pcibios_irq_init(void); -void pcibios_fixup_irqs(void); void pcibios_enable_irq(struct pci_dev *dev); diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c index 1c35c93f942b..2fde211499ac 100644 --- a/arch/frv/mb93090-mb00/pci-irq.c +++ b/arch/frv/mb93090-mb00/pci-irq.c @@ -40,19 +40,19 @@ void __init pcibios_irq_init(void) { } -void __init pcibios_fixup_irqs(void) +int pcibios_map_irq(struct pci_dev *dev, uint8_t slot, uint8_t pin) { - struct pci_dev *dev = NULL; - uint8_t line, pin; - - for_each_pci_dev(dev) { - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin) { - dev->irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1]; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line); - } + int irq; + + irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1]; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + return irq; +} + +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->map_irq = pcibios_map_irq; + return 0; } void pcibios_enable_irq(struct pci_dev *dev) diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index f211839e2cae..22d59ed70e73 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -387,7 +387,6 @@ int __init pcibios_init(void) bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); pcibios_irq_init(); - pcibios_fixup_irqs(); pcibios_resource_survey(); if (!bus) return 0; diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c index 821de928dc3f..86661cda7b0a 100644 --- a/arch/m68k/coldfire/pci.c +++ b/arch/m68k/coldfire/pci.c @@ -319,11 +319,17 @@ static int __init mcf_pci_init(void) rootbus->resource[0] = &mcf_pci_io; rootbus->resource[1] = &mcf_pci_mem; - pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq); pci_bus_size_bridges(rootbus); pci_bus_assign_resources(rootbus); pci_bus_add_devices(rootbus); return 0; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pci_common_swizzle; + bridge->map_irq = mcf_pci_map_irq; + return 0; +} + subsys_initcall(mcf_pci_init); diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ae838ed5fcf2..99ea108514ec 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -855,12 +855,15 @@ void pcibios_setup_bus_devices(struct pci_bus *bus) * code and is needed by the DMA init */ set_dev_node(&dev->dev, pcibus_to_node(dev->bus)); - - /* Read default IRQs and fixup if necessary */ - dev->irq = of_irq_parse_and_map_pci(dev, 0, 0); } } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->map_irq = of_irq_parse_and_map_pci; + return 0; +} + void pcibios_fixup_bus(struct pci_bus *bus) { /* When called from the generic PCI probe, read PCI<->PCI bridge diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index b8a0bf5766f2..137d3fea5b9c 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -247,13 +247,18 @@ static int __init pcibios_init(void) for (hose = hose_head; hose; hose = hose->next) pcibios_scanbus(hose); - pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq); - pci_initialized = 1; return 0; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pci_common_swizzle; + bridge->map_irq = pcibios_map_irq; + return 0; +} + subsys_initcall(pcibios_init); static int pcibios_enable_resources(struct pci_dev *dev, int mask) diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h index 96c484b12226..b7d55267a1b6 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.h +++ b/arch/mn10300/unit-asb2305/pci-asb2305.h @@ -60,9 +60,6 @@ struct irq_routing_table { } __attribute__((packed)); extern unsigned int pcibios_irq_mask; - -extern void pcibios_irq_init(void); -extern void pcibios_fixup_irqs(void); -extern void pcibios_enable_irq(struct pci_dev *dev); +extern int pci_map_irq(struct pci_dev *, u8 slot, u8 pin); #endif /* PCI_ASB2305_H */ diff --git a/arch/mn10300/unit-asb2305/pci-irq.c b/arch/mn10300/unit-asb2305/pci-irq.c index fcb28ceb824d..d7d2ce92caf7 100644 --- a/arch/mn10300/unit-asb2305/pci-irq.c +++ b/arch/mn10300/unit-asb2305/pci-irq.c @@ -20,27 +20,11 @@ #include <asm/smp.h> #include "pci-asb2305.h" -void __init pcibios_irq_init(void) +int pci_map_irq(struct pci_dev *, u8 slot, u8 pin) { -} - -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - u8 line, pin; + u8 line; - for_each_pci_dev(dev) { - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin) { - dev->irq = XIRQ1; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - dev->irq); - } - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line); - } -} - -void pcibios_enable_irq(struct pci_dev *dev) -{ + dev->irq = XIRQ1; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line); } diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 3dfe2d31c67b..c9fc19dba9a9 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c @@ -375,14 +375,17 @@ static int __init pcibios_init(void) bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); if (!bus) return 0; - - pcibios_irq_init(); - pcibios_fixup_irqs(); pcibios_resource_survey(); pci_bus_add_devices(bus); return 0; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->map_irq = pci_map_irq; + return 0; +} + arch_initcall(pcibios_init); char *__init pcibios_setup(char *str) @@ -395,16 +398,6 @@ char *__init pcibios_setup(char *str) return str; } -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - int err; - - err = pci_enable_resources(dev, mask); - if (err == 0) - pcibios_enable_irq(dev); - return err; -} - /* * disable the ethernet chipset */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 0f7a60f1e9f6..9fe033af98ad 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -232,7 +232,7 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) * If the interrupt is used, then gets the interrupt line from the * openfirmware and sets it in the pci_dev and pci_config line. */ -static int pci_read_irq_line(struct pci_dev *pci_dev) +static int pci_read_irq_line(struct pci_dev *pci_dev, u8 pin) { struct of_phandle_args oirq; unsigned int virq; @@ -244,7 +244,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) #endif /* Try to get a mapping from the device-tree */ if (of_irq_parse_pci(pci_dev, &oirq)) { - u8 line, pin; + u8 line; /* If that fails, lets fallback to what is in the config * space and map that through the default controller. We @@ -253,10 +253,6 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) * either provide a proper interrupt tree or don't use this * function. */ - if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) - return -1; - if (pin == 0) - return -1; if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || line == 0xff || line == 0) { return -1; @@ -281,9 +277,16 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) pr_debug(" Mapped to linux irq %d\n", virq); - pci_dev->irq = virq; + return virq; +} - return 0; +static int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* Read default IRQs and fixup if necessary */ + dev->irq = pci_read_irq_line(dev, pin); + if (ppc_md.pci_irq_fixup) + ppc_md.pci_irq_fixup(dev); + return dev->irq; } /* @@ -785,6 +788,7 @@ int pci_proc_domain(struct pci_bus *bus) int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) { + bridge->map_irq = pci_map_irq; if (ppc_md.pcibios_root_bridge_prepare) return ppc_md.pcibios_root_bridge_prepare(bridge); @@ -984,11 +988,6 @@ static void pcibios_setup_device(struct pci_dev *dev) phb = pci_bus_to_host(dev->bus); if (phb->controller_ops.dma_dev_setup) phb->controller_ops.dma_dev_setup(dev); - - /* Read default IRQs and fixup if necessary */ - pci_read_irq_line(dev); - if (ppc_md.pci_irq_fixup) - ppc_md.pci_irq_fixup(dev); } int pcibios_add_device(struct pci_dev *dev) diff --git a/arch/sh/drivers/pci/fixups-cayman.c b/arch/sh/drivers/pci/fixups-cayman.c index edc2fb7a5bb2..32467884d6f7 100644 --- a/arch/sh/drivers/pci/fixups-cayman.c +++ b/arch/sh/drivers/pci/fixups-cayman.c @@ -5,7 +5,7 @@ #include <cpu/irq.h> #include "pci-sh5.h" -int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin) { int result = -1; diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index 1d1c5a227e50..9d597f7ab8dd 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c @@ -76,7 +76,7 @@ static void gapspci_fixup_resources(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources); -int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin) { /* * The interrupt routing semantics here are quite trivial. diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c index 57ed3f09d0c2..2c9b58f848dd 100644 --- a/arch/sh/drivers/pci/fixups-r7780rp.c +++ b/arch/sh/drivers/pci/fixups-r7780rp.c @@ -15,7 +15,7 @@ #include <linux/sh_intc.h> #include "pci-sh4.h" -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { return evt2irq(0xa20) + slot; } diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c index eaddb56c45c6..358ac104f08c 100644 --- a/arch/sh/drivers/pci/fixups-rts7751r2d.c +++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c @@ -20,18 +20,18 @@ #define PCIMCR_MRSET_OFF 0xBFFFFFFF #define PCIMCR_RFSH_OFF 0xFFFFFFFB -static u8 rts7751r2d_irq_tab[] __initdata = { +static u8 rts7751r2d_irq_tab[] = { IRQ_PCI_INTA, IRQ_PCI_INTB, IRQ_PCI_INTC, IRQ_PCI_INTD, }; -static char lboxre2_irq_tab[] __initdata = { +static char lboxre2_irq_tab[] = { IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD, }; -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { if (mach_is_lboxre2()) return lboxre2_irq_tab[slot]; diff --git a/arch/sh/drivers/pci/fixups-sdk7780.c b/arch/sh/drivers/pci/fixups-sdk7780.c index c0a015ae6ecf..24e96dfbdb22 100644 --- a/arch/sh/drivers/pci/fixups-sdk7780.c +++ b/arch/sh/drivers/pci/fixups-sdk7780.c @@ -22,7 +22,7 @@ #define IRQ_INTD evt2irq(0xa80) /* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */ -static char sdk7780_irq_tab[4][16] __initdata = { +static char sdk7780_irq_tab[4][16] = { /* INTA */ { IRQ_INTA, IRQ_INTD, IRQ_INTC, IRQ_INTD, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, @@ -37,7 +37,7 @@ static char sdk7780_irq_tab[4][16] __initdata = { -1, -1, -1 }, }; -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { return sdk7780_irq_tab[pin-1][slot]; } diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c index 84a88ca92008..1cb8d0ac4fdb 100644 --- a/arch/sh/drivers/pci/fixups-se7751.c +++ b/arch/sh/drivers/pci/fixups-se7751.c @@ -7,7 +7,7 @@ #include <linux/sh_intc.h> #include "pci-sh4.h" -int __init pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin) { switch (slot) { case 0: return evt2irq(0x3a0); diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c index 16207bef9f52..55ac1ba2c74f 100644 --- a/arch/sh/drivers/pci/fixups-sh03.c +++ b/arch/sh/drivers/pci/fixups-sh03.c @@ -4,7 +4,7 @@ #include <linux/pci.h> #include <linux/sh_intc.h> -int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin) { int irq; diff --git a/arch/sh/drivers/pci/fixups-snapgear.c b/arch/sh/drivers/pci/fixups-snapgear.c index 6e33ba4cd076..a931e5928f58 100644 --- a/arch/sh/drivers/pci/fixups-snapgear.c +++ b/arch/sh/drivers/pci/fixups-snapgear.c @@ -19,7 +19,7 @@ #include <linux/sh_intc.h> #include "pci-sh4.h" -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { int irq = -1; diff --git a/arch/sh/drivers/pci/fixups-titan.c b/arch/sh/drivers/pci/fixups-titan.c index bd1addb1b8be..a9d563e479d5 100644 --- a/arch/sh/drivers/pci/fixups-titan.c +++ b/arch/sh/drivers/pci/fixups-titan.c @@ -19,7 +19,7 @@ #include <mach/titan.h> #include "pci-sh4.h" -static char titan_irq_tab[] __initdata = { +static char titan_irq_tab[] = { TITAN_IRQ_WAN, TITAN_IRQ_LAN, TITAN_IRQ_MPCIA, @@ -27,7 +27,7 @@ static char titan_irq_tab[] __initdata = { TITAN_IRQ_USB, }; -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { int irq = titan_irq_tab[slot]; diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index d5462b7bc514..28f8c9083130 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -144,16 +144,20 @@ static int __init pcibios_init(void) for (hose = hose_head; hose; hose = hose->next) pcibios_scanbus(hose); - pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq); - dma_debug_add_bus(&pci_bus_type); - pci_initialized = 1; return 0; } subsys_initcall(pcibios_init); +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pci_common_swizzle; + bridge->map_irq = pcibios_map_platform_irq; + return 0; +} + /* * Called after each bus is probed, but before its children * are examined. diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index a162a7f86b2e..0167a7352719 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -467,7 +467,7 @@ static int __init pcie_init(struct sh7786_pcie_port *port) return 0; } -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { return evt2irq(0xae0); } diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c index 4371f72ff025..ca11fb8e861a 100644 --- a/arch/sparc/kernel/leon_pci.c +++ b/arch/sparc/kernel/leon_pci.c @@ -13,6 +13,8 @@ #include <asm/leon.h> #include <asm/leon_pci.h> +int (*leon_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); + /* The LEON architecture does not rely on a BIOS or bootloader to setup * PCI for us. The Linux generic routines are used to setup resources, * reset values of configuration-space register settings are preserved. @@ -39,14 +41,20 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info) return; } - /* Setup IRQs of all devices using custom routines */ - pci_fixup_irqs(pci_common_swizzle, info->map_irq); + leon_pci_map_irq = info->map_irq; /* Assign devices with resources */ pci_assign_unassigned_resources(); pci_bus_add_devices(root_bus); } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pci_common_swizzle; + bridge->map_irq = leon_pci_map_irq; + return 0; +} + void pcibios_fixup_bus(struct pci_bus *pbus) { struct pci_dev *dev; diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index badf0951d73c..f29f65993af0 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -337,10 +337,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, } else { dev->hdr_type = PCI_HEADER_TYPE_NORMAL; dev->rom_base_reg = PCI_ROM_ADDRESS; - - dev->irq = sd->op->archdata.irqs[0]; - if (dev->irq == 0xffffffff) - dev->irq = PCI_IRQ_NONE; } pci_parse_of_addrs(sd->op, node, dev); @@ -353,6 +349,25 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, return dev; } +int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq; + struct platform_device *op = of_find_device_by_node(dev->sysdata); + + irq = op->archdata.irqs[0]; + if (irq == 0xffffffff) + irq = PCI_IRQ_NONE; + return irq; +} + +#ifndef CONFIG_LEON_PCI +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->map_irq = pci_map_irq; + return 0; +} +#endif + static void apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) { u32 idx, first, last; diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index 9475a74cd53a..e151d80ab178 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -313,9 +313,6 @@ int __init pcibios_init(void) } } - /* Do machine dependent PCI interrupt routing */ - pci_fixup_irqs(pci_common_swizzle, tile_map_irq); - /* * This comes from the generic Linux PCI driver. * @@ -369,6 +366,13 @@ int __init pcibios_init(void) } subsys_initcall(pcibios_init); +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pci_common_swizzle; + bridge->map_irq = tile_map_irq; + return 0; +} + /* * No bus fixups needed. */ diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c index 4c017d0d2de8..7eb3e2bd2687 100644 --- a/arch/tile/kernel/pci_gx.c +++ b/arch/tile/kernel/pci_gx.c @@ -887,9 +887,6 @@ int __init pcibios_init(void) next_busno = bus->busn_res.end + 1; } - /* Do machine dependent PCI interrupt routing */ - pci_fixup_irqs(pci_common_swizzle, tile_map_irq); - /* * This comes from the generic Linux PCI driver. * @@ -1038,6 +1035,13 @@ alloc_mem_map_failed: } subsys_initcall(pcibios_init); +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pci_common_swizzle; + bridge->map_irq = tile_map_irq; + return 0; +} + /* No bus fixups needed. */ void pcibios_fixup_bus(struct pci_bus *bus) { diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c index d45fa5f3e9c4..42295b20d9e2 100644 --- a/arch/unicore32/kernel/pci.c +++ b/arch/unicore32/kernel/pci.c @@ -101,7 +101,7 @@ void pci_puv3_preinit(void) writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD); } -static int __init pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { if (dev->bus->number == 0) { #ifdef CONFIG_ARCH_FPGA /* 4 pci slots */ @@ -263,8 +263,6 @@ static int __init pci_common_init(void) if (!puv3_bus) panic("PCI: unable to scan bus!"); - pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq); - if (!pci_has_flag(PCI_PROBE_ONLY)) { pci_bus_size_bridges(puv3_bus); pci_bus_assign_resources(puv3_bus); @@ -274,6 +272,13 @@ static int __init pci_common_init(void) } subsys_initcall(pci_common_init); +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + bridge->swizzle_irq = pci_common_swizzle; + bridge->map_irq = pci_puv3_map_irq; + return 0; +} + char * __init pcibios_setup(char *str) { if (!strcmp(str, "debug")) { diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index fa1195dae425..16fd8e99cd4d 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -90,6 +90,7 @@ extern unsigned int pcibios_irq_mask; extern raw_spinlock_t pci_config_lock; +extern int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); extern int (*pcibios_enable_irq)(struct pci_dev *dev); extern void (*pcibios_disable_irq)(struct pci_dev *dev); @@ -119,7 +120,7 @@ extern int __init pci_acpi_init(void); extern void __init pcibios_irq_init(void); extern int __init pcibios_init(void); extern int pci_legacy_init(void); -extern void pcibios_fixup_irqs(void); +extern int pcibios_fixup_irq(struct pci_dev *dev, u8 pin); /* pci-mmconfig.c */ @@ -200,9 +201,9 @@ static inline void mmio_config_writel(void __iomem *pos, u32 val) # define x86_default_pci_init pci_legacy_init # endif # define x86_default_pci_init_irq pcibios_irq_init -# define x86_default_pci_fixup_irqs pcibios_fixup_irqs +# define x86_default_pci_fixup_irq pcibios_fixup_irq #else # define x86_default_pci_init NULL # define x86_default_pci_init_irq NULL -# define x86_default_pci_fixup_irqs NULL +# define x86_default_pci_fixup_irq NULL #endif diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 3839628d962e..810f1dd37d92 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -80,7 +80,6 @@ struct x86_init_ops x86_init __initdata = { .pci = { .init = x86_default_pci_init, .init_irq = x86_default_pci_init_irq, - .fixup_irqs = x86_default_pci_fixup_irqs, }, }; diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 3cd69832d7f4..dda4bc18ddd6 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -373,21 +373,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) return bus; } -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -{ - /* - * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL - * here, pci_create_root_bus() has been called by someone else and - * sysdata is likely to be different from what we expect. Let it go in - * that case. - */ - if (!bridge->dev.parent) { - struct pci_sysdata *sd = bridge->bus->sysdata; - ACPI_COMPANION_SET(&bridge->dev, sd->companion); - } - return 0; -} - int __init pci_acpi_init(void) { struct pci_dev *dev = NULL; diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 32e70343e6fd..7032798f27e2 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -876,9 +876,8 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev) return NULL; } -static int pcibios_lookup_irq(struct pci_dev *dev, int assign) +static int pcibios_lookup_irq(struct pci_dev *dev, u8 pin, int assign) { - u8 pin; struct irq_info *info; int i, pirq, newirq; int irq = 0; @@ -888,7 +887,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) char *msg = NULL; /* Find IRQ pin */ - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (!pin) { dev_dbg(&dev->dev, "no interrupt pin\n"); return 0; @@ -1021,47 +1019,38 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) return 1; } -void __init pcibios_fixup_irqs(void) +int pcibios_fixup_irq(struct pci_dev *dev, u8 pin) { - struct pci_dev *dev = NULL; - u8 pin; - + int irq = dev->irq; DBG(KERN_DEBUG "PCI: IRQ fixup\n"); - for_each_pci_dev(dev) { - /* - * If the BIOS has set an out of range IRQ number, just - * ignore it. Also keep track of which IRQ's are - * already in use. - */ - if (dev->irq >= 16) { - dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq); - dev->irq = 0; - } - /* - * If the IRQ is already assigned to a PCI device, - * ignore its ISA use penalty - */ - if (pirq_penalty[dev->irq] >= 100 && - pirq_penalty[dev->irq] < 100000) - pirq_penalty[dev->irq] = 0; - pirq_penalty[dev->irq]++; + /* + * If the BIOS has set an out of range IRQ number, just + * ignore it. Also keep track of which IRQ's are + * already in use. + */ + if (irq >= 16) { + dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", irq); + irq = 0; } + /* + * If the IRQ is already assigned to a PCI device, + * ignore its ISA use penalty + */ + if (pirq_penalty[irq] >= 100 && + pirq_penalty[irq] < 100000) + pirq_penalty[irq] = 0; + pirq_penalty[irq]++; - if (io_apic_assign_pci_irqs) - return; + if (io_apic_assign_pci_irqs || !pin) + return irq; - dev = NULL; - for_each_pci_dev(dev) { - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (!pin) - continue; + /* + * Still no IRQ? Try to lookup one... + */ + if (!irq && pcibios_lookup_irq(dev, pin, 0)) + irq = dev->irq; - /* - * Still no IRQ? Try to lookup one... - */ - if (!dev->irq) - pcibios_lookup_irq(dev, 0); - } + return irq; } /* @@ -1162,6 +1151,22 @@ void __init pcibios_irq_init(void) } } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + /* + * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL + * here, pci_create_root_bus() has been called by someone else and + * sysdata is likely to be different from what we expect. Let it go in + * that case. + */ + if (!bridge->dev.parent) { + struct pci_sysdata *sd = bridge->bus->sysdata; + ACPI_COMPANION_SET(&bridge->dev, sd->companion); + } + bridge->map_irq = pci_map_irq; + return 0; +} + static void pirq_penalize_isa_irq(int irq, int active) { /* @@ -1186,12 +1191,20 @@ void pcibios_penalize_isa_irq(int irq, int active) pirq_penalize_isa_irq(irq, active); } +int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + dev->irq = pcibios_fixup_irq(dev, pin); + if (pcibios_enable_irq(dev)) + return -1; + return dev->irq; +} + static int pirq_enable_irq(struct pci_dev *dev) { u8 pin = 0; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin && !pcibios_lookup_irq(dev, 1)) { + if (pin && !pcibios_lookup_irq(dev, pin, 1)) { char *msg = ""; if (!io_apic_assign_pci_irqs && dev->irq) |