linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / x86_64 / kernel / apic.c
index 36e2e4b..e5b14c5 100644 (file)
@@ -14,6 +14,7 @@
  *     Mikael Pettersson       :       PM converted to driver model.
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 
 #include <linux/mm.h>
@@ -50,7 +51,7 @@ int disable_apic_timer __initdata;
 static cpumask_t timer_interrupt_broadcast_ipi_mask;
 
 /* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer __read_mostly = 0;
+int using_apic_timer = 0;
 
 static void apic_pm_activate(void);
 
@@ -99,7 +100,7 @@ void clear_local_APIC(void)
        maxlvt = get_maxlvt();
 
        /*
-        * Masking an LVT entry can trigger a local APIC error
+        * Masking an LVT entry on a P6 can trigger a local APIC error
         * if the vector is zero. Mask LVTERR first to prevent this.
         */
        if (maxlvt >= 3) {
@@ -341,7 +342,6 @@ void __init init_bsp_APIC(void)
 void __cpuinit setup_local_APIC (void)
 {
        unsigned int value, maxlvt;
-       int i, j;
 
        value = apic_read(APIC_LVR);
 
@@ -370,25 +370,6 @@ void __cpuinit setup_local_APIC (void)
        value &= ~APIC_TPRI_MASK;
        apic_write(APIC_TASKPRI, value);
 
-       /*
-        * After a crash, we no longer service the interrupts and a pending
-        * interrupt from previous kernel might still have ISR bit set.
-        *
-        * Most probably by now CPU has serviced that pending interrupt and
-        * it might not have done the ack_APIC_irq() because it thought,
-        * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
-        * does not clear the ISR bit and cpu thinks it has already serivced
-        * 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();
-               }
-       }
-
        /*
         * Now that we are all set up, enable the APIC
         */
@@ -614,7 +595,7 @@ static int __init apic_set_verbosity(char *str)
                printk(KERN_WARNING "APIC Verbosity level %s not recognised"
                                " use apic=verbose or apic=debug", str);
 
-       return 1;
+       return 0;
 }
 
 __setup("apic=", apic_set_verbosity);
@@ -850,18 +831,7 @@ void disable_APIC_timer(void)
                unsigned long v;
 
                v = apic_read(APIC_LVTT);
-               /*
-                * When an illegal vector value (0-15) is written to an LVT
-                * entry and delivery mode is Fixed, the APIC may signal an
-                * illegal vector error, with out regard to whether the mask
-                * bit is set or whether an interrupt is actually seen on input.
-                *
-                * Boot sequence might call this function when the LVTT has
-                * '0' vector value. So make sure vector field is set to
-                * valid value.
-                */
-               v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
-               apic_write(APIC_LVTT, v);
+               apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
        }
 }
 
@@ -919,13 +889,15 @@ int setup_profiling_timer(unsigned int multiplier)
        return -EINVAL;
 }
 
-void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
-                           unsigned char msg_type, unsigned char mask)
+#ifdef CONFIG_X86_MCE_AMD
+void setup_threshold_lvt(unsigned long lvt_off)
 {
-       unsigned long reg = (lvt_off << 4) + K8_APIC_EXT_LVT_BASE;
-       unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
+       unsigned int v = 0;
+       unsigned long reg = (lvt_off << 4) + 0x500;
+       v |= THRESHOLD_APIC_VECTOR;
        apic_write(reg, v);
 }
+#endif /* CONFIG_X86_MCE_AMD */
 
 #undef APIC_DIVISOR
 
@@ -991,7 +963,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
 }
 
 /*
- * apic_is_clustered_box() -- Check if we can expect good TSC
+ * oem_force_hpet_timer -- force HPET mode for some boxes.
  *
  * Thus far, the major user of this is IBM's Summit2 series:
  *
@@ -999,7 +971,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
  * multi-chassis. Use available data to take a good guess.
  * If in doubt, go HPET.
  */
-__cpuinit int apic_is_clustered_box(void)
+__cpuinit int oem_force_hpet_timer(void)
 {
        int i, clusters, zeros;
        unsigned id;
@@ -1030,7 +1002,8 @@ __cpuinit int apic_is_clustered_box(void)
        }
 
        /*
-        * If clusters > 2, then should be multi-chassis.
+        * If clusters > 2, then should be multi-chassis.  Return 1 for HPET.
+        * Else return 0 to use TSC.
         * May have to revisit this when multi-core + hyperthreaded CPUs come
         * out, but AFAIK this will work even for them.
         */
@@ -1098,8 +1071,7 @@ asmlinkage void smp_error_interrupt(void)
           6: Received illegal vector
           7: Illegal register address
        */
-       if (num_online_cpus() > 1)
-               printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
+       printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
                smp_processor_id(), v , v1);
        irq_exit();
 }
@@ -1145,35 +1117,35 @@ int __init APIC_init_uniprocessor (void)
 static __init int setup_disableapic(char *str) 
 { 
        disable_apic = 1;
-       return 1;
+       return 0;
 } 
 
 static __init int setup_nolapic(char *str) 
 { 
        disable_apic = 1;
-       return 1;
+       return 0;
 } 
 
 static __init int setup_noapictimer(char *str) 
 { 
        if (str[0] != ' ' && str[0] != 0)
-               return 0;
+               return -1;
        disable_apic_timer = 1;
-       return 1;
+       return 0;
 } 
 
 static __init int setup_apicmaintimer(char *str)
 {
        apic_runs_main_timer = 1;
        nohpet = 1;
-       return 1;
+       return 0;
 }
 __setup("apicmaintimer", setup_apicmaintimer);
 
 static __init int setup_noapicmaintimer(char *str)
 {
        apic_runs_main_timer = -1;
-       return 1;
+       return 0;
 }
 __setup("noapicmaintimer", setup_noapicmaintimer);