[PATCH v2] cpufreq: powernv: Set the cpus to nominal frequency during reboot/kexec

Viresh Kumar viresh.kumar at linaro.org
Fri Aug 29 10:03:31 EST 2014


On 28 August 2014 19:36, Shilpasri G Bhat
<shilpa.bhat at linux.vnet.ibm.com> wrote:
> 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.
>
> Changes v1->v2:
> Invoke .target() driver callback to set the cpus to nominal frequency
> in reboot notifier, instead of calling cpufreq_suspend() as suggested
> by Viresh Kumar.
> Modified the commit message.

This changelog will get commited, is this what you want?

> Signed-off-by: Shilpasri G Bhat <shilpa.bhat at linux.vnet.ibm.com>
> Reviewed-by: Preeti U Murthy <preeti at linux.vnet.ibm.com>
> ---
>  drivers/cpufreq/powernv-cpufreq.c | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>
> diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
> index 379c083..ba27c49 100644
> --- a/drivers/cpufreq/powernv-cpufreq.c
> +++ b/drivers/cpufreq/powernv-cpufreq.c
> @@ -26,6 +26,7 @@
>  #include <linux/cpufreq.h>
>  #include <linux/smp.h>
>  #include <linux/of.h>
> +#include <linux/reboot.h>
>
>  #include <asm/cputhreads.h>
>  #include <asm/firmware.h>
> @@ -35,6 +36,7 @@
>  #define POWERNV_MAX_PSTATES    256
>
>  static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
> +static bool rebooting;
>
>  /*
>   * Note: The set of pstates consists of contiguous integers, the
> @@ -284,6 +286,15 @@ static void set_pstate(void *freq_data)
>  }
>
>  /*
> + * get_nominal_index: Returns the index corresponding to the nominal
> + * pstate in the cpufreq table
> + */
> +static inline unsigned int get_nominal_index(void)
> +{
> +       return powernv_pstate_info.max - powernv_pstate_info.nominal;
> +}
> +
> +/*
>   * powernv_cpufreq_target_index: Sets the frequency corresponding to
>   * the cpufreq table entry indexed by new_index on the cpus in the
>   * mask policy->cpus
> @@ -293,6 +304,9 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
>  {
>         struct powernv_smp_call_data freq_data;
>
> +       if (unlikely(rebooting) && new_index != get_nominal_index())
> +               return -EBUSY;

Have you placed the unlikely only around 'rebooting' intentionally or
should it cover whole if statement?

> +
>         freq_data.pstate_id = powernv_freqs[new_index].driver_data;
>
>         /*
> @@ -317,6 +331,25 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
>         return cpufreq_table_validate_and_show(policy, powernv_freqs);
>  }
>
> +static int powernv_cpufreq_reboot_notifier(struct notifier_block *nb,
> +                               unsigned long action, void *unused)
> +{
> +       int cpu;
> +       struct cpufreq_policy cpu_policy;
> +
> +       rebooting = true;
> +       for_each_online_cpu(cpu) {
> +               cpufreq_get_policy(&cpu_policy, cpu);
> +               powernv_cpufreq_target_index(&cpu_policy, get_nominal_index());
> +       }
> +
> +       return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block powernv_cpufreq_reboot_nb = {
> +       .notifier_call = powernv_cpufreq_reboot_notifier,
> +};
> +
>  static struct cpufreq_driver powernv_cpufreq_driver = {
>         .name           = "powernv-cpufreq",
>         .flags          = CPUFREQ_CONST_LOOPS,
> @@ -342,12 +375,14 @@ static int __init powernv_cpufreq_init(void)
>                 return rc;
>         }
>
> +       register_reboot_notifier(&powernv_cpufreq_reboot_nb);
>         return cpufreq_register_driver(&powernv_cpufreq_driver);
>  }
>  module_init(powernv_cpufreq_init);
>
>  static void __exit powernv_cpufreq_exit(void)
>  {
> +       unregister_reboot_notifier(&powernv_cpufreq_reboot_nb);
>         cpufreq_unregister_driver(&powernv_cpufreq_driver);
>  }
>  module_exit(powernv_cpufreq_exit);

Looks fine otherwise.

Acked-by: Viresh Kumar <viresh.kumar at linaro.org>


More information about the Linuxppc-dev mailing list