- Update Xen patches to 3.3-rc5 and c/s 1157.
[linux-flexiantxendom0-3.2.10.git] / drivers / acpi / processor_idle.c
index 0e8e2de..ab879bc 100644 (file)
@@ -125,6 +125,7 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = {
 };
 
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
 /*
  * Callers should disable interrupts before the call and enable
  * interrupts after return.
@@ -143,6 +144,7 @@ static void acpi_safe_halt(void)
        }
        current_thread_info()->status |= TS_POLLING;
 }
+#endif
 
 #ifdef ARCH_APICTIMER_STOPS_ON_C3
 
@@ -213,7 +215,7 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 static void lapic_timer_check_state(int state, struct acpi_processor *pr,
                                   struct acpi_processor_cx *cstate) { }
 static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { }
-static void lapic_timer_state_broadcast(struct acpi_processor *pr,
+static inline void lapic_timer_state_broadcast(struct acpi_processor *pr,
                                       struct acpi_processor_cx *cx,
                                       int broadcast)
 {
@@ -252,7 +254,7 @@ int acpi_processor_resume(struct acpi_device * device)
        return 0;
 }
 
-#if defined(CONFIG_X86)
+#if defined(CONFIG_X86) && !defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
 static void tsc_check_state(int state)
 {
        switch (boot_cpu_data.x86_vendor) {
@@ -449,7 +451,8 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
                                 */
                                cx.entry_method = ACPI_CSTATE_HALT;
                                snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
-                       } else {
+                       /* This doesn't apply to external control case */
+                       } else if (!processor_pm_external()) {
                                continue;
                        }
                        if (cx.type == ACPI_STATE_C1 &&
@@ -488,6 +491,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
 
                cx.power = obj->integer.value;
 
+#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+               /* cache control methods to notify external logic */
+               if (processor_pm_external())
+                       memcpy(&cx.reg, reg, sizeof(*reg));
+#endif
+
                current_count++;
                memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
 
@@ -509,7 +518,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
                          current_count));
 
        /* Validate number of power states discovered */
-       if (current_count < 2)
+       if (current_count < (processor_pm_external() ? 1 : 2))
                status = -EFAULT;
 
       end:
@@ -605,7 +614,9 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
        unsigned int i;
        unsigned int working = 0;
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
        pr->power.timer_broadcast_on_state = INT_MAX;
+#endif
 
        for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
                struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -677,6 +688,7 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
        return 0;
 }
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
 /**
  * acpi_idle_bm_check - checks if bus master activity was detected
  */
@@ -1106,6 +1118,10 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
 
        return 0;
 }
+#else
+static void acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) {}
+static void acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) {}
+#endif /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
 
 int acpi_processor_hotplug(struct acpi_processor *pr)
 {
@@ -1124,6 +1140,14 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
        if (!pr->flags.power_setup_done)
                return -ENODEV;
 
+       if (processor_pm_external()) {
+               pr->flags.power = 0;
+               ret = acpi_processor_get_power_info(pr);
+               processor_notify_external(pr,
+                       PROCESSOR_PM_CHANGE, PM_TYPE_IDLE);
+               return ret;
+       }
+
        cpuidle_pause_and_lock();
        cpuidle_disable_device(&pr->power.dev);
        acpi_processor_get_power_info(pr);
@@ -1201,7 +1225,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
                              struct acpi_device *device)
 {
        acpi_status status = 0;
-       int retval;
        static int first_run;
 
        if (disabled_by_idle_boot_param())
@@ -1232,12 +1255,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
        acpi_processor_get_power_info(pr);
        pr->flags.power_setup_done = 1;
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
        /*
         * Install the idle handler if processor power management is supported.
         * Note that we use previously set idle handler will be used on
         * platforms that only support C1.
         */
        if (pr->flags.power) {
+               int retval;
+
                /* Register acpi_idle_driver if not already registered */
                if (!acpi_processor_registered) {
                        acpi_processor_setup_cpuidle_states(pr);
@@ -1259,6 +1285,12 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
                }
                acpi_processor_registered++;
        }
+#endif
+
+       if (processor_pm_external())
+               processor_notify_external(pr,
+                       PROCESSOR_PM_INIT, PM_TYPE_IDLE);
+
        return 0;
 }