aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorShilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>2014-09-29 09:49:11 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-09-29 09:53:04 -0400
commitcf30af76952b0cb20c4a2cf8db16d69ca59eb652 (patch)
tree71e8b386f77b3f2d045f1c887a79589d44c84ddc /drivers/cpufreq
parentb120339c787b243cdbe3f67401b4aa5625d88ff3 (diff)
cpufreq: powernv: Set the cpus to nominal frequency during reboot/kexec
This patch ensures the cpus to kexec/reboot at nominal frequency. Nominal frequency is the highest cpu frequency on PowerPC at which the cores can run without getting throttled. If the host kernel had set the cpus to a low pstate and then it kexecs/reboots to a cpufreq disabled kernel it would cause the target kernel to perform poorly. It will also increase the boot up time of the target kernel. So set the cpus to high pstate, in this case to nominal frequency before rebooting to avoid such scenarios. The reboot notifier will set the cpus to nominal frequncy. Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> Reviewed-by: Preeti U Murthy <preeti@linux.vnet.ibm.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-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);