x86, ioapic: Print IR_IO_APIC_route_entry when IR is enabled
[pandora-kernel.git] / arch / x86 / kernel / apic / io_apic.c
index 45fd33d..8eb863e 100644 (file)
@@ -76,17 +76,40 @@ int sis_apic_bug = -1;
 static DEFINE_RAW_SPINLOCK(ioapic_lock);
 static DEFINE_RAW_SPINLOCK(vector_lock);
 
-/*
- * # of IRQ routing registers
- */
-int nr_ioapic_registers[MAX_IO_APICS];
+static struct ioapic {
+       /*
+        * # of IRQ routing registers
+        */
+       int nr_registers;
+       /*
+        * Saved state during suspend/resume, or while enabling intr-remap.
+        */
+       struct IO_APIC_route_entry *saved_registers;
+       /* I/O APIC config */
+       struct mpc_ioapic mp_config;
+       /* IO APIC gsi routing info */
+       struct mp_ioapic_gsi  gsi_config;
+       DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
+} ioapics[MAX_IO_APICS];
 
-/* I/O APIC entries */
-struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
-int nr_ioapics;
+#define mpc_ioapic_ver(id)             ioapics[id].mp_config.apicver
+
+int mpc_ioapic_id(int id)
+{
+       return ioapics[id].mp_config.apicid;
+}
 
-/* IO APIC gsi routing info */
-struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
+unsigned int mpc_ioapic_addr(int id)
+{
+       return ioapics[id].mp_config.apicaddr;
+}
+
+struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int id)
+{
+       return &ioapics[id].gsi_config;
+}
+
+int nr_ioapics;
 
 /* The one past the highest gsi number used */
 u32 gsi_top;
@@ -179,6 +202,14 @@ int __init arch_early_irq_init(void)
                io_apic_irqs = ~0UL;
        }
 
+       for (i = 0; i < nr_ioapics; i++) {
+               ioapics[i].saved_registers =
+                       kzalloc(sizeof(struct IO_APIC_route_entry) *
+                               ioapics[i].nr_registers, GFP_KERNEL);
+               if (!ioapics[i].saved_registers)
+                       pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
+       }
+
        cfg = irq_cfgx;
        count = ARRAY_SIZE(irq_cfgx);
        node = cpu_to_node(0);
@@ -297,7 +328,7 @@ struct io_apic {
 static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
 {
        return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
-               + (mp_ioapics[idx].apicaddr & ~PAGE_MASK);
+               + (mpc_ioapic_addr(idx) & ~PAGE_MASK);
 }
 
 static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
@@ -573,7 +604,7 @@ static void clear_IO_APIC (void)
        int apic, pin;
 
        for (apic = 0; apic < nr_ioapics; apic++)
-               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+               for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
                        clear_IO_APIC_pin(apic, pin);
 }
 
@@ -615,74 +646,43 @@ static int __init ioapic_pirq_setup(char *str)
 __setup("pirq=", ioapic_pirq_setup);
 #endif /* CONFIG_X86_32 */
 
-struct IO_APIC_route_entry **alloc_ioapic_entries(void)
-{
-       int apic;
-       struct IO_APIC_route_entry **ioapic_entries;
-
-       ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
-                               GFP_KERNEL);
-       if (!ioapic_entries)
-               return 0;
-
-       for (apic = 0; apic < nr_ioapics; apic++) {
-               ioapic_entries[apic] =
-                       kzalloc(sizeof(struct IO_APIC_route_entry) *
-                               nr_ioapic_registers[apic], GFP_KERNEL);
-               if (!ioapic_entries[apic])
-                       goto nomem;
-       }
-
-       return ioapic_entries;
-
-nomem:
-       while (--apic >= 0)
-               kfree(ioapic_entries[apic]);
-       kfree(ioapic_entries);
-
-       return 0;
-}
-
 /*
  * Saves all the IO-APIC RTE's
  */
