ACPI: Notify the _PPC evaluation status to the platform
authorZhao Yakui <yakui.zhao@intel.com>
Fri, 16 Oct 2009 01:20:41 +0000 (09:20 +0800)
committerLen Brown <len.brown@intel.com>
Fri, 6 Nov 2009 06:58:07 +0000 (01:58 -0500)
According to the ACPI spec(section 8.4.4.3) OSPM should convey the _PPC
evaluations status to the platform if there exists the _OST object.
The _OST contains two arguments:
The first is the PERFORMANCE notificatin event.
The second is the status of _PPC object.
OSPM will convey the _PPC evaluation status to the platform.
Of course when the module parameter of "ignore_ppc" is added, OSPM won't
evaluate the _PPC object. But it will call the _OST object.

At the same time the _OST object will be evaluated only when the PERFORMANCE
notification event is received.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/processor_core.c
drivers/acpi/processor_perflib.c
include/acpi/processor.h

index c567b46dfa0f78a83bc1e0d0feb77e79516cfb42..773d7e76f30119ea5613c7802cbfe39509815b24 100644 (file)
@@ -722,7 +722,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)
        switch (event) {
        case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
                saved = pr->performance_platform_limit;
-               acpi_processor_ppc_has_changed(pr);
+               acpi_processor_ppc_has_changed(pr, 1);
                if (saved == pr->performance_platform_limit)
                        break;
                acpi_bus_generate_proc_event(device, event,
@@ -758,7 +758,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
        struct acpi_processor *pr = per_cpu(processors, cpu);
 
        if (action == CPU_ONLINE && pr) {
-               acpi_processor_ppc_has_changed(pr);
+               acpi_processor_ppc_has_changed(pr, 0);
                acpi_processor_cst_has_changed(pr);
                acpi_processor_tstate_has_changed(pr);
        }
@@ -830,7 +830,7 @@ static int acpi_processor_add(struct acpi_device *device)
        arch_acpi_processor_cleanup_pdc(pr);
 
 #ifdef CONFIG_CPU_FREQ
-       acpi_processor_ppc_has_changed(pr);
+       acpi_processor_ppc_has_changed(pr, 0);
 #endif
        acpi_processor_get_throttling_info(pr);
        acpi_processor_get_limit_info(pr);
index 8ba0ed0b9ddbc912684d398e2eda14357920aed4..fc1f49bbbeef1cc88b804a3b428d8ee69b1220e1 100644 (file)
@@ -152,15 +152,59 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
        return 0;
 }
 
-int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
+#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE      0x80
+/*
+ * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status
+ * @handle: ACPI processor handle
+ * @status: the status code of _PPC evaluation
+ *     0: success. OSPM is now using the performance state specificed.
+ *     1: failure. OSPM has not changed the number of P-states in use
+ */
+static void acpi_processor_ppc_ost(acpi_handle handle, int status)
+{
+       union acpi_object params[2] = {
+               {.type = ACPI_TYPE_INTEGER,},
+               {.type = ACPI_TYPE_INTEGER,},
+       };
+       struct acpi_object_list arg_list = {2, params};
+       acpi_handle temp;
+
+       params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
+       params[1].integer.value =  status;
+
+       /* when there is no _OST , skip it */
+       if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp)))
+               return;
+
+       acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
+       return;
+}
+
+int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
 {
        int ret;
 
-       if (ignore_ppc)
+       if (ignore_ppc) {
+               /*
+                * Only when it is notification event, the _OST object
+                * will be evaluated. Otherwise it is skipped.
+                */
+               if (event_flag)
+                       acpi_processor_ppc_ost(pr->handle, 1);
                return 0;
+       }
 
        ret = acpi_processor_get_platform_limit(pr);
-
+       /*
+        * Only when it is notification event, the _OST object
+        * will be evaluated. Otherwise it is skipped.
+        */
+       if (event_flag) {
+               if (ret < 0)
+                       acpi_processor_ppc_ost(pr->handle, 1);
+               else
+                       acpi_processor_ppc_ost(pr->handle, 0);
+       }
        if (ret < 0)
                return (ret);
        else
index 740ac3ad8fd06fc61b8e2dacc10054ec27469439..a920237f7c62dd3496effd65483a5bfc7286b604 100644 (file)
@@ -294,7 +294,7 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
 #ifdef CONFIG_CPU_FREQ
 void acpi_processor_ppc_init(void);
 void acpi_processor_ppc_exit(void);
-int acpi_processor_ppc_has_changed(struct acpi_processor *pr);
+int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag);
 #else
 static inline void acpi_processor_ppc_init(void)
 {
@@ -304,7 +304,8 @@ static inline void acpi_processor_ppc_exit(void)
 {
        return;
 }
-static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
+static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr,
+                                                               int event_flag)
 {
        static unsigned int printout = 1;
        if (printout) {