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 072aea6..c02cc69 100644 (file)
@@ -14,7 +14,7 @@
  *     Mikael Pettersson       :       PM converted to driver model.
  */
 
-#include <linux/perf_counter.h>
+#include <linux/perf_event.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi_pmtmr.h>
@@ -35,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>
@@ -50,6 +51,7 @@
 #include <asm/smp.h>
 #include <asm/mce.h>
 #include <asm/kvm_para.h>
+#include <asm/tsc.h>
 
 unsigned int num_processors;
 
@@ -60,12 +62,6 @@ unsigned int boot_cpu_physical_apicid = -1U;
 
 /*
  * The highest APIC ID seen during enumeration.
- *
- * On AMD, 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;
 
@@ -240,28 +236,13 @@ static int modern_apic(void)
 }
 
 /*
- * bare function to substitute write operation
- * and it's _that_ fast :)
- */
-static void native_apic_write_dummy(u32 reg, u32 v)
-{
-       WARN_ON_ONCE((cpu_has_apic || !disable_apic));
-}
-
-static u32 native_apic_read_dummy(u32 reg)
-{
-       WARN_ON_ONCE((cpu_has_apic && !disable_apic));
-       return 0;
-}
-
-/*
- * right after this call apic->write/read doesn't do anything
- * note that there is no restore operation it works one way
+ * right after this call apic become NOOP driven
+ * so apic->write/read doesn't do anything
  */
 void apic_disable(void)
 {
-       apic->read = native_apic_read_dummy;
-       apic->write = native_apic_write_dummy;
+       pr_info("APIC: switched to apic NOOP\n");
+       apic = &apic_noop;
 }
 
 void native_apic_wait_icr_idle(void)
@@ -458,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 */
@@ -601,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;
        }
@@ -661,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);
 
@@ -978,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);
@@ -1171,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();
@@ -1188,7 +1174,7 @@ void __cpuinit setup_local_APIC(void)
                apic_write(APIC_ESR, 0);
        }
 #endif
-       perf_counters_lapic_init();
+       perf_events_lapic_init();
 
        preempt_disable();
 
@@ -1224,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
@@ -1355,7 +1360,7 @@ void enable_x2apic(void)
 
        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);
        }
 }
@@ -1391,14 +1396,11 @@ 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 = 0;
+       int dmar_table_init_ret;
 
-#ifdef CONFIG_INTR_REMAP
        dmar_table_init_ret = dmar_table_init();
-       if (dmar_table_init_ret)
-               pr_debug("dmar_table_init() failed with %d:\n",
-                               dmar_table_init_ret);
-#endif
+       if (dmar_table_init_ret && !x2apic_supported())
+               return;
 
        ioapic_entries = alloc_ioapic_entries();
        if (!ioapic_entries) {
@@ -1413,7 +1415,7 @@ void __init enable_IR_x2apic(void)
        }
 
        local_irq_save(flags);
-       mask_8259A();
+       legacy_pic->mask_all();
        mask_IO_APIC_setup(ioapic_entries);
 
        if (dmar_table_init_ret)
@@ -1445,7 +1447,7 @@ void __init enable_IR_x2apic(void)
 nox2apic:
        if (!ret) /* IR enabling failed */
                restore_IO_APIC_setup(ioapic_entries);
-       unmask_8259A();
+       legacy_pic->restore_mask();
        local_irq_restore(flags);
 
 out:
@@ -1663,8 +1665,8 @@ int __init APIC_init_uniprocessor(void)
        }
 #endif
 
+#ifndef CONFIG_SMP
        enable_IR_x2apic();
-#ifdef CONFIG_X86_64
        default_setup_apic_routing();
 #endif
 
@@ -1708,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
@@ -1914,18 +1916,6 @@ void __cpuinit generic_processor_info(int apicid, int version)
        if (apicid > max_physical_apicid)
                max_physical_apicid = apicid;
 
-#ifdef CONFIG_X86_32
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_INTEL:
-               if (num_processors > 8)
-                       def_to_bigsmp = 1;
-               break;
-       case X86_VENDOR_AMD:
-               if (max_physical_apicid >= 8)
-                       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;
@@ -2055,7 +2045,7 @@ static int lapic_resume(struct sys_device *dev)
                }
 
                mask_IO_APIC_setup(ioapic_entries);
-               mask_8259A();
+               legacy_pic->mask_all();
        }
 
        if (x2apic_mode)
@@ -2099,7 +2089,7 @@ static int lapic_resume(struct sys_device *dev)
 
        if (intr_remapping_enabled) {
                reenable_intr_remapping(x2apic_mode);
-               unmask_8259A();
+               legacy_pic->restore_mask();
                restore_IO_APIC_setup(ioapic_entries);
                free_ioapic_entries(ioapic_entries);
        }