From: Thomas Gleixner <[EMAIL PROTECTED]>

This is a preperatory patch for highres/dyntick:

- replace the big #ifdef ARCH_APICTIMER_STOPS_ON_C3 hackery by functions

- remove the double switch in the power verify function (in the worst case
  we switched ipi to apic and 20usec later apic to ipi)

- keep track of the the state which stops local APIC timer

Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
Cc: Len Brown <[EMAIL PROTECTED]>
Cc: <linux-acpi@vger.kernel.org>
Cc: Andi Kleen <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---

 drivers/acpi/processor_idle.c |   67 ++++++++++++++++++++++++++++++------------
 include/acpi/processor.h      |    1 
 2 files changed, 49 insertions(+), 19 deletions(-)

Index: linux-2.6.20-rc4-mm1-bo/drivers/acpi/processor_idle.c
===================================================================
--- linux-2.6.20-rc4-mm1-bo.orig/drivers/acpi/processor_idle.c
+++ linux-2.6.20-rc4-mm1-bo/drivers/acpi/processor_idle.c
@@ -250,6 +250,49 @@ static void acpi_cstate_enter(struct acp
        }
 }
 
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+
+/*
+ * Some BIOS implementations switch to C3 in the published C2 state. This seems
+ * to be a common problem on AMD boxen.
+ */
+static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+                                  struct acpi_processor_cx *cx)
+{
+       struct acpi_processor_power *pwr = &pr->power;
+
+       /*
+        * Check, if one of the previous states already marked the lapic
+        * unstable
+        */
+       if (pwr->timer_broadcast_on_state < state)
+               return;
+
+       if(cx->type == ACPI_STATE_C3 ||
+          boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
+               pr->power.timer_broadcast_on_state = state;
+               return;
+       }
+}
+
+static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
+{
+       cpumask_t mask = cpumask_of_cpu(pr->id);
+
+       if (pr->power.timer_broadcast_on_state < INT_MAX)
+               on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
+       else
+               on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
+}
+
+#else
+
+static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+                                  struct acpi_processor_cx *cstate) { }
+static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { }
+
+#endif
+
 static void acpi_processor_idle(void)
 {
        struct acpi_processor *pr = NULL;
@@ -920,11 +963,7 @@ static int acpi_processor_power_verify(s
        unsigned int i;
        unsigned int working = 0;
 
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-       int timer_broadcast = 0;
-       cpumask_t mask = cpumask_of_cpu(pr->id);
-       on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
-#endif
+       pr->power.timer_broadcast_on_state = INT_MAX;
 
        for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
                struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -936,21 +975,14 @@ static int acpi_processor_power_verify(s
 
                case ACPI_STATE_C2:
                        acpi_processor_power_verify_c2(cx);
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-                       /* Some AMD systems fake C3 as C2, but still
-                          have timer troubles */
-                       if (cx->valid && 
-                               boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-                               timer_broadcast++;
-#endif
+                       if (cx->valid)
+                               acpi_timer_check_state(i, pr, cx);
                        break;
 
                case ACPI_STATE_C3:
                        acpi_processor_power_verify_c3(pr, cx);
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
                        if (cx->valid)
-                               timer_broadcast++;
-#endif
+                               acpi_timer_check_state(i, pr, cx);
                        break;
                }
 
@@ -958,10 +990,7 @@ static int acpi_processor_power_verify(s
                        working++;
        }
 
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-       if (timer_broadcast)
-               on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
-#endif
+       acpi_propagate_timer_broadcast(pr);
 
        return (working);
 }
Index: linux-2.6.20-rc4-mm1-bo/include/acpi/processor.h
===================================================================
--- linux-2.6.20-rc4-mm1-bo.orig/include/acpi/processor.h
+++ linux-2.6.20-rc4-mm1-bo/include/acpi/processor.h
@@ -79,6 +79,7 @@ struct acpi_processor_power {
        u32 bm_activity;
        int count;
        struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
+       int timer_broadcast_on_state;
 };
 
 /* Performance Management */

--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to