-int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+int save_ioapic_entries(void)
 {
        int apic, pin;
-
-       if (!ioapic_entries)
-               return -ENOMEM;
+       int err = 0;
 
        for (apic = 0; apic < nr_ioapics; apic++) {
-               if (!ioapic_entries[apic])
-                       return -ENOMEM;
+               if (!ioapics[apic].saved_registers) {
+                       err = -ENOMEM;
+                       continue;
+               }
 
-               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
-                       ioapic_entries[apic][pin] =
+               for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+                       ioapics[apic].saved_registers[pin] =
                                ioapic_read_entry(apic, pin);
        }
 
-       return 0;
+       return err;
 }
 
 /*
  * Mask all IO APIC entries.
  */
-void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+void mask_ioapic_entries(void)
 {
        int apic, pin;
 
-       if (!ioapic_entries)
-               return;
-
        for (apic = 0; apic < nr_ioapics; apic++) {
-               if (!ioapic_entries[apic])
-                       break;
+               if (!ioapics[apic].saved_registers)
+                       continue;
 
-               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+               for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
                        struct IO_APIC_route_entry entry;
 
-                       entry = ioapic_entries[apic][pin];
+                       entry = ioapics[apic].saved_registers[pin];
                        if (!entry.mask) {
                                entry.mask = 1;
                                ioapic_write_entry(apic, pin, entry);
@@ -692,36 +692,23 @@ void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
 }
 
 /*
- * Restore IO APIC entries which was saved in ioapic_entries.
+ * Restore IO APIC entries which was saved in the ioapic structure.
  */
-int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+int restore_ioapic_entries(void)
 {
        int apic, pin;
 
-       if (!ioapic_entries)
-               return -ENOMEM;
-
        for (apic = 0; apic < nr_ioapics; apic++) {
-               if (!ioapic_entries[apic])
-                       return -ENOMEM;
+               if (!ioapics[apic].saved_registers)
+                       continue;
 
-               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+               for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
                        ioapic_write_entry(apic, pin,
-                                       ioapic_entries[apic][pin]);
+                                          ioapics[apic].saved_registers[pin]);
        }
        return 0;
 }
 
-void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
-{
-       int apic;
-
-       for (apic = 0; apic < nr_ioapics; apic++)
-               kfree(ioapic_entries[apic]);
-
-       kfree(ioapic_entries);
-}
-
 /*
  * Find the IRQ entry number of a certain pin.
  */
@@ -731,7 +718,7 @@ static int find_irq_entry(int apic, int pin, int type)
 
        for (i = 0; i < mp_irq_entries; i++)
                if (mp_irqs[i].irqtype == type &&
-                   (mp_irqs[i].dstapic == mp_ioapics[apic].apicid ||
+                   (mp_irqs[i].dstapic == mpc_ioapic_id(apic) ||
                     mp_irqs[i].dstapic == MP_APIC_ALL) &&
                    mp_irqs[i].dstirq == pin)
                        return i;
@@ -773,7 +760,7 @@ static int __init find_isa_irq_apic(int irq, int type)
        if (i < mp_irq_entries) {
                int apic;
                for(apic = 0; apic < nr_ioapics; apic++) {
-                       if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic)
+                       if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic)
                                return apic;
                }
        }
