]> Pileus Git - ~andy/linux/blobdiff - arch/x86_64/kernel/apic.c
[PATCH] x86_64: Rename oem_force_hpet_timer to apic_is_clustered_box
[~andy/linux] / arch / x86_64 / kernel / apic.c
index d70605eda3339904b2349edb57e61cab4ce6228c..53fc17d894e8d5e96d1f97abc79c905ff831c04c 100644 (file)
@@ -51,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 = 0;
+int using_apic_timer __read_mostly = 0;
 
 static void apic_pm_activate(void);
 
@@ -342,6 +342,7 @@ 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,6 +371,25 @@ 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
         */
@@ -595,7 +615,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 0;
+       return 1;
 }
 
 __setup("apic=", apic_set_verbosity);
@@ -962,28 +982,21 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
        irq_exit();
 }
 
-int __initdata unsync_tsc_on_multicluster;
-
 /*
- * oem_force_hpet_timer -- force HPET mode for some boxes.
+ * apic_is_clustered_box() -- Check if we can expect good TSC
  *
  * Thus far, the major user of this is IBM's Summit2 series:
  *
- * Some clustered boxes may have unsynced TSC problems if they are
+ * Clustered boxes may have unsynced TSC problems if they are
  * multi-chassis. Use available data to take a good guess.
  * If in doubt, go HPET.
  */
-__cpuinit int oem_force_hpet_timer(void)
+__cpuinit int apic_is_clustered_box(void)
 {
        int i, clusters, zeros;
        unsigned id;
        DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
 
-       /* Only do this check on IBM machines - big Unisys systems
-          use multiple clusters too, but have synchronized TSC */
-       if (!unsync_tsc_on_multicluster)
-               return 0;
-
        bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
 
        for (i = 0; i < NR_CPUS; i++) {
@@ -1009,8 +1022,7 @@ __cpuinit int oem_force_hpet_timer(void)
        }
 
        /*
-        * If clusters > 2, then should be multi-chassis.  Return 1 for HPET.
-        * Else return 0 to use TSC.
+        * If clusters > 2, then should be multi-chassis.
         * May have to revisit this when multi-core + hyperthreaded CPUs come
         * out, but AFAIK this will work even for them.
         */
@@ -1124,35 +1136,35 @@ int __init APIC_init_uniprocessor (void)
 static __init int setup_disableapic(char *str) 
 { 
        disable_apic = 1;
-       return 0;
+       return 1;
 } 
 
 static __init int setup_nolapic(char *str) 
 { 
        disable_apic = 1;
-       return 0;
+       return 1;
 } 
 
 static __init int setup_noapictimer(char *str) 
 { 
        if (str[0] != ' ' && str[0] != 0)
-               return -1;
+               return 0;
        disable_apic_timer = 1;
-       return 0;
+       return 1;
 } 
 
 static __init int setup_apicmaintimer(char *str)
 {
        apic_runs_main_timer = 1;
        nohpet = 1;
-       return 0;
+       return 1;
 }
 __setup("apicmaintimer", setup_apicmaintimer);
 
 static __init int setup_noapicmaintimer(char *str)
 {
        apic_runs_main_timer = -1;
-       return 0;
+       return 1;
 }
 __setup("noapicmaintimer", setup_noapicmaintimer);