Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
[safe/jmp/linux-2.6] / arch / x86 / kernel / apic / apic.c
index fb504f8..c02cc69 100644 (file)
@@ -14,6 +14,7 @@
  *     Mikael Pettersson       :       PM converted to driver model.
  */
 
+#include <linux/perf_event.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi_pmtmr.h>
@@ -34,7 +35,8 @@
 #include <linux/smp.h>
 #include <linux/mm.h>
 
-#include <asm/perf_counter.h>
+#include <asm/perf_event.h>
+#include <asm/x86_init.h>
 #include <asm/pgalloc.h>
 #include <asm/atomic.h>
 #include <asm/mpspec.h>
@@ -48,6 +50,8 @@
 #include <asm/mtrr.h>
 #include <asm/smp.h>
 #include <asm/mce.h>
+#include <asm/kvm_para.h>
+#include <asm/tsc.h>
 
 unsigned int num_processors;
 
@@ -58,12 +62,6 @@ unsigned int boot_cpu_physical_apicid = -1U;
 
 /*
  * The highest APIC ID seen during enumeration.
- *
- * This determines the messaging protocol we can use: if all APIC IDs
- * are in the 0 ... 7 range, then we can use logical addressing which
- * has some performance advantages (better broadcasting).
- *
- * If there's an APIC ID above 8, we use physical addressing.
  */
 unsigned int max_physical_apicid;
 
@@ -99,6 +97,29 @@ early_param("lapic", parse_lapic);
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 static int enabled_via_apicbase;
 
+/*
+ * Handle interrupt mode configuration register (IMCR).
+ * This register controls whether the interrupt signals
+ * that reach the BSP come from the master PIC or from the
+ * local APIC. Before entering Symmetric I/O Mode, either
+ * the BIOS or the operating system must switch out of
+ * PIC Mode by changing the IMCR.
+ */
+static inline void imcr_pic_to_apic(void)
+{
+       /* select IMCR register */
+       outb(0x70, 0x22);
+       /* NMI and 8259 INTR go through APIC */
+       outb(0x01, 0x23);
+}
+
+static inline void imcr_apic_to_pic(void)
+{
+       /* select IMCR register */
+       outb(0x70, 0x22);
+       /* NMI and 8259 INTR go directly to BSP */
+       outb(0x00, 0x23);
+}
 #endif
 
 #ifdef CONFIG_X86_64
@@ -112,14 +133,18 @@ static __init int setup_apicpmtimer(char *s)
 __setup("apicpmtimer", setup_apicpmtimer);
 #endif
 
+int x2apic_mode;
 #ifdef CONFIG_X86_X2APIC
-int x2apic;
 /* x2apic enabled before OS handover */
 static int x2apic_preenabled;
-static int disable_x2apic;
 static __init int setup_nox2apic(char *str)
 {
-       disable_x2apic = 1;
+       if (x2apic_enabled()) {
+               pr_warning("Bios already enabled x2apic, "
+                          "can't enforce nox2apic");
+               return 0;
+       }
+
        setup_clear_cpu_cap(X86_FEATURE_X2APIC);
        return 0;
 }
@@ -210,6 +235,16 @@ static int modern_apic(void)
        return lapic_get_version() >= 0x14;
 }
 
+/*
+ * right after this call apic become NOOP driven
+ * so apic->write/read doesn't do anything
+ */
+void apic_disable(void)
+{
+       pr_info("APIC: switched to apic NOOP\n");
+       apic = &apic_noop;
+}
+
 void native_apic_wait_icr_idle(void)
 {
        while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
@@ -349,7 +384,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 
 static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
 {
-       unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
+       unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
        unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
 
        apic_write(reg, v);
@@ -404,7 +439,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
                v = apic_read(APIC_LVTT);
                v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
                apic_write(APIC_LVTT, v);
-               apic_write(APIC_TMICT, 0xffffffff);
+               apic_write(APIC_TMICT, 0);
                break;
        case CLOCK_EVT_MODE_RESUME:
                /* Nothing to do here */
@@ -432,6 +467,12 @@ static void __cpuinit setup_APIC_timer(void)
 {
        struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 
+       if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)) {
+               lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP;
+               /* Make LAPIC timer preferrable over percpu HPET */
+               lapic_clockevent.rating = 150;
+       }
+
        memcpy(levt, &lapic_clockevent, sizeof(*levt));
        levt->cpumask = cpumask_of(smp_processor_id());
 
@@ -541,7 +582,7 @@ calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc)
                res = (((u64)(*deltatsc)) * pm_100ms);
                do_div(res, deltapm);
                apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