@@ -942,6 +929,7 @@ static int pin_2_irq(int idx, int apic, int pin)
 {
        int irq;
        int bus = mp_irqs[idx].srcbus;
+       struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
 
        /*
         * Debugging check, we are in big trouble if this message pops up!
@@ -952,7 +940,7 @@ static int pin_2_irq(int idx, int apic, int pin)
        if (test_bit(bus, mp_bus_not_pci)) {
                irq = mp_irqs[idx].srcbusirq;
        } else {
-               u32 gsi = mp_gsi_routing[apic].gsi_base + pin;
+               u32 gsi = gsi_cfg->gsi_base + pin;
 
                if (gsi >= NR_IRQS_LEGACY)
                        irq = gsi;
@@ -1003,7 +991,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
                int lbus = mp_irqs[i].srcbus;
 
                for (apic = 0; apic < nr_ioapics; apic++)
-                       if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
+                       if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic ||
                            mp_irqs[i].dstapic == MP_APIC_ALL)
                                break;
 
@@ -1222,7 +1210,7 @@ static inline int IO_APIC_irq_trigger(int irq)
        int apic, idx, pin;
 
        for (apic = 0; apic < nr_ioapics; apic++) {
-               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+               for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
                        idx = find_irq_entry(apic, pin, mp_INT);
                        if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
                                return irq_trigger(idx);
@@ -1307,6 +1295,16 @@ static int setup_ioapic_entry(int apic_id, int irq,
                 * irq handler will do the explicit EOI to the io-apic.
                 */
                ir_entry->vector = pin;
+
+               apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
+                       "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
+                       "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
+                       "Avail:%X Vector:%02X Dest:%08X "
+                       "SID:%04X SQ:%X SVT:%X)\n",
+                       apic_id, irte.present, irte.fpd, irte.dst_mode,
+                       irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
+                       irte.avail, irte.vector, irte.dest_id,
+                       irte.sid, irte.sq, irte.svt);
        } else {
                entry->delivery_mode = apic->irq_delivery_mode;
                entry->dest_mode = apic->irq_dest_mode;
@@ -1349,15 +1347,15 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
 
        apic_printk(APIC_VERBOSE,KERN_DEBUG
                    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
-                   "IRQ %d Mode:%i Active:%i)\n",
-                   apic_id, mp_ioapics[apic_id].apicid, pin, cfg->vector,
-                   irq, trigger, polarity);
+                   "IRQ %d Mode:%i Active:%i Dest:%d)\n",
+                   apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector,
+                   irq, trigger, polarity, dest);
 
 
-       if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry,
+       if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry,
                               dest, trigger, polarity, cfg->vector, pin)) {
                printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
-                      mp_ioapics[apic_id].apicid, pin);
+                      mpc_ioapic_id(apic_id), pin);
                __clear_irq_vector(irq, cfg);
                return;
        }
@@ -1369,17 +1367,13 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
        ioapic_write_entry(apic_id, pin, entry);
 }
 
-static struct {
-       DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
-} mp_ioapic_routing[MAX_IO_APICS];
-
 static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
 {
        if (idx != -1)
                return false;
 
        apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
-                   mp_ioapics[apic_id].apicid, pin);
+                   mpc_ioapic_id(apic_id), pin);
        return true;
 }
 
@@ -1389,7 +1383,7 @@ static void __init __io_apic_setup_irqs(unsigned int apic_id)
        struct io_apic_irq_attr attr;
        unsigned int pin, irq;
 
-       for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+       for (pin = 0; pin < ioapics[apic_id].nr_registers; pin++) {
                idx = find_irq_entry(apic_id, pin, mp_INT);
                if (io_apic_pin_not_connected(idx, apic_id, pin))
                        continue;
@@ -1511,7 +1505,7 @@ __apicdebuginit(void) print_IO_APIC(void)
        printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
        for (i = 0; i < nr_ioapics; i++)
                printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
-                      mp_ioapics[i].apicid, nr_ioapic_registers[i]);
+                      mpc_ioapic_id(i), ioapics[i].nr_registers);
 
        /*
         * We are a bit conservative about what we expect.  We have to
@@ -1531,17 +1525,19 @@ __apicdebuginit(void) print_IO_APIC(void)
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
        printk("\n");
-       printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid);
+       printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(apic));
        printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
        printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
        printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
        printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
 
        printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
-       printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+       printk(KERN_DEBUG ".......     : max redirection entries: %02X\n",
+               reg_01.bits.entries);
 
        printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
-       printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+       printk(KERN_DEBUG ".......     : IO APIC version: %02X\n",
+               reg_01.bits.version);
 
        /*
         * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
@@ -1566,31 +1562,60 @@ __apicdebuginit(void) print_IO_APIC(void)
 
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
-       printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
-                         " Stat Dmod Deli Vect:\n");
+       if (intr_remapping_enabled) {
+               printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR"
+                       " Pol Stat Indx2 Zero Vect:\n");
+       } else {
+               printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+                       " Stat Dmod Deli Vect:\n");
+       }
 
        for (i = 0; i <= reg_01.bits.entries; i++) {
-               struct IO_APIC_route_entry entry;
-
-               entry = ioapic_read_entry(apic, i);
-
-               printk(KERN_DEBUG " %02x %03X ",
-                       i,
-                       entry.dest
-               );
+               if (intr_remapping_enabled) {
+                       struct IO_APIC_route_entry entry;
+                       struct IR_IO_APIC_route_entry *ir_entry;
+
+                       entry = ioapic_read_entry(apic, i);
+                       ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
+                       printk(KERN_DEBUG " %02x %04X ",
+                               i,
+                               ir_entry->index
+                       );
+                       printk("%1d   %1d    %1d    %1d   %1d   "
+                               "%1d    %1d     %X    %02X\n",
+                               ir_entry->format,
+                               ir_entry->mask,
+                               ir_entry->trigger,
+                               ir_entry->irr,
+                               ir_entry->polarity,
+                               ir_entry->delivery_status,
+                               ir_entry->index2,
+                               ir_entry->zero,
+                               ir_entry->vector
+                       );
+               } else {
+                       struct IO_APIC_route_entry entry;
 
-               printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
-                       entry.mask,
-                       entry.trigger,
-                       entry.irr,
-                       entry.polarity,
-                       entry.delivery_status,
-                       entry.dest_mode,
-                       entry.delivery_mode,
-                       entry.vector
-               );
+                       entry = ioapic_read_entry(apic, i);
+                       printk(KERN_DEBUG " %02x %02X  ",
+                               i,
+                               entry.dest
+                       );
+                       printk("%1d    %1d    %1d   %1d   %1d    "
+                               "%1d    %1d    %02X\n",
+                               entry.mask,
+                               entry.trigger,
+                               entry.irr,
+                               entry.polarity,
+                               entry.delivery_status,
+                               entry.dest_mode,
+                               entry.delivery_mode,
+                               entry.vector
+                       );
+               }
        }
        }
+
        printk(KERN_DEBUG "IRQ to pin mappings:\n");
        for_each_active_irq(irq) {
                struct irq_pin_list *entry;
@@ -1808,7 +1833,7 @@ __apicdebuginit(int) print_ICs(void)
        return 0;
 }
 
-fs_initcall(print_ICs);
+late_initcall(print_ICs);
 
 
 /* Where if anywhere is the i8259 connect in external int mode */
@@ -1825,7 +1850,7 @@ void __init enable_IO_APIC(void)
        for(apic = 0; apic < nr_ioapics; apic++) {
                int pin;
                /* See if any of the pins is in ExtINT mode */
-               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+               for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
                        struct IO_APIC_route_entry entry;
                        entry = ioapic_read_entry(apic, pin);
 
@@ -1949,14 +1974,14 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
                reg_00.raw = io_apic_read(apic_id, 0);
                raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
-               old_id = mp_ioapics[apic_id].apicid;
+               old_id = mpc_ioapic_id(apic_id);
 
-               if (mp_ioapics[apic_id].apicid >= get_physical_broadcast()) {
+               if (mpc_ioapic_id(apic_id) >= get_physical_broadcast()) {
                        printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
-                               apic_id, mp_ioapics[apic_id].apicid);
+                               apic_id, mpc_ioapic_id(apic_id));
                        printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
                                reg_00.bits.ID);
