Merge branch 'for-linus' of ssh://master.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / drivers / acpi / processor_idle.c
index 4ea6d8b..6077300 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/moduleparam.h>
 #include <linux/sched.h>       /* need_resched() */
 #include <linux/latency.h>
+#include <linux/clockchips.h>
 
 /*
  * Include the apic definitions for x86 to have the APIC timer related defines
 #include <asm/apic.h>
 #endif
 
+/*
+ * Include the apic definitions for x86 to have the APIC timer related defines
+ * available also for UP (on SMP it gets magically included via linux/smp.h).
+ */
+#ifdef CONFIG_X86
+#include <asm/apic.h>
+#endif
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -58,9 +67,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_idle");
 #define ACPI_PROCESSOR_FILE_POWER      "power"
 #define US_TO_PM_TIMER_TICKS(t)                ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
 #define C2_OVERHEAD                    4       /* 1us (3.579 ticks per us) */
@@ -274,12 +282,40 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
 
 static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
 {
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+       unsigned long reason;
+
+       reason = pr->power.timer_broadcast_on_state < INT_MAX ?
+               CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
+
+       clockevents_notify(reason, &pr->id);
+#else
        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);
+#endif
+}
+
+/* Power(C) State timer broadcast control */
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+                                      struct acpi_processor_cx *cx,
+                                      int broadcast)
+{
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
+       int state = cx - pr->power.states;
+
+       if (state >= pr->power.timer_broadcast_on_state) {
+               unsigned long reason;
+
+               reason = broadcast ?  CLOCK_EVT_NOTIFY_BROADCAST_ENTER :
+                       CLOCK_EVT_NOTIFY_BROADCAST_EXIT;
+               clockevents_notify(reason, &pr->id);
+       }
+#endif
 }
 
 #else
@@ -287,6 +323,11 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
 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) { }
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+                                      struct acpi_processor_cx *cx,
+                                      int broadcast)
+{
+}
 
 #endif
 
@@ -434,6 +475,7 @@ static void acpi_processor_idle(void)
                /* Get start time (ticks) */
                t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
                /* Invoke C2 */
+               acpi_state_timer_broadcast(pr, cx, 1);
                acpi_cstate_enter(cx);
                /* Get end time (ticks) */
                t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -448,6 +490,7 @@ static void acpi_processor_idle(void)
                /* Compute time (ticks) that we were actually asleep */
                sleep_ticks =
                    ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
+               acpi_state_timer_broadcast(pr, cx, 0);
                break;
 
        case ACPI_STATE_C3:
@@ -469,6 +512,7 @@ static void acpi_processor_idle(void)
                /* Get start time (ticks) */
                t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
                /* Invoke C3 */
+               acpi_state_timer_broadcast(pr, cx, 1);
                acpi_cstate_enter(cx);
                /* Get end time (ticks) */
                t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -488,6 +532,7 @@ static void acpi_processor_idle(void)
                /* Compute time (ticks) that we were actually asleep */
                sleep_ticks =
                    ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
+               acpi_state_timer_broadcast(pr, cx, 0);
                break;
 
        default: