aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_perflib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/processor_perflib.c')
-rw-r--r--drivers/acpi/processor_perflib.c81
1 files changed, 72 insertions, 9 deletions
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 60e543d3234e..3a73a93596e8 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -30,6 +30,7 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/cpufreq.h> 32#include <linux/cpufreq.h>
33#include <linux/slab.h>
33 34
34#ifdef CONFIG_X86 35#ifdef CONFIG_X86
35#include <asm/cpufeature.h> 36#include <asm/cpufeature.h>
@@ -39,6 +40,8 @@
39#include <acpi/acpi_drivers.h> 40#include <acpi/acpi_drivers.h>
40#include <acpi/processor.h> 41#include <acpi/processor.h>
41 42
43#define PREFIX "ACPI: "
44
42#define ACPI_PROCESSOR_CLASS "processor" 45#define ACPI_PROCESSOR_CLASS "processor"
43#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" 46#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
44#define _COMPONENT ACPI_PROCESSOR_COMPONENT 47#define _COMPONENT ACPI_PROCESSOR_COMPONENT
@@ -150,21 +153,78 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
150 return 0; 153 return 0;
151} 154}
152 155
153int acpi_processor_ppc_has_changed(struct acpi_processor *pr) 156#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
157/*
158 * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status
159 * @handle: ACPI processor handle
160 * @status: the status code of _PPC evaluation
161 * 0: success. OSPM is now using the performance state specificed.
162 * 1: failure. OSPM has not changed the number of P-states in use
163 */
164static void acpi_processor_ppc_ost(acpi_handle handle, int status)
165{
166 union acpi_object params[2] = {
167 {.type = ACPI_TYPE_INTEGER,},
168 {.type = ACPI_TYPE_INTEGER,},
169 };
170 struct acpi_object_list arg_list = {2, params};
171 acpi_handle temp;
172
173 params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
174 params[1].integer.value = status;
175
176 /* when there is no _OST , skip it */
177 if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp)))
178 return;
179
180 acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
181 return;
182}
183
184int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
154{ 185{
155 int ret; 186 int ret;
156 187
157 if (ignore_ppc) 188 if (ignore_ppc) {
189 /*
190 * Only when it is notification event, the _OST object
191 * will be evaluated. Otherwise it is skipped.
192 */
193 if (event_flag)
194 acpi_processor_ppc_ost(pr->handle, 1);
158 return 0; 195 return 0;
196 }
159 197
160 ret = acpi_processor_get_platform_limit(pr); 198 ret = acpi_processor_get_platform_limit(pr);
161 199 /*
200 * Only when it is notification event, the _OST object
201 * will be evaluated. Otherwise it is skipped.
202 */
203 if (event_flag) {
204 if (ret < 0)
205 acpi_processor_ppc_ost(pr->handle, 1);
206 else
207 acpi_processor_ppc_ost(pr->handle, 0);
208 }
162 if (ret < 0) 209 if (ret < 0)
163 return (ret); 210 return (ret);
164 else 211 else
165 return cpufreq_update_policy(pr->id); 212 return cpufreq_update_policy(pr->id);
166} 213}
167 214
215int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
216{
217 struct acpi_processor *pr;
218
219 pr = per_cpu(processors, cpu);
220 if (!pr || !pr->performance || !pr->performance->state_count)
221 return -ENODEV;
222 *limit = pr->performance->states[pr->performance_platform_limit].
223 core_frequency * 1000;
224 return 0;
225}
226EXPORT_SYMBOL(acpi_processor_get_bios_limit);
227
168void acpi_processor_ppc_init(void) 228void acpi_processor_ppc_init(void)
169{ 229{
170 if (!cpufreq_register_notifier 230 if (!cpufreq_register_notifier
@@ -354,7 +414,11 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
354 if (result) 414 if (result)
355 goto update_bios; 415 goto update_bios;
356 416
357 return 0; 417 /* We need to call _PPC once when cpufreq starts */
418 if (ignore_ppc != 1)
419 result = acpi_processor_get_platform_limit(pr);
420
421 return result;
358 422
359 /* 423 /*
360 * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that 424 * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
@@ -383,8 +447,8 @@ int acpi_processor_notify_smm(struct module *calling_module)
383 if (!try_module_get(calling_module)) 447 if (!try_module_get(calling_module))
384 return -EINVAL; 448 return -EINVAL;
385 449
386 /* is_done is set to negative if an error occured, 450 /* is_done is set to negative if an error occurred,
387 * and to postitive if _no_ error occured, but SMM 451 * and to postitive if _no_ error occurred, but SMM
388 * was already notified. This avoids double notification 452 * was already notified. This avoids double notification
389 * which might lead to unexpected results... 453 * which might lead to unexpected results...
390 */ 454 */
@@ -498,7 +562,7 @@ end:
498} 562}
499 563
500int acpi_processor_preregister_performance( 564int acpi_processor_preregister_performance(
501 struct acpi_processor_performance *performance) 565 struct acpi_processor_performance __percpu *performance)
502{ 566{
503 int count, count_target; 567 int count, count_target;
504 int retval = 0; 568 int retval = 0;
@@ -509,7 +573,7 @@ int acpi_processor_preregister_performance(
509 struct acpi_processor *match_pr; 573 struct acpi_processor *match_pr;
510 struct acpi_psd_package *match_pdomain; 574 struct acpi_psd_package *match_pdomain;
511 575
512 if (!alloc_cpumask_var(&covered_cpus, GFP_KERNEL)) 576 if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))
513 return -ENOMEM; 577 return -ENOMEM;
514 578
515 mutex_lock(&performance_mutex); 579 mutex_lock(&performance_mutex);
@@ -556,7 +620,6 @@ int acpi_processor_preregister_performance(
556 * Now that we have _PSD data from all CPUs, lets setup P-state 620 * Now that we have _PSD data from all CPUs, lets setup P-state
557 * domain info. 621 * domain info.
558 */ 622 */
559 cpumask_clear(covered_cpus);
560 for_each_possible_cpu(i) { 623 for_each_possible_cpu(i) {
561 pr = per_cpu(processors, i); 624 pr = per_cpu(processors, i);
562 if (!pr) 625 if (!pr)