-                       mp_ioapics[apic_id].apicid = reg_00.bits.ID;
+                       ioapics[apic_id].mp_config.apicid = reg_00.bits.ID;
                }
 
                /*
@@ -1965,9 +1990,9 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
                 * 'stuck on smp_invalidate_needed IPI wait' messages.
                 */
                if (apic->check_apicid_used(&phys_id_present_map,
-                                       mp_ioapics[apic_id].apicid)) {
+                                           mpc_ioapic_id(apic_id))) {
                        printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
-                               apic_id, mp_ioapics[apic_id].apicid);
+                               apic_id, mpc_ioapic_id(apic_id));
                        for (i = 0; i < get_physical_broadcast(); i++)
                                if (!physid_isset(i, phys_id_present_map))
                                        break;
@@ -1976,13 +2001,14 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
                        printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
                                i);
                        physid_set(i, phys_id_present_map);
-                       mp_ioapics[apic_id].apicid = i;
+                       ioapics[apic_id].mp_config.apicid = i;
                } else {
                        physid_mask_t tmp;
-                       apic->apicid_to_cpu_present(mp_ioapics[apic_id].apicid, &tmp);
+                       apic->apicid_to_cpu_present(mpc_ioapic_id(apic_id),
+                                                   &tmp);
                        apic_printk(APIC_VERBOSE, "Setting %d in the "
                                        "phys_id_present_map\n",
-                                       mp_ioapics[apic_id].apicid);
+                                       mpc_ioapic_id(apic_id));
                        physids_or(phys_id_present_map, phys_id_present_map, tmp);
                }
 
@@ -1990,24 +2016,24 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
                 * We need to adjust the IRQ routing table
                 * if the ID changed.
                 */
-               if (old_id != mp_ioapics[apic_id].apicid)
+               if (old_id != mpc_ioapic_id(apic_id))
                        for (i = 0; i < mp_irq_entries; i++)
                                if (mp_irqs[i].dstapic == old_id)
                                        mp_irqs[i].dstapic
-                                               = mp_ioapics[apic_id].apicid;
+                                               = mpc_ioapic_id(apic_id);
 
                /*
                 * Update the ID register according to the right value
                 * from the MPC table if they are different.
                 */
-               if (mp_ioapics[apic_id].apicid == reg_00.bits.ID)
+               if (mpc_ioapic_id(apic_id) == reg_00.bits.ID)
                        continue;
 
                apic_printk(APIC_VERBOSE, KERN_INFO
                        "...changing IO-APIC physical APIC ID to %d ...",
-                       mp_ioapics[apic_id].apicid);
+                       mpc_ioapic_id(apic_id));
 
-               reg_00.bits.ID = mp_ioapics[apic_id].apicid;
+               reg_00.bits.ID = mpc_ioapic_id(apic_id);
                raw_spin_lock_irqsave(&ioapic_lock, flags);
                io_apic_write(apic_id, 0, reg_00.raw);
                raw_spin_unlock_irqrestore(&ioapic_lock, flags);
@@ -2018,7 +2044,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
                raw_spin_lock_irqsave(&ioapic_lock, flags);
                reg_00.raw = io_apic_read(apic_id, 0);
                raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-               if (reg_00.bits.ID != mp_ioapics[apic_id].apicid)
+               if (reg_00.bits.ID != mpc_ioapic_id(apic_id))
                        printk("could not set ID!\n");
                else
                        apic_printk(APIC_VERBOSE, " ok.\n");
