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 71c4443..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.
- *
- * 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;
 
@@ -1157,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();
@@ -1210,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
@@ -1396,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)
@@ -1428,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:
@@ -1646,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
 
@@ -1897,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;
@@ -2048,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)
@@ -2092,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);
        }