aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 5a628f1e2cdf..2dfd4fdb5a52 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -26,6 +26,7 @@
26#include <linux/cpufreq.h> 26#include <linux/cpufreq.h>
27#include <linux/smp.h> 27#include <linux/smp.h>
28#include <linux/of.h> 28#include <linux/of.h>
29#include <linux/reboot.h>
29 30
30#include <asm/cputhreads.h> 31#include <asm/cputhreads.h>
31#include <asm/firmware.h> 32#include <asm/firmware.h>
@@ -35,6 +36,7 @@
35#define POWERNV_MAX_PSTATES 256 36#define POWERNV_MAX_PSTATES 256
36 37
37static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; 38static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
39static bool rebooting;
38 40
39/* 41/*
40 * Note: The set of pstates consists of contiguous integers, the 42 * Note: The set of pstates consists of contiguous integers, the
@@ -284,6 +286,15 @@ static void set_pstate(void *freq_data)
284} 286}
285 287
286/* 288/*
289 * get_nominal_index: Returns the index corresponding to the nominal
290 * pstate in the cpufreq table
291 */
292static inline unsigned int get_nominal_index(void)
293{
294 return powernv_pstate_info.max - powernv_pstate_info.nominal;
295}
296
297/*
287 * powernv_cpufreq_target_index: Sets the frequency corresponding to 298 * powernv_cpufreq_target_index: Sets the frequency corresponding to
288 * the cpufreq table entry indexed by new_index on the cpus in the 299 * the cpufreq table entry indexed by new_index on the cpus in the
289 * mask policy->cpus 300 * mask policy->cpus
@@ -293,6 +304,9 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
293{ 304{
294 struct powernv_smp_call_data freq_data; 305 struct powernv_smp_call_data freq_data;
295 306
307 if (unlikely(rebooting) && new_index != get_nominal_index())
308 return 0;
309
296 freq_data.pstate_id = powernv_freqs[new_index].driver_data; 310 freq_data.pstate_id = powernv_freqs[new_index].driver_data;
297 311
298 /* 312 /*
@@ -317,6 +331,25 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
317 return cpufreq_table_validate_and_show(policy, powernv_freqs); 331 return cpufreq_table_validate_and_show(policy, powernv_freqs);
318} 332}
319 333
334static int powernv_cpufreq_reboot_notifier(struct notifier_block *nb,
335 unsigned long action, void *unused)
336{
337 int cpu;
338 struct cpufreq_policy cpu_policy;
339
340 rebooting = true;
341 for_each_online_cpu(cpu) {
342 cpufreq_get_policy(&cpu_policy, cpu);
343 powernv_cpufreq_target_index(&cpu_policy, get_nominal_index());
344 }
345
346 return NOTIFY_DONE;
347}
348
349static struct notifier_block powernv_cpufreq_reboot_nb = {
350 .notifier_call = powernv_cpufreq_reboot_notifier,
351};
352
320static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy) 353static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy)
321{ 354{
322 struct powernv_smp_call_data freq_data; 355 struct powernv_smp_call_data freq_data;
@@ -351,12 +384,14 @@ static int __init powernv_cpufreq_init(void)
351 return rc; 384 return rc;
352 } 385 }
353 386
387 register_reboot_notifier(&powernv_cpufreq_reboot_nb);
354 return cpufreq_register_driver(&powernv_cpufreq_driver); 388 return cpufreq_register_driver(&powernv_cpufreq_driver);
355} 389}
356module_init(powernv_cpufreq_init); 390module_init(powernv_cpufreq_init);
357 391
358static void __exit powernv_cpufreq_exit(void) 392static void __exit powernv_cpufreq_exit(void)
359{ 393{
394 unregister_reboot_notifier(&powernv_cpufreq_reboot_nb);
360 cpufreq_unregister_driver(&powernv_cpufreq_driver); 395 cpufreq_unregister_driver(&powernv_cpufreq_driver);
361} 396}
362module_exit(powernv_cpufreq_exit); 397module_exit(powernv_cpufreq_exit);