@@ -2404,7 +2430,7 @@ static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
 
        raw_spin_lock_irqsave(&ioapic_lock, flags);
        for_each_irq_pin(entry, cfg->irq_2_pin) {
-               if (mp_ioapics[entry->apic].apicver >= 0x20) {
+               if (mpc_ioapic_ver(entry->apic) >= 0x20) {
                        /*
                         * Intr-remapping uses pin number as the virtual vector
                         * in the RTE. Actual vector is programmed in
@@ -2918,49 +2944,19 @@ static int __init io_apic_bug_finalize(void)
 
 late_initcall(io_apic_bug_finalize);
 
-static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS];
-
-static void suspend_ioapic(int ioapic_id)
+static void resume_ioapic_id(int ioapic_id)
 {
-       struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id];
-       int i;
-
-       if (!saved_data)
-               return;
-
-       for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++)
-               saved_data[i] = ioapic_read_entry(ioapic_id, i);
-}
-
-static int ioapic_suspend(void)
-{
-       int ioapic_id;
-
-       for (ioapic_id = 0; ioapic_id < nr_ioapics; ioapic_id++)
-               suspend_ioapic(ioapic_id);
-
-       return 0;
-}
-
-static void resume_ioapic(int ioapic_id)
-{
-       struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id];
        unsigned long flags;
        union IO_APIC_reg_00 reg_00;
-       int i;
 
-       if (!saved_data)
-               return;
 
        raw_spin_lock_irqsave(&ioapic_lock, flags);
        reg_00.raw = io_apic_read(ioapic_id, 0);
-       if (reg_00.bits.ID != mp_ioapics[ioapic_id].apicid) {
-               reg_00.bits.ID = mp_ioapics[ioapic_id].apicid;
+       if (reg_00.bits.ID != mpc_ioapic_id(ioapic_id)) {
+               reg_00.bits.ID = mpc_ioapic_id(ioapic_id);
                io_apic_write(ioapic_id, 0, reg_00.raw);
        }
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-       for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++)
-               ioapic_write_entry(ioapic_id, i, saved_data[i]);
 }
 
 static void ioapic_resume(void)
@@ -2968,28 +2964,18 @@ static void ioapic_resume(void)
        int ioapic_id;
 
        for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--)
-               resume_ioapic(ioapic_id);
+               resume_ioapic_id(ioapic_id);
+
+       restore_ioapic_entries();
 }
 
 static struct syscore_ops ioapic_syscore_ops = {
-       .suspend = ioapic_suspend,
+       .suspend = save_ioapic_entries,
        .resume = ioapic_resume,
 };
 
 static int __init ioapic_init_ops(void)
 {
-       int i;
-
-       for (i = 0; i < nr_ioapics; i++) {
-               unsigned int size;
-
-               size = nr_ioapic_registers[i]
-                       * sizeof(struct IO_APIC_route_entry);
-               ioapic_saved_data[i] = kzalloc(size, GFP_KERNEL);
-               if (!ioapic_saved_data[i])
-                       pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
-       }
-
        register_syscore_ops(&ioapic_syscore_ops);
 
        return 0;
@@ -3592,14 +3578,14 @@ int io_apic_setup_irq_pin_once(unsigned int irq, int node,
        int ret;
 
        /* Avoid redundant programming */
-       if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) {
+       if (test_bit(pin, ioapics[id].pin_programmed)) {
                pr_debug("Pin %d-%d already programmed\n",
-                        mp_ioapics[id].apicid, pin);
+                        mpc_ioapic_id(id), pin);
                return 0;
        }
        ret = io_apic_setup_irq_pin(irq, node, attr);
        if (!ret)
-               set_bit(pin, mp_ioapic_routing[id].pin_programmed);
+               set_bit(pin, ioapics[id].pin_programmed);
        return ret;
 }
 
@@ -3764,8 +3750,7 @@ static u8 __init io_apic_unique_id(u8 id)
 
        bitmap_zero(used, 256);
        for (i = 0; i < nr_ioapics; i++) {
-               struct mpc_ioapic *ia = &mp_ioapics[i];
-               __set_bit(ia->apicid, used);
+               __set_bit(mpc_ioapic_id(i), used);
        }
        if (!test_bit(id, used))
                return id;
@@ -3825,7 +3810,7 @@ void __init setup_ioapic_dest(void)
                return;
 
        for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
-       for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+       for (pin = 0; pin < ioapics[ioapic].nr_registers; pin++) {
                irq_entry = find_irq_entry(ioapic, pin, mp_INT);
                if (irq_entry == -1)
                        continue;
@@ -3896,7 +3881,7 @@ void __init ioapic_and_gsi_init(void)
        ioapic_res = ioapic_setup_resources(nr_ioapics);
        for (i = 0; i < nr_ioapics; i++) {
                if (smp_found_config) {
-                       ioapic_phys = mp_ioapics[i].apicaddr;
+                       ioapic_phys = mpc_ioapic_addr(i);
 #ifdef CONFIG_X86_32
                        if (!ioapic_phys) {
                                printk(KERN_ERR
@@ -3956,8 +3941,9 @@ int mp_find_ioapic(u32 gsi)
 
        /* Find the IOAPIC that manages this GSI. */
        for (i = 0; i < nr_ioapics; i++) {
-               if ((gsi >= mp_gsi_routing[i].gsi_base)
-                   && (gsi <= mp_gsi_routing[i].gsi_end))
+               struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(i);
+               if ((gsi >= gsi_cfg->gsi_base)
+                   && (gsi <= gsi_cfg->gsi_end))
                        return i;
        }
 
@@ -3967,12 +3953,16 @@ int mp_find_ioapic(u32 gsi)
 
 int mp_find_ioapic_pin(int ioapic, u32 gsi)
 {
+       struct mp_ioapic_gsi *gsi_cfg;
+
        if (WARN_ON(ioapic == -1))
                return -1;
-       if (WARN_ON(gsi > mp_gsi_routing[ioapic].gsi_end))
+
+       gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+       if (WARN_ON(gsi > gsi_cfg->gsi_end))
                return -1;
 
-       return gsi - mp_gsi_routing[ioapic].gsi_base;
+       return gsi - gsi_cfg->gsi_base;
 }
 
 static __init int bad_ioapic(unsigned long address)
@@ -3994,40 +3984,42 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
 {
        int idx = 0;
        int entries;
+       struct mp_ioapic_gsi *gsi_cfg;
 
        if (bad_ioapic(address))
                return;
 
        idx = nr_ioapics;
 
-       mp_ioapics[idx].type = MP_IOAPIC;
-       mp_ioapics[idx].flags = MPC_APIC_USABLE;
-       mp_ioapics[idx].apicaddr = address;
+       ioapics[idx].mp_config.type = MP_IOAPIC;
+       ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
+       ioapics[idx].mp_config.apicaddr = address;
 
        set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
-       mp_ioapics[idx].apicid = io_apic_unique_id(id);
-       mp_ioapics[idx].apicver = io_apic_get_version(idx);
+       ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
+       ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
 
        /*
         * Build basic GSI lookup table to facilitate gsi->io_apic lookups
         * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
         */
        entries = io_apic_get_redir_entries(idx);
-       mp_gsi_routing[idx].gsi_base = gsi_base;
-       mp_gsi_routing[idx].gsi_end = gsi_base + entries - 1;
+       gsi_cfg = mp_ioapic_gsi_routing(idx);
+       gsi_cfg->gsi_base = gsi_base;
+       gsi_cfg->gsi_end = gsi_base + entries - 1;
 
        /*
         * The number of IO-APIC IRQ registers (== #pins):
         */
-       nr_ioapic_registers[idx] = entries;
+       ioapics[idx].nr_registers = entries;
 
-       if (mp_gsi_routing[idx].gsi_end >= gsi_top)
-               gsi_top = mp_gsi_routing[idx].gsi_end + 1;
+       if (gsi_cfg->gsi_end >= gsi_top)
+               gsi_top = gsi_cfg->gsi_end + 1;
 
        printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
-              "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
-              mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
-              mp_gsi_routing[idx].gsi_base, mp_gsi_routing[idx].gsi_end);
+              "GSI %d-%d\n", idx, mpc_ioapic_id(idx),
+              mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
+              gsi_cfg->gsi_base, gsi_cfg->gsi_end);
 
        nr_ioapics++;
 }