alpha/PCI: Move pci_map_irq()/pci_swizzle() out of initdata
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Thu, 26 Oct 2017 14:54:15 +0000 (15:54 +0100)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 26 Oct 2017 16:53:38 +0000 (11:53 -0500)
The introduction of {map/swizzle}_irq() hooks in the struct pci_host_bridge
allowed to replace the pci_fixup_irqs() PCI IRQ allocation in alpha arch
PCI code with per-bridge map/swizzle functions with commit 0e4c2eeb758a
("alpha/PCI: Replace pci_fixup_irqs() call with host bridge IRQ mapping
hooks").

As a side effect of converting PCI IRQ allocation to the struct
pci_host_bridge {map/swizzle}_irq() hooks mechanism, the actual PCI IRQ
allocation function (ie pci_assign_irq()) is carried out per-device in
pci_device_probe() that is called when a PCI device driver is about to be
probed.

This means that, for drivers compiled as loadable modules, the actual PCI
device IRQ allocation can now happen after the system has booted so the
struct pci_host_bridge {map/swizzle}_irq() hooks pci_assign_irq() relies on
must stay valid after the system has booted so that PCI core can carry out
PCI IRQ allocation correctly.

Most of the alpha board structures pci_map_irq() and pci_swizzle() hooks
(that are used to initialize their struct pci_host_bridge equivalent
through the alpha_mv global variable - that represents the struct
alpha_machine_vector of the running kernel) are marked as
__init/__initdata; this causes freed memory dereferences when PCI IRQ
allocation is carried out after the kernel has booted (ie when loading PCI
drivers as loadable module) because when the kernel tries to bind the PCI
device to its (module) driver, the function pci_assign_irq() is called,
that in turn retrieves the struct pci_host_bridge {map/swizzle}_irq() hooks
to carry out PCI IRQ allocation; if those hooks are marked as __init
code/__initdata they point at freed/invalid memory.

Fix the issue by removing the __init/__initdata markers from all subarch
struct alpha_machine_vector.pci_map_irq()/pci_swizzle() functions (and
data).

Fixes: 0e4c2eeb758a ("alpha/PCI: Replace pci_fixup_irqs() call with host bridge IRQ mapping hooks")
Link: http://lkml.kernel.org/r/alpine.LRH.2.21.1710251043170.7098@math.ut.ee
Reported-by: Meelis Roos <mroos@linux.ee>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Meelis Roos <mroos@linux.ee>
Cc: Matt Turner <mattst88@gmail.com>
17 files changed:
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_dp264.c
arch/alpha/kernel/sys_eb64p.c
arch/alpha/kernel/sys_eiger.c
arch/alpha/kernel/sys_miata.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_noritake.c
arch/alpha/kernel/sys_rawhide.c
arch/alpha/kernel/sys_ruffian.c
arch/alpha/kernel/sys_rx164.c
arch/alpha/kernel/sys_sable.c
arch/alpha/kernel/sys_sio.c
arch/alpha/kernel/sys_sx164.c
arch/alpha/kernel/sys_takara.c
arch/alpha/kernel/sys_wildfire.c

index 118dc6af1805098e1f69439b07dc4885627a21d6..7ad074fd5ab5066bf7534713da4060852fd6bcba 100644 (file)
@@ -181,10 +181,10 @@ alcor_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 alcor_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[7][5] __initdata = {
+       static char irq_tab[7][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                /* note: IDSEL 17 is XLT only */
                {16+13, 16+13, 16+13, 16+13, 16+13},    /* IdSel 17,  TULIP  */
index 4c50f8f40cbbfe73c39ffd0062d1937dd892b9a6..c0fa1fe5ce773fbda6d4b0a4253052a60dff98af 100644 (file)
@@ -173,10 +173,10 @@ pc164_init_irq(void)
  * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
  */
 
-static inline int __init
+static inline int
 eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT  INTA  INTB  INTC   INTD */
                {16+0, 16+0, 16+5,  16+9, 16+13},  /* IdSel 6,  slot 0, J25 */
                {16+1, 16+1, 16+6, 16+10, 16+14},  /* IdSel 7,  slot 1, J26 */
@@ -203,10 +203,10 @@ eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
  * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
  */
 
-static inline int __init
+static inline int
 cabriolet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT   INTA  INTB  INTC   INTD */
                { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5,  slot 2, J21 */
                { 16+0, 16+0, 16+5,  16+9, 16+13}, /* IdSel 6,  slot 0, J19 */
@@ -287,10 +287,10 @@ cia_cab_init_pci(void)
  * 
  */
 
-static inline int __init
+static inline int
 alphapc164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[7][5] __initdata = {
+       static char irq_tab[7][5] = {
                /*INT   INTA  INTB   INTC   INTD */
                { 16+2, 16+2, 16+9,  16+13, 16+17}, /* IdSel  5, slot 2, J20 */
                { 16+0, 16+0, 16+7,  16+11, 16+15}, /* IdSel  6, slot 0, J29 */
index 6c35159bc00eb47860516bda8868801a74bbe868..9e1e40ea1d14be8e20e99155e5f589b33499e5ba 100644 (file)
@@ -356,7 +356,7 @@ clipper_init_irq(void)
  *  10  64 bit PCI option slot 3 (not bus 0)
  */
 
-static int __init
+static int
 isa_irq_fixup(const struct pci_dev *dev, int irq)
 {
        u8 irq8;
@@ -372,10 +372,10 @@ isa_irq_fixup(const struct pci_dev *dev, int irq)
        return irq8 & 0xf;
 }
 
-static int __init
+static int
 dp264_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[6][5] __initdata = {
+       static char irq_tab[6][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 5 ISA Bridge */
                { 16+ 3, 16+ 3, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin*/
@@ -394,10 +394,10 @@ dp264_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return isa_irq_fixup(dev, irq);
 }
 
-static int __init
+static int
 monet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[13][5] __initdata = {
+       static char irq_tab[13][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {    45,    45,    45,    45,    45}, /* IdSel 3 21143 PCI1 */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 4 unused */
@@ -423,7 +423,7 @@ monet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
 }
 
-static u8 __init
+static u8
 monet_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        struct pci_controller *hose = dev->sysdata;
@@ -456,10 +456,10 @@ monet_swizzle(struct pci_dev *dev, u8 *pinp)
        return slot;
 }
 
-static int __init
+static int
 webbrick_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[13][5] __initdata = {
+       static char irq_tab[13][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 7 ISA Bridge */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 8 unused */
@@ -478,10 +478,10 @@ webbrick_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
 }
 
-static int __init
+static int
 clipper_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[7][5] __initdata = {
+       static char irq_tab[7][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 1 slot 1 */
                { 16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 2 slot 2 */
index ad40a425e841c2f1c99904a43c45fa2c9a281d1d..372661c5653793f7695fb1e36598bb38269d0552 100644 (file)
@@ -167,10 +167,10 @@ eb64p_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 eb64p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT  INTA  INTB  INTC   INTD */
                {16+7, 16+7, 16+7, 16+7,  16+7},  /* IdSel 5,  slot ?, ?? */
                {16+0, 16+0, 16+2, 16+4,  16+9},  /* IdSel 6,  slot ?, ?? */
index 15f42083bdb3501fc041c2e1634225674fe849b3..2731738b5872c415637d87aaa70e495fd85f7d75 100644 (file)
@@ -141,7 +141,7 @@ eiger_init_irq(void)
        }
 }
 
-static int __init
+static int
 eiger_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u8 irq_orig;
@@ -158,7 +158,7 @@ eiger_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return irq_orig - 0x80;
 }
 
-static u8 __init
+static u8
 eiger_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        struct pci_controller *hose = dev->sysdata;
index d5b9776a608d91d957b8a362c3da3e8c93ccaad5..731d693fa1f99cf3d5d493676217eebf7c323b85 100644 (file)
@@ -149,10 +149,10 @@ miata_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-        static char irq_tab[18][5] __initdata = {
+        static char irq_tab[18][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8},  /* IdSel 14,  DC21142 */
                {   -1,    -1,    -1,    -1,    -1},  /* IdSel 15,  EIDE    */
@@ -196,7 +196,7 @@ miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 miata_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index 5e82dc1ad6f2dc096cdc217f9c32f46180c6a7a6..350ec9c8335b4dff3ff36b3e7828ce5ee5b6cc61 100644 (file)
@@ -145,10 +145,10 @@ mikasa_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 mikasa_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[8][5] __initdata = {
+       static char irq_tab[8][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {16+12, 16+12, 16+12, 16+12, 16+12},    /* IdSel 17,  SCSI */
                {   -1,    -1,    -1,    -1,    -1},    /* IdSel 18,  PCEB */
index 8ae04a121186e2b090256956b3e7e425a571e1c4..d019e4ce07bd946be467ce996e105c8a345a8bf7 100644 (file)
@@ -62,7 +62,7 @@ nautilus_init_irq(void)
        common_init_isa_dma();
 }
 
-static int __init
+static int
 nautilus_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /* Preserve the IRQ set up by the console.  */
index 063e594fd96934f90971172c25f84fc8e9a89255..2301678d9f9dc747b95867e5b3341b69f3b7543a 100644 (file)
@@ -193,10 +193,10 @@ noritake_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 noritake_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[15][5] __initdata = {
+       static char irq_tab[15][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                /* note: IDSELs 16, 17, and 25 are CORELLE only */
                { 16+1,  16+1,  16+1,  16+1,  16+1},  /* IdSel 16,  QLOGIC */
@@ -221,7 +221,7 @@ noritake_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 noritake_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index dfd510ae5d8c82701b5a5fbf278bc0af699d56a5..546822d07dc7a2973e590b61b3396a8d21e05320 100644 (file)
@@ -221,10 +221,10 @@ rawhide_init_irq(void)
  * 
  */
 
-static int __init
+static int
 rawhide_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 */
                { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
index a3f4852571700183d033126a8b82ff46613c2943..3b35e19134922fc46c0c86e3d4eb81c5cb111fba 100644 (file)
@@ -117,10 +117,10 @@ ruffian_kill_arch (int mode)
  *
  */
 
-static int __init
+static int
 ruffian_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-        static char irq_tab[11][5] __initdata = {
+        static char irq_tab[11][5] = {
              /*INT  INTA INTB INTC INTD */
                {-1,  -1,  -1,  -1,  -1},  /* IdSel 13,  21052       */
                {-1,  -1,  -1,  -1,  -1},  /* IdSel 14,  SIO         */
@@ -139,7 +139,7 @@ ruffian_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index 08ee737d4fba1559c6fe09ce2cb7a98e2fc23ffe..e178007107ef36f44cbe146d9b4c26756457897e 100644 (file)
@@ -142,7 +142,7 @@ rx164_init_irq(void)
  * 
  */
 
-static int __init
+static int
 rx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 #if 0
@@ -156,7 +156,7 @@ rx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
          { 16+1, 16+1, 16+6, 16+11, 16+16},      /* IdSel 10, slot 4 */
        };
 #else
-       static char irq_tab[6][5] __initdata = {
+       static char irq_tab[6][5] = {
          /*INT   INTA  INTB  INTC   INTD */
          { 16+0, 16+0, 16+6, 16+11, 16+16},      /* IdSel 5,  slot 0 */
          { 16+1, 16+1, 16+7, 16+12, 16+17},      /* IdSel 6,  slot 1 */
index 8a0aa6d67b5319c18d9ba050f4d6364d4108dc5b..86d259c2612d8b8c4a0642fc6d83944d08a0aa67 100644 (file)
@@ -192,10 +192,10 @@ sable_init_irq(void)
  * with the values in the irq swizzling tables above.
  */
 
-static int __init
+static int
 sable_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[9][5] __initdata = {
+       static char irq_tab[9][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 32+0,  32+0,  32+0,  32+0,  32+0},  /* IdSel 0,  TULIP  */
                { 32+1,  32+1,  32+1,  32+1,  32+1},  /* IdSel 1,  SCSI   */
@@ -374,10 +374,10 @@ lynx_init_irq(void)
  * with the values in the irq swizzling tables above.
  */
 
-static int __init
+static int
 lynx_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[19][5] __initdata = {
+       static char irq_tab[19][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {   -1,    -1,    -1,    -1,    -1},  /* IdSel 13,  PCEB   */
                {   -1,    -1,    -1,    -1,    -1},  /* IdSel 14,  PPB    */
@@ -404,7 +404,7 @@ lynx_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 lynx_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index febd24eba7a6a26d7251dfdd85473d00b531669a..9fd2895639d594d7c456c77994ef5e1ecd1bb1a2 100644 (file)
@@ -144,7 +144,7 @@ sio_fixup_irq_levels(unsigned int level_bits)
        outb((level_bits >> 8) & 0xff, 0x4d1);
 }
 
-static inline int __init
+static inline int
 noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /*
@@ -165,7 +165,7 @@ noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
         * that they use the default INTA line, if they are interrupt
         * driven at all).
         */
-       static char irq_tab[][5] __initdata = {
+       static char irq_tab[][5] = {
                /*INT A   B   C   D */
                { 3,  3,  3,  3,  3}, /* idsel  6 (53c810) */ 
                {-1, -1, -1, -1, -1}, /* idsel  7 (SIO: PCI/ISA bridge) */
@@ -183,10 +183,10 @@ noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return irq >= 0 ? tmp : -1;
 }
 
-static inline int __init
+static inline int
 p2k_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[][5] __initdata = {
+       static char irq_tab[][5] = {
                /*INT A   B   C   D */
                { 0,  0, -1, -1, -1}, /* idsel  6 (53c810) */
                {-1, -1, -1, -1, -1}, /* idsel  7 (SIO: PCI/ISA bridge) */
index d063b360efedc49d7690af17d87d39a93205f56d..23eee54d714ae80b6beb0cd951068298f96bd463 100644 (file)
@@ -94,10 +94,10 @@ sx164_init_irq(void)
  *   9  32 bit PCI option slot 3
  */
 
-static int __init
+static int
 sx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
                { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
index dd0f1eae3c68d27122718485760ce2f2db276bf2..9101f2bb61765ebb37364320d8bf07523110d59f 100644 (file)
@@ -155,10 +155,10 @@ takara_init_irq(void)
  * assign it whatever the hell IRQ we like and it doesn't matter.
  */
 
-static int __init
+static int
 takara_map_irq_srm(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[15][5] __initdata = {
+       static char irq_tab[15][5] = {
                { 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot  6 == device 3 */
                { 16+2, 16+2, 16+2, 16+2, 16+2},   /* slot  7 == device 2 */
                { 16+1, 16+1, 16+1, 16+1, 16+1},   /* slot  8 == device 1 */
@@ -210,7 +210,7 @@ takara_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 takara_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot = PCI_SLOT(dev->devfn);
index ee1874887776bd5c732ce6c964cbe8cb7154d8ef..c3f8b79fe21422af34a2430969d323739d91efbb 100644 (file)
@@ -288,10 +288,10 @@ wildfire_device_interrupt(unsigned long vector)
  *   7  64 bit PCI 1 option slot 7
  */
 
-static int __init
+static int
 wildfire_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[8][5] __initdata = {
+       static char irq_tab[8][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { -1,    -1,    -1,    -1,    -1}, /* IdSel 0 ISA Bridge */
                { 36,    36,    36+1, 36+2, 36+3}, /* IdSel 1 SCSI builtin */