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 61a5628..c02cc69 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/smp.h>
 #include <asm/mce.h>
 #include <asm/kvm_para.h>
+#include <asm/tsc.h>
 
 unsigned int num_processors;
 
@@ -61,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;
 
@@ -246,6 +241,7 @@ static int modern_apic(void)
  */
 void apic_disable(void)
 {
+       pr_info("APIC: switched to apic NOOP\n");
        apic = &apic_noop;
 }
 
@@ -443,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 */
@@ -586,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;
        }
@@ -646,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);
 
@@ -1156,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();
@@ -1209,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
@@ -1340,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);
        }
 }
@@ -1376,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) {
@@ -1398,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)
@@ -1430,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:
@@ -1648,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
 
@@ -1899,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;
@@ -2040,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)
@@ -2084,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);
        }