aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/e_powersaver.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index 84661c54a74c..2882d40a3084 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -19,6 +19,11 @@
19#include <asm/msr.h> 19#include <asm/msr.h>
20#include <asm/tsc.h> 20#include <asm/tsc.h>
21 21
22#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
23#include <linux/acpi.h>
24#include <acpi/processor.h>
25#endif
26
22#define EPS_BRAND_C7M 0 27#define EPS_BRAND_C7M 0
23#define EPS_BRAND_C7 1 28#define EPS_BRAND_C7 1
24#define EPS_BRAND_EDEN 2 29#define EPS_BRAND_EDEN 2
@@ -27,6 +32,9 @@
27 32
28struct eps_cpu_data { 33struct eps_cpu_data {
29 u32 fsb; 34 u32 fsb;
35#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
36 u32 bios_limit;
37#endif
30 struct cpufreq_frequency_table freq_table[]; 38 struct cpufreq_frequency_table freq_table[];
31}; 39};
32 40
@@ -36,6 +44,46 @@ static struct eps_cpu_data *eps_cpu[NR_CPUS];
36static int freq_failsafe_off; 44static int freq_failsafe_off;
37static int voltage_failsafe_off; 45static int voltage_failsafe_off;
38 46
47#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
48static int ignore_acpi_limit;
49
50static struct acpi_processor_performance *eps_acpi_cpu_perf;
51
52/* Minimum necessary to get acpi_processor_get_bios_limit() working */
53static int eps_acpi_init(void)
54{
55 eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance),
56 GFP_KERNEL);
57 if (!eps_acpi_cpu_perf)
58 return -ENOMEM;
59
60 if (!zalloc_cpumask_var(&eps_acpi_cpu_perf->shared_cpu_map,
61 GFP_KERNEL)) {
62 kfree(eps_acpi_cpu_perf);
63 eps_acpi_cpu_perf = NULL;
64 return -ENOMEM;
65 }
66
67 if (acpi_processor_register_performance(eps_acpi_cpu_perf, 0)) {
68 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
69 kfree(eps_acpi_cpu_perf);
70 eps_acpi_cpu_perf = NULL;
71 return -EIO;
72 }
73 return 0;
74}
75
76static int eps_acpi_exit(struct cpufreq_policy *policy)
77{
78 if (eps_acpi_cpu_perf) {
79 acpi_processor_unregister_performance(eps_acpi_cpu_perf, 0);
80 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
81 kfree(eps_acpi_cpu_perf);
82 eps_acpi_cpu_perf = NULL;
83 }
84 return 0;
85}
86#endif
39 87
40static unsigned int eps_get(unsigned int cpu) 88static unsigned int eps_get(unsigned int cpu)
41{ 89{
@@ -168,6 +216,9 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
168 int k, step, voltage; 216 int k, step, voltage;
169 int ret; 217 int ret;
170 int states; 218 int states;
219#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
220 unsigned int limit;
221#endif
171 222
172 if (policy->cpu != 0) 223 if (policy->cpu != 0)
173 return -ENODEV; 224 return -ENODEV;
@@ -271,6 +322,24 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
271 322
272 /* Calc FSB speed */ 323 /* Calc FSB speed */
273 fsb = cpu_khz / current_multiplier; 324 fsb = cpu_khz / current_multiplier;
325
326#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
327 /* Check for ACPI processor speed limit */
328 if (!ignore_acpi_limit && !eps_acpi_init()) {
329 if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) {
330 printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n",
331 limit/1000000,
332 (limit%1000000)/10000);
333 eps_acpi_exit(policy);
334 /* Check if max_multiplier is in BIOS limits */
335 if (limit && max_multiplier * fsb > limit) {
336 printk(KERN_INFO "eps: Aborting.\n");
337 return -EINVAL;
338 }
339 }
340 }
341#endif
342
274 /* Calc number of p-states supported */ 343 /* Calc number of p-states supported */
275 if (brand == EPS_BRAND_C7M) 344 if (brand == EPS_BRAND_C7M)
276 states = max_multiplier - min_multiplier + 1; 345 states = max_multiplier - min_multiplier + 1;
@@ -287,6 +356,9 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
287 356
288 /* Copy basic values */ 357 /* Copy basic values */
289 centaur->fsb = fsb; 358 centaur->fsb = fsb;
359#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
360 centaur->bios_limit = limit;
361#endif
290 362
291 /* Fill frequency and MSR value table */ 363 /* Fill frequency and MSR value table */
292 f_table = &centaur->freq_table[0]; 364 f_table = &centaur->freq_table[0];
@@ -377,6 +449,10 @@ module_param(freq_failsafe_off, int, 0644);
377MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check"); 449MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check");
378module_param(voltage_failsafe_off, int, 0644); 450module_param(voltage_failsafe_off, int, 0644);
379MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check"); 451MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check");
452#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
453module_param(ignore_acpi_limit, int, 0644);
454MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit");
455#endif
380 456
381MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>"); 457MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>");
382MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's."); 458MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");