-                                         "PM-Timer: %lu (%ld) \n",
+                                         "PM-Timer: %lu (%ld)\n",
                                        (unsigned long)res, *deltatsc);
                *deltatsc = (long)res;
        }
@@ -601,7 +642,7 @@ static int __init calibrate_APIC_clock(void)
        calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
 
        apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
-       apic_printk(APIC_VERBOSE, "..... mult: %ld\n", lapic_clockevent.mult);
+       apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
        apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
                    calibration_result);
 
@@ -756,8 +797,6 @@ static void local_apic_timer_interrupt(void)
        inc_irq_stat(apic_timer_irqs);
 
        evt->event_handler(evt);
-
-       perf_counter_unthrottle();
 }
 
 /*
@@ -812,7 +851,7 @@ void clear_local_APIC(void)
        u32 v;
 
        /* APIC hasn't been mapped yet */
-       if (!x2apic && !apic_phys)
+       if (!x2apic_mode && !apic_phys)
                return;
 
        maxlvt = lapic_get_maxlvt();
@@ -840,7 +879,7 @@ void clear_local_APIC(void)
        }
 
        /* lets not touch this if we didn't frob it */
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
+#ifdef CONFIG_X86_THERMAL_VECTOR
        if (maxlvt >= 5) {
                v = apic_read(APIC_LVTTHMR);
                apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
@@ -920,7 +959,7 @@ void lapic_shutdown(void)
 {
        unsigned long flags;
 
-       if (!cpu_has_apic)
+       if (!cpu_has_apic && !apic_from_smp_config())
                return;
 
        local_irq_save(flags);
@@ -1113,8 +1152,13 @@ static void __cpuinit lapic_setup_esr(void)
  */
 void __cpuinit setup_local_APIC(void)
 {
-       unsigned int value;
-       int i, j;
+       unsigned int value, queued;
+       int i, j, acked = 0;
+       unsigned long long tsc = 0, ntsc;
+       long long max_loops = cpu_khz;
+
+       if (cpu_has_tsc)
+               rdtscll(tsc);
 
        if (disable_apic) {
                arch_disable_smp_support();
@@ -1130,7 +1174,7 @@ void __cpuinit setup_local_APIC(void)
                apic_write(APIC_ESR, 0);
        }
 #endif
-       perf_counters_lapic_init(0);
+       perf_events_lapic_init();
 
        preempt_disable();
 
@@ -1138,8 +1182,7 @@ void __cpuinit setup_local_APIC(void)
         * Double-check whether this APIC is really registered.
         * This is meaningless in clustered apic mode, so we skip it.
         */
-       if (!apic->apic_id_registered())
-               BUG();
+       BUG_ON(!apic->apic_id_registered());
 
        /*
         * Intel recommends to set DFR, LDR and TPR before enabling
@@ -1167,13 +1210,32 @@ void __cpuinit setup_local_APIC(void)
         * the interrupt. Hence a vector might get locked. It was noticed
         * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
         */
-       for (i = APIC_ISR_NR - 1; i >= 0; i--) {
-               value = apic_read(APIC_ISR + i*0x10);
-               for (j = 31; j >= 0; j--) {
-                       if (value & (1<<j))
-                               ack_APIC_irq();
+       do {
+               queued = 0;
+               for (i = APIC_ISR_NR - 1; i >= 0; i--)
+                       queued |= apic_read(APIC_IRR + i*0x10);
+
+               for (i = APIC_ISR_NR - 1; i >= 0; i--) {
+                       value = apic_read(APIC_ISR + i*0x10);
+                       for (j = 31; j >= 0; j--) {
+                               if (value & (1<<j)) {
+                                       ack_APIC_irq();
+                                       acked++;
+                               }
+                       }
                }
-       }
+               if (acked > 256) {
+                       printk(KERN_ERR "LAPIC pending interrupts after %d EOI\n",
+                              acked);
+                       break;
+               }
+               if (cpu_has_tsc) {
+                       rdtscll(ntsc);
+                       max_loops = (cpu_khz << 10) - (ntsc - tsc);
+               } else
+                       max_loops--;
+       } while (queued && max_loops > 0);
+       WARN_ON(max_loops <= 0);
 
        /*
         * Now that we are all set up, enable the APIC
@@ -1285,7 +1347,7 @@ void check_x2apic(void)
 {
        if (x2apic_enabled()) {
                pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
-               x2apic_preenabled = x2apic = 1;
+               x2apic_preenabled = x2apic_mode = 1;
        }
 }
 
@@ -1293,120 +1355,113 @@ void enable_x2apic(void)
 {
        int msr, msr2;
 
-       if (!x2apic)
+       if (!x2apic_mode)
                return;
 
        rdmsr(MSR_IA32_APICBASE, msr, msr2);
        if (!(msr & X2APIC_ENABLE)) {
-               pr_info("Enabling x2apic\n");
+               printk_once(KERN_INFO "Enabling x2apic\n");
                wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
        }
 }
+#endif /* CONFIG_X86_X2APIC */
 
-void __init enable_IR_x2apic(void)
+int __init enable_IR(void)
 {
 #ifdef CONFIG_INTR_REMAP
-       int ret;
-       unsigned long flags;
-       struct IO_APIC_route_entry **ioapic_entries = NULL;
-
-       if (!cpu_has_x2apic)
-               return;
-
-       if (!x2apic_preenabled && disable_x2apic) {
-               pr_info("Skipped enabling x2apic and Interrupt-remapping "
-                       "because of nox2apic\n");
-               return;
+       if (!intr_remapping_supported()) {
+               pr_debug("intr-remapping not supported\n");
+               return 0;
        }
 
-       if (x2apic_preenabled && disable_x2apic)
-               panic("Bios already enabled x2apic, can't enforce nox2apic");
-
        if (!x2apic_preenabled && skip_ioapic_setup) {
-               pr_info("Skipped enabling x2apic and Interrupt-remapping "
-                       "because of skipping io-apic setup\n");
-               return;
+               pr_info("Skipped enabling intr-remap because of skipping "
+                       "io-apic setup\n");
+               return 0;
        }
 
-       ret = dmar_table_init();
-       if (ret) {
-               pr_info("dmar_table_init() failed with %d:\n", ret);
+       if (enable_intr_remapping(x2apic_supported()))
+               return 0;
 
-               if (x2apic_preenabled)
-                       panic("x2apic enabled by bios. But IR enabling failed");
-               else
-                       pr_info("Not enabling x2apic,Intr-remapping\n");
+       pr_info("Enabled Interrupt-remapping\n");
+
+       return 1;
+
+#endif
+       return 0;
+}
+
+void __init enable_IR_x2apic(void)
+{
+       unsigned long flags;
+       struct IO_APIC_route_entry **ioapic_entries = NULL;
+       int ret, x2apic_enabled = 0;
+       int dmar_table_init_ret;
+
+       dmar_table_init_ret = dmar_table_init();
+       if (dmar_table_init_ret && !x2apic_supported())
                return;
-       }
 
        ioapic_entries = alloc_ioapic_entries();
        if (!ioapic_entries) {
-               pr_info("Allocate ioapic_entries failed: %d\n", ret);
-               goto end;
+               pr_err("Allocate ioapic_entries failed\n");
+               goto out;
        }
 
        ret = save_IO_APIC_setup(ioapic_entries);
        if (ret) {
                pr_info("Saving IO-APIC state failed: %d\n", ret);
-               goto end;
+               goto out;
        }
 
        local_irq_save(flags);
+       legacy_pic->mask_all();
        mask_IO_APIC_setup(ioapic_entries);
-       mask_8259A();
 
-       ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
+       if (dmar_table_init_ret)
+               ret = 0;
+       else
+               ret = enable_IR();
 
-       if (ret && x2apic_preenabled) {
-               local_irq_restore(flags);
-               panic("x2apic enabled by bios. But IR enabling failed");
+       if (!ret) {
+               /* IR is required if there is APIC ID > 255 even when running
+                * under KVM
+                */
+               if (max_physical_apicid > 255 || !kvm_para_available())
+                       goto nox2apic;
+               /*
+                * without IR all CPUs can be addressed by IOAPIC/MSI
+                * only in physical mode
+                */
+               x2apic_force_phys();
        }
 
-       if (ret)
-               goto end_restore;
+       x2apic_enabled = 1;
 
-       if (!x2apic) {
-               x2apic = 1;
+       if (x2apic_supported() && !x2apic_mode) {
+               x2apic_mode = 1;
                enable_x2apic();
+               pr_info("Enabled x2apic\n");
        }
 
-end_restore:
-       if (ret)
-               /*
-                * IR enabling failed
-                */
+nox2apic:
+       if (!ret) /* IR enabling failed */
                restore_IO_APIC_setup(ioapic_entries);
-       else
-               reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);
-
-       unmask_8259A();
+       legacy_pic->restore_mask();
        local_irq_restore(flags);
 
-end:
-       if (!ret) {
-               if (!x2apic_preenabled)
-                       pr_info("Enabled x2apic and interrupt-remapping\n");
-               else
-                       pr_info("Enabled Interrupt-remapping\n");
-       } else
-               pr_err("Failed to enable Interrupt-remapping and x2apic\n");
+out:
        if (ioapic_entries)
                free_ioapic_entries(ioapic_entries);
-#else
-       if (!cpu_has_x2apic)
+
+       if (x2apic_enabled)
                return;
 
        if (x2apic_preenabled)
-               panic("x2apic enabled prior OS handover,"
-                     " enable CONFIG_INTR_REMAP");
-
-       pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping "
-               " and x2apic\n");
-#endif
-
-       return;
+               panic("x2apic: enabled by BIOS but kernel init failed.");
+       else if (cpu_has_x2apic)
+               pr_info("Not enabling x2apic, Intr-remapping init failed.\n");
 }
-#endif /* CONFIG_X86_X2APIC */
 
 #ifdef CONFIG_X86_64
 /*
@@ -1423,7 +1478,6 @@ static int __init detect_init_APIC(void)
        }
 
        mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-       boot_cpu_physical_apicid = 0;
        return 0;
 }
 #else
@@ -1509,8 +1563,6 @@ no_apic:
 #ifdef CONFIG_X86_64
 void __init early_init_lapic_mapping(void)
 {
-       unsigned long phys_addr;
-
        /*
         * If no local APIC can be found then go out
         * : it means there is no mpatable and MADT
@@ -1518,11 +1570,9 @@ void __init early_init_lapic_mapping(void)
        if (!smp_found_config)
                return;
 
-       phys_addr = mp_lapic_addr;
-
-       set_fixmap_nocache(FIX_APIC_BASE, phys_addr);
+       set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
        apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
-                   APIC_BASE, phys_addr);
+                   APIC_BASE, mp_lapic_addr);
 
        /*
         * Fetch the APIC ID of the BSP in case we have a
@@ -1537,32 +1587,49 @@ void __init early_init_lapic_mapping(void)
  */
 void __init init_apic_mappings(void)
 {
-       if (x2apic) {
+       unsigned int new_apicid;
+
+       if (x2apic_mode) {
                boot_cpu_physical_apicid = read_apic_id();
                return;
        }
 
-       /*
-        * If no local APIC can be found then set up a fake all
-        * zeroes page to simulate the local APIC and another
-        * one for the IO-APIC.
-        */
+       /* If no local APIC can be found return early */
        if (!smp_found_config && detect_init_APIC()) {
-               apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-               apic_phys = __pa(apic_phys);
-       } else
+               /* lets NOP'ify apic operations */
+               pr_info("APIC: disable apic facility\n");
+               apic_disable();
+       } else {
                apic_phys = mp_lapic_addr;
 
-       set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-       apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
-                               APIC_BASE, apic_phys);
+               /*
+                * acpi lapic path already maps that address in
+                * acpi_register_lapic_address()
+                */
+               if (!acpi_lapic)
+                       set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+
+               apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
+                                       APIC_BASE, apic_phys);
+       }
 
        /*
         * Fetch the APIC ID of the BSP in case we have a
         * default configuration (or the MP table is broken).
         */
-       if (boot_cpu_physical_apicid == -1U)
-               boot_cpu_physical_apicid = read_apic_id();
+       new_apicid = read_apic_id();
+       if (boot_cpu_physical_apicid != new_apicid) {
+               boot_cpu_physical_apicid = new_apicid;
+               /*
+                * yeah -- we lie about apic_version
+                * in case if apic was disabled via boot option
+                * but it's not a problem for SMP compiled kernel
+                * since smp_sanity_check is prepared for such a case
+                * and disable smp mode
+                */
+               apic_version[new_apicid] =
+                        GET_APIC_VERSION(apic_read(APIC_LVR));
+       }
 }
 
 /*
@@ -1594,13 +1661,12 @@ int __init APIC_init_uniprocessor(void)
            APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
                pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
                        boot_cpu_physical_apicid);
-               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
                return -1;
        }
 #endif
 
+#ifndef CONFIG_SMP
        enable_IR_x2apic();
-#ifdef CONFIG_X86_64
        default_setup_apic_routing();
 #endif
 
@@ -1644,7 +1710,7 @@ int __init APIC_init_uniprocessor(void)
        localise_nmi_watchdog();
 #endif
 
-       setup_boot_clock();
+       x86_init.timers.setup_percpu_clockev();
 #ifdef CONFIG_X86_64
        check_nmi_watchdog();
 #endif
@@ -1731,8 +1797,7 @@ void __init connect_bsp_APIC(void)
                 */
                apic_printk(APIC_VERBOSE, "leaving PIC mode, "
                                "enabling APIC mode.\n");
-               outb(0x70, 0x22);
-               outb(0x01, 0x23);
+               imcr_pic_to_apic();
        }
 #endif
        if (apic->enable_apic_mode)
@@ -1760,8 +1825,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
                 */
                apic_printk(APIC_VERBOSE, "disabling APIC mode, "
                                "entering PIC mode.\n");
-               outb(0x70, 0x22);
-               outb(0x00, 0x23);
+               imcr_apic_to_pic();
                return;
        }
 #endif
@@ -1852,28 +1916,6 @@ void __cpuinit generic_processor_info(int apicid, int version)
        if (apicid > max_physical_apicid)
                max_physical_apicid = apicid;
 
-#ifdef CONFIG_X86_32
-       /*
-        * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
-        * but we need to work other dependencies like SMP_SUSPEND etc
-        * before this can be done without some confusion.
-        * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
-        *       - Ashok Raj <ashok.raj@intel.com>
-        */
-       if (max_physical_apicid >= 8) {
-               switch (boot_cpu_data.x86_vendor) {
-               case X86_VENDOR_INTEL:
-                       if (!APIC_XAPIC(version)) {
-                               def_to_bigsmp = 0;
-                               break;
-                       }
-                       /* If P4 and above fall through */
-               case X86_VENDOR_AMD:
-                       def_to_bigsmp = 1;
-               }
-       }
-#endif
-
 #if defined(CONFIG_SMP) || defined(CONFIG_X86_64)
        early_per_cpu(x86_cpu_to_apicid, cpu) = apicid;
        early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
@@ -1960,17 +2002,17 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
        apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
        apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
        apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
+#ifdef CONFIG_X86_THERMAL_VECTOR
        if (maxlvt >= 5)
                apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
 #endif
 
        local_irq_save(flags);
        disable_local_APIC();
-#ifdef CONFIG_INTR_REMAP
+
        if (intr_remapping_enabled)
                disable_intr_remapping();
-#endif
+
        local_irq_restore(flags);
        return 0;
 }
