aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorTomasz Nowicki <tn@semihalf.com>2016-01-22 12:16:59 +0100
committerTomasz Nowicki <tn@semihalf.com>2016-01-22 12:16:59 +0100
commit2c0d7f690c060ea8c7f1b469fa29a2684f55df53 (patch)
tree136993a8de630c16f5ea87301a98b00d2ea250be /arch
parentafd2ff9b7e1b367172f18ba7f693dfb62bdcb2dc (diff)
parent9241797c2416068120928c716b6b1c8ccc5ce2ee (diff)
Merge remote-tracking branch 'vality/pci-fixes' into pci-acpi-v3
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/pci.c7
-rw-r--r--arch/alpha/kernel/sys_nautilus.c1
-rw-r--r--arch/arm/kernel/bios32.c9
-rw-r--r--arch/cris/arch-v32/drivers/pci/bios.c12
-rw-r--r--arch/frv/mb93090-mb00/pci-frv.h1
-rw-r--r--arch/frv/mb93090-mb00/pci-irq.c24
-rw-r--r--arch/frv/mb93090-mb00/pci-vdk.c1
-rw-r--r--arch/m68k/coldfire/pci.c8
-rw-r--r--arch/microblaze/pci/pci-common.c9
-rw-r--r--arch/mips/pci/pci.c9
-rw-r--r--arch/mn10300/unit-asb2305/pci-asb2305.h5
-rw-r--r--arch/mn10300/unit-asb2305/pci-irq.c24
-rw-r--r--arch/mn10300/unit-asb2305/pci.c19
-rw-r--r--arch/powerpc/kernel/pci-common.c25
-rw-r--r--arch/sh/drivers/pci/fixups-cayman.c2
-rw-r--r--arch/sh/drivers/pci/fixups-dreamcast.c2
-rw-r--r--arch/sh/drivers/pci/fixups-r7780rp.c2
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c6
-rw-r--r--arch/sh/drivers/pci/fixups-sdk7780.c4
-rw-r--r--arch/sh/drivers/pci/fixups-se7751.c2
-rw-r--r--arch/sh/drivers/pci/fixups-sh03.c2
-rw-r--r--arch/sh/drivers/pci/fixups-snapgear.c2
-rw-r--r--arch/sh/drivers/pci/fixups-titan.c4
-rw-r--r--arch/sh/drivers/pci/pci.c10
-rw-r--r--arch/sh/drivers/pci/pcie-sh7786.c2
-rw-r--r--arch/sparc/kernel/leon_pci.c12
-rw-r--r--arch/sparc/kernel/pci.c23
-rw-r--r--arch/tile/kernel/pci.c10
-rw-r--r--arch/tile/kernel/pci_gx.c10
-rw-r--r--arch/unicore32/kernel/pci.c11
-rw-r--r--arch/x86/include/asm/pci_x86.h7
-rw-r--r--arch/x86/kernel/x86_init.c1
-rw-r--r--arch/x86/pci/acpi.c15
-rw-r--r--arch/x86/pci/irq.c91
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)