Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / x86 / kernel / apic / apic.c
index 966673f..f92a8e5 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/ftrace.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/delay.h>
 #include <linux/timex.h>
 #include <linux/dmar.h>
@@ -505,7 +505,7 @@ static void __cpuinit setup_APIC_timer(void)
 {
        struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 
-       if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_ARAT)) {
+       if (this_cpu_has(X86_FEATURE_ARAT)) {
                lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP;
                /* Make LAPIC timer preferrable over percpu HPET */
                lapic_clockevent.rating = 150;
@@ -1237,6 +1237,17 @@ void __cpuinit setup_local_APIC(void)
        /* always use the value from LDR */
        early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
                logical_smp_processor_id();
+
+       /*
+        * Some NUMA implementations (NUMAQ) don't initialize apicid to
+        * node mapping during NUMA init.  Now that logical apicid is
+        * guaranteed to be known, give it another chance.  This is already
+        * a bit too late - percpu allocation has already happened without
+        * proper NUMA affinity.
+        */
+       if (apic->x86_32_numa_cpu_node)
+               set_apicid_to_node(early_per_cpu(x86_cpu_to_apicid, cpu),
+                                  apic->x86_32_numa_cpu_node(cpu));
 #endif
 
        /*
@@ -1812,30 +1823,41 @@ void smp_spurious_interrupt(struct pt_regs *regs)
  */
 void smp_error_interrupt(struct pt_regs *regs)
 {
-       u32 v, v1;
+       u32 v0, v1;
+       u32 i = 0;
+       static const char * const error_interrupt_reason[] = {
+               "Send CS error",                /* APIC Error Bit 0 */
+               "Receive CS error",             /* APIC Error Bit 1 */
+               "Send accept error",            /* APIC Error Bit 2 */
+               "Receive accept error",         /* APIC Error Bit 3 */
+               "Redirectable IPI",             /* APIC Error Bit 4 */
+               "Send illegal vector",          /* APIC Error Bit 5 */
+               "Received illegal vector",      /* APIC Error Bit 6 */
+               "Illegal register address",     /* APIC Error Bit 7 */
+       };
 
        exit_idle();
        irq_enter();
        /* First tickle the hardware, only then report what went on. -- REW */
-       v = apic_read(APIC_ESR);
+       v0 = apic_read(APIC_ESR);
        apic_write(APIC_ESR, 0);
        v1 = apic_read(APIC_ESR);
        ack_APIC_irq();
        atomic_inc(&irq_err_count);
 
-       /*
-        * Here is what the APIC error bits mean:
-        * 0: Send CS error
-        * 1: Receive CS error
-        * 2: Send accept error
-        * 3: Receive accept error
-        * 4: Reserved
-        * 5: Send illegal vector
-        * 6: Received illegal vector
-        * 7: Illegal register address
-        */
-       pr_debug("APIC error on CPU%d: %02x(%02x)\n",
-               smp_processor_id(), v , v1);
+       apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)",
+                   smp_processor_id(), v0 , v1);
+
+       v1 = v1 & 0xff;
+       while (v1) {
+               if (v1 & 0x1)
+                       apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
+               i++;
+               v1 >>= 1;
+       };
+
+       apic_printk(APIC_DEBUG, KERN_CONT "\n");
+
        irq_exit();
 }
 
@@ -2003,21 +2025,6 @@ void default_init_apic_ldr(void)
        apic_write(APIC_LDR, val);
 }
 
-#ifdef CONFIG_X86_32
-int default_x86_32_numa_cpu_node(int cpu)
-{
-#ifdef CONFIG_NUMA
-       int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
-
-       if (apicid != BAD_APICID)
-               return __apicid_to_node[apicid];
-       return NUMA_NO_NODE;
-#else
-       return 0;
-#endif
-}
-#endif
-
 /*
  * Power management
  */
@@ -2046,7 +2053,7 @@ static struct {
        unsigned int apic_thmr;
 } apic_pm_state;
 
-static int lapic_suspend(struct sys_device *dev, pm_message_t state)
+static int lapic_suspend(void)
 {
        unsigned long flags;
        int maxlvt;
@@ -2084,23 +2091,21 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
        return 0;
 }
 
-static int lapic_resume(struct sys_device *dev)
+static void lapic_resume(void)
 {
        unsigned int l, h;
        unsigned long flags;
-       int maxlvt;
-       int ret = 0;
+       int maxlvt, ret;
        struct IO_APIC_route_entry **ioapic_entries = NULL;
 
        if (!apic_pm_state.active)
-               return 0;
+               return;
 
        local_irq_save(flags);
        if (intr_remapping_enabled) {
                ioapic_entries = alloc_ioapic_entries();
                if (!ioapic_entries) {
                        WARN(1, "Alloc ioapic_entries in lapic resume failed.");
-                       ret = -ENOMEM;
                        goto restore;
                }
 
@@ -2162,8 +2167,6 @@ static int lapic_resume(struct sys_device *dev)
        }
 restore:
        local_irq_restore(flags);
-
-       return ret;
 }
 
 /*
@@ -2171,17 +2174,11 @@ restore:
  * are needed on every CPU up until machine_halt/restart/poweroff.
  */
 
-static struct sysdev_class lapic_sysclass = {
-       .name           = "lapic",
+static struct syscore_ops lapic_syscore_ops = {
        .resume         = lapic_resume,
        .suspend        = lapic_suspend,
 };
 
-static struct sys_device device_lapic = {
-       .id     = 0,
-       .cls    = &lapic_sysclass,
-};
-
 static void __cpuinit apic_pm_activate(void)
 {
        apic_pm_state.active = 1;
@@ -2189,16 +2186,11 @@ static void __cpuinit apic_pm_activate(void)
 
 static int __init init_lapic_sysfs(void)
 {
-       int error;
-
-       if (!cpu_has_apic)
-               return 0;
        /* XXX: remove suspend/resume procs if !apic_pm_state.active? */
+       if (cpu_has_apic)
+               register_syscore_ops(&lapic_syscore_ops);
 
-       error = sysdev_class_register(&lapic_sysclass);
-       if (!error)
-               error = sysdev_register(&device_lapic);
-       return error;
+       return 0;
 }
 
 /* local apic needs to resume before other devices access its registers. */