@@ -1980,42 +2022,34 @@ static int lapic_resume(struct sys_device *dev)
        unsigned int l, h;
        unsigned long flags;
        int maxlvt;
-
-#ifdef CONFIG_INTR_REMAP
-       int ret;
+       int ret = 0;
        struct IO_APIC_route_entry **ioapic_entries = NULL;
 
        if (!apic_pm_state.active)
                return 0;
 
        local_irq_save(flags);
-       if (x2apic) {
+       if (intr_remapping_enabled) {
                ioapic_entries = alloc_ioapic_entries();
                if (!ioapic_entries) {
                        WARN(1, "Alloc ioapic_entries in lapic resume failed.");
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto restore;
                }
 
                ret = save_IO_APIC_setup(ioapic_entries);
                if (ret) {
                        WARN(1, "Saving IO-APIC state failed: %d\n", ret);
                        free_ioapic_entries(ioapic_entries);
-                       return ret;
+                       goto restore;
                }
 
                mask_IO_APIC_setup(ioapic_entries);
-               mask_8259A();
-               enable_x2apic();
+               legacy_pic->mask_all();
        }
-#else
-       if (!apic_pm_state.active)
-               return 0;
 
-       local_irq_save(flags);
-       if (x2apic)
+       if (x2apic_mode)
                enable_x2apic();
-#endif
-
        else {
                /*
                 * Make sure the APICBASE points to the right address
@@ -2053,21 +2087,16 @@ static int lapic_resume(struct sys_device *dev)
        apic_write(APIC_ESR, 0);
        apic_read(APIC_ESR);
 
-#ifdef CONFIG_INTR_REMAP
-       if (intr_remapping_enabled)
-               reenable_intr_remapping(EIM_32BIT_APIC_ID);
-
-       if (x2apic) {
-               unmask_8259A();
+       if (intr_remapping_enabled) {
+               reenable_intr_remapping(x2apic_mode);
+               legacy_pic->restore_mask();
                restore_IO_APIC_setup(ioapic_entries);
                free_ioapic_entries(ioapic_entries);
        }
-#endif
-
+restore:
        local_irq_restore(flags);
 
-
-       return 0;
+       return ret;
 }
 
 /*
@@ -2115,31 +2144,14 @@ static void apic_pm_activate(void) { }
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_X86_64
-/*
- * apic_is_clustered_box() -- Check if we can expect good TSC
- *
- * Thus far, the major user of this is IBM's Summit2 series:
- *
- * Clustered boxes may have unsynced TSC problems if they are
- * multi-chassis. Use available data to take a good guess.
- * If in doubt, go HPET.
- */
-__cpuinit int apic_is_clustered_box(void)
+
+static int __cpuinit apic_cluster_num(void)
 {
        int i, clusters, zeros;
        unsigned id;
        u16 *bios_cpu_apicid;
        DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
 
-       /*
-        * there is not this kind of box with AMD CPU yet.
-        * Some AMD box with quadcore cpu and 8 sockets apicid
-        * will be [4, 0x23] or [8, 0x27] could be thought to
-        * vsmp box still need checking...
-        */
-       if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
-               return 0;
-
        bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
        bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
 
@@ -2175,18 +2187,67 @@ __cpuinit int apic_is_clustered_box(void)
                        ++zeros;
        }
 
-       /* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
-        * not guaranteed to be synced between boards
-        */
-       if (is_vsmp_box() && clusters > 1)
+       return clusters;
+}
+
+static int __cpuinitdata multi_checked;
+static int __cpuinitdata multi;
+
+static int __cpuinit set_multi(const struct dmi_system_id *d)
+{
+       if (multi)
+               return 0;
+       pr_info("APIC: %s detected, Multi Chassis\n", d->ident);
+       multi = 1;
+       return 0;
+}
+
+static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = {
+       {
+               .callback = set_multi,
+               .ident = "IBM System Summit2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"),
+               },
+       },
+       {}
+};
+
+static void __cpuinit dmi_check_multi(void)
+{
+       if (multi_checked)
+               return;
+
+       dmi_check_system(multi_dmi_table);
+       multi_checked = 1;
+}
+
+/*
+ * apic_is_clustered_box() -- Check if we can expect good TSC
+ *
+ * Thus far, the major user of this is IBM's Summit2 series:
+ * Clustered boxes may have unsynced TSC problems if they are
+ * multi-chassis.
+ * Use DMI to check them
+ */
+__cpuinit int apic_is_clustered_box(void)
+{
+       dmi_check_multi();
+       if (multi)
                return 1;
 
+       if (!is_vsmp_box())
+               return 0;
+
        /*
-        * If clusters > 2, then should be multi-chassis.
-        * May have to revisit this when multi-core + hyperthreaded CPUs come
-        * out, but AFAIK this will work even for them.
+        * ScaleMP vSMPowered boxes have one cluster per board and TSCs are
+        * not guaranteed to be synced between boards
         */
-       return (clusters > 2);
+       if (apic_cluster_num() > 1)
+               return 1;
+
+       return 0;
 }
 #endif