[PATCH 08/17] powerpc/85xx: add support to JOG feature using cpufreq interface

Tang Yuantian-B29983 B29983 at freescale.com
Sun Apr 7 12:30:41 EST 2013


Also send this patch to cpufreq at vger.kernel.org and linux-pm at vger.kernel.org
And better to rebase it on git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git

Thanks,
Yuantian

> -----Original Message-----
> From: Linuxppc-dev [mailto:linuxppc-dev-
> bounces+b29983=freescale.com at lists.ozlabs.org] On Behalf Of Zhao Chenhui
> Sent: 2013年4月3日 21:09
> To: linuxppc-dev at lists.ozlabs.org
> Subject: [PATCH 08/17] powerpc/85xx: add support to JOG feature using
> cpufreq interface
> 
> From: chenhui zhao <chenhui.zhao at freescale.com>
> 
> Some MPC85xx SoCs like MPC8536 and P1022 have a JOG feature, which
> provides a dynamic mechanism to lower or raise the CPU core clock at
> runtime.
> 
> This patch adds the support to change CPU frequency using the standard
> cpufreq interface. The ratio CORE to CCB can be 1:1(except MPC8536), 3:2,
> 2:1, 5:2, 3:1, 7:2 and 4:1.
> 
> Two CPU cores on P1022 must not in the low power state during the
> frequency transition. The driver uses a flag to meet the requirement.
> 
> The jog mode frequency transition process on the MPC8536 is similar to
> the deep sleep process. The driver need save the CPU state and restore it
> after CPU warm reset.
> 
> Note:
>  * The I/O peripherals such as PCIe and eTSEC may lose packets during
>    the jog mode frequency transition.
>  * The driver doesn't support MPC8536 Rev 1.0 due to a JOG erratum.
>    Subsequent revisions of MPC8536 have corrected the erratum.
> 
> Signed-off-by: Dave Liu <daveliu at freescale.com>
> Signed-off-by: Li Yang <leoli at freescale.com>
> Signed-off-by: Jerry Huang <Chang-Ming.Huang at freescale.com>
> Signed-off-by: Zhao Chenhui <chenhui.zhao at freescale.com>
> ---
>  arch/powerpc/platforms/85xx/Makefile |    1 +
>  arch/powerpc/sysdev/fsl_soc.h        |    5 +
>  drivers/cpufreq/Kconfig.powerpc      |   10 +
>  drivers/cpufreq/Makefile             |    1 +
>  drivers/cpufreq/cpufreq-jog.c        |  416
> ++++++++++++++++++++++++++++++++++
>  include/linux/cpu.h                  |    4 +
>  kernel/cpu.c                         |   60 +++---
>  7 files changed, 467 insertions(+), 30 deletions(-)  create mode 100644
> drivers/cpufreq/cpufreq-jog.c
> 
> diff --git a/arch/powerpc/platforms/85xx/Makefile
> b/arch/powerpc/platforms/85xx/Makefile
> index 2f4713f..4946be7 100644
> --- a/arch/powerpc/platforms/85xx/Makefile
> +++ b/arch/powerpc/platforms/85xx/Makefile
> @@ -3,6 +3,7 @@
>  #
>  obj-$(CONFIG_SMP) += smp.o
>  obj-$(CONFIG_FSL_PMC)	+= sleep.o
> +obj-$(CONFIG_MPC85xx_CPUFREQ) += sleep.o
> 
>  obj-y += common.o
> 
> diff --git a/arch/powerpc/sysdev/fsl_soc.h
> b/arch/powerpc/sysdev/fsl_soc.h index 29a87ee..b7d5ef7 100644
> --- a/arch/powerpc/sysdev/fsl_soc.h
> +++ b/arch/powerpc/sysdev/fsl_soc.h
> @@ -62,5 +62,10 @@ void fsl_hv_halt(void);
>   * code can be compatible with both 32-bit & 36-bit.
>   */
>  extern void mpc85xx_enter_deep_sleep(u64 ccsrbar, u32 powmgtreq);
> +
> +static inline void mpc85xx_enter_jog(u64 ccsrbar, u32 powmgtreq) {
> +	mpc85xx_enter_deep_sleep(ccsrbar, powmgtreq); }
>  #endif
>  #endif
> diff --git a/drivers/cpufreq/Kconfig.powerpc
> b/drivers/cpufreq/Kconfig.powerpc index e76992f..c47a662 100644
> --- a/drivers/cpufreq/Kconfig.powerpc
> +++ b/drivers/cpufreq/Kconfig.powerpc
> @@ -5,3 +5,13 @@ config CPU_FREQ_MAPLE
>  	help
>  	  This adds support for frequency switching on Maple 970FX
>  	  Evaluation Board and compatible boards (IBM JS2x blades).
> +
> +config MPC85xx_CPUFREQ
> +	bool "Support for Freescale MPC85xx CPU freq"
> +	depends on PPC_85xx && PPC32 && !PPC_E500MC
> +	select CPU_FREQ_TABLE
> +	help
> +	  This adds support for dynamic frequency switching on
> +	  Freescale MPC85xx by cpufreq interface. MPC8536 and P1022
> +	  have a JOG feature, which provides a dynamic mechanism
> +	  to lower or raise the CPU core clock at runtime.
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index
> 863fd18..628fa0e 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -61,3 +61,4 @@ obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-
> cpufreq.o
> 
> #########################################################################
> #########
>  # PowerPC platform drivers
>  obj-$(CONFIG_CPU_FREQ_MAPLE)		+= maple-cpufreq.o
> +obj-$(CONFIG_MPC85xx_CPUFREQ)		+= cpufreq-jog.o
> diff --git a/drivers/cpufreq/cpufreq-jog.c b/drivers/cpufreq/cpufreq-
> jog.c new file mode 100644 index 0000000..5656d48
> --- /dev/null
> +++ b/drivers/cpufreq/cpufreq-jog.c
> @@ -0,0 +1,416 @@
> +/*
> + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
> + * Author: Dave Liu <daveliu at freescale.com>
> + * Modifier: Chenhui Zhao <chenhui.zhao at freescale.com>
> + *
> + * The cpufreq driver is for Freescale 85xx processor,
> + * based on arch/powerpc/platforms/cell/cbe_cpufreq.c
> + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
> + *	Christian Krafft <krafft at de.ibm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2, or (at your option)
> + * any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/cpufreq.h>
> +#include <linux/of_platform.h>
> +#include <linux/suspend.h>
> +#include <linux/cpu.h>
> +#include <linux/io.h>
> +#include <linux/time.h>
> +#include <linux/smp.h>
> +
> +#include <asm/prom.h>
> +#include <asm/reg.h>
> +#include <asm/machdep.h>
> +
> +#include <sysdev/fsl_soc.h>
> +
> +static DEFINE_MUTEX(mpc85xx_switch_mutex);
> +static void __iomem *guts;
> +
> +static u32 sysfreq;
> +static unsigned int max_pll[2];
> +static atomic_t in_jog_process;
> +static struct cpufreq_frequency_table *mpc85xx_freqs; static int
> +(*set_pll)(unsigned int cpu, unsigned int pll);
> +
> +static struct cpufreq_frequency_table mpc8536_freqs_table[] = {
> +	{3,	0},
> +	{4,	0},
> +	{5,	0},
> +	{6,	0},
> +	{7,	0},
> +	{8,	0},
> +	{0,	CPUFREQ_TABLE_END},
> +};
> +
> +static struct cpufreq_frequency_table p1022_freqs_table[] = {
> +	{2,	0},
> +	{3,	0},
> +	{4,	0},
> +	{5,	0},
> +	{6,	0},
> +	{7,	0},
> +	{8,	0},
> +	{0,	CPUFREQ_TABLE_END},
> +};
> +
> +#define FREQ_500MHz	500000000
> +#define FREQ_800MHz	800000000
> +
> +#define CORE_RATIO_STRIDE	8
> +#define CORE_RATIO_MASK		0x3f
> +#define CORE_RATIO_SHIFT	16
> +
> +#define PORPLLSR	0x0	/* Power-On Reset PLL ratio status register */
> +
> +#define PMJCR		0x7c	/* Power Management Jog Control Register */
> +#define PMJCR_CORE0_SPD	0x00001000
> +#define PMJCR_CORE_SPD	0x00002000
> +
> +#define POWMGTCSR	0x80 /* Power management control and status
> register */
> +#define POWMGTCSR_JOG		0x00200000
> +#define POWMGTCSR_INT_MASK	0x00000f00
> +
> +static void spin_while_jogging(void *dummy) {
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +
> +	atomic_inc(&in_jog_process);
> +
> +	while (atomic_read(&in_jog_process) != 0)
> +		barrier();
> +
> +	local_irq_restore(flags);
> +}
> +
> +static int get_pll(int hw_cpu)
> +{
> +	int shift;
> +	u32 val = in_be32(guts + PORPLLSR);
> +
> +	shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
> +
> +	return (val >> shift) & CORE_RATIO_MASK; }
> +
> +static int mpc8536_set_pll(unsigned int cpu, unsigned int pll) {
> +	u32 corefreq, val, mask;
> +	unsigned int cur_pll = get_pll(0);
> +	unsigned long flags;
> +
> +	if (pll == cur_pll)
> +		return 0;
> +
> +	val = (pll & CORE_RATIO_MASK) << CORE_RATIO_SHIFT;
> +
> +	corefreq = sysfreq * pll / 2;
> +	/*
> +	 * Set the COREx_SPD bit if the requested core frequency
> +	 * is larger than the threshold frequency.
> +	 */
> +	if (corefreq > FREQ_800MHz)
> +			val |= PMJCR_CORE_SPD;
> +
> +	mask = (CORE_RATIO_MASK << CORE_RATIO_SHIFT) | PMJCR_CORE_SPD;
> +	clrsetbits_be32(guts + PMJCR, mask, val);
> +
> +	/* readback to sync write */
> +	in_be32(guts + PMJCR);
> +
> +	local_irq_save(flags);
> +	mpc85xx_enter_jog(get_immrbase(), POWMGTCSR_JOG);
> +	local_irq_restore(flags);
> +
> +	/* verify */
> +	cur_pll =  get_pll(0);
> +	if (cur_pll != pll) {
> +		pr_err("%s: error. The current PLL of core 0 is %d instead
> of %d.\n",
> +				__func__, cur_pll, pll);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int p1022_set_pll(unsigned int cpu, unsigned int pll) {
> +	int index, hw_cpu = get_hard_smp_processor_id(cpu);
> +	int shift;
> +	u32 corefreq, val, mask = 0;
> +	unsigned int cur_pll = get_pll(hw_cpu);
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	if (pll == cur_pll)
> +		return 0;
> +
> +	shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
> +	val = (pll & CORE_RATIO_MASK) << shift;
> +
> +	corefreq = sysfreq * pll / 2;
> +	/*
> +	 * Set the COREx_SPD bit if the requested core frequency
> +	 * is larger than the threshold frequency.
> +	 */
> +	if (corefreq > FREQ_500MHz)
> +		val |= PMJCR_CORE0_SPD << hw_cpu;
> +
> +	mask = (CORE_RATIO_MASK << shift) | (PMJCR_CORE0_SPD << hw_cpu);
> +	clrsetbits_be32(guts + PMJCR, mask, val);
> +
> +	/* readback to sync write */
> +	in_be32(guts + PMJCR);
> +
> +	cpu_hotplug_disable_before_freeze();
> +	/*
> +	 * A Jog request can not be asserted when any core is in a low
> +	 * power state on P1022. Before executing a jog request, any
> +	 * core which is in a low power state must be waked by a
> +	 * interrupt, and keep waking up until the sequence is
> +	 * finished.
> +	 */
> +	for_each_present_cpu(index) {
> +		if (!cpu_online(index)) {
> +			cpu_hotplug_enable_after_thaw();
> +			pr_err("%s: error, core%d is down.\n", __func__, index);
> +			return -1;
> +		}
> +	}
> +
> +	atomic_set(&in_jog_process, 0);
> +	smp_call_function(spin_while_jogging, NULL, 0);
> +
> +	local_irq_save(flags);
> +
> +	/* Wait for the other core to wake. */
> +	if (!spin_event_timeout(atomic_read(&in_jog_process) == 1, 1000,
> 100)) {
> +		pr_err("%s: timeout, the other core is not at running
> state.\n",
> +					__func__);
> +		ret = -1;
> +		goto err;
> +	}
> +
> +	out_be32(guts + POWMGTCSR, POWMGTCSR_JOG | POWMGTCSR_INT_MASK);
> +
> +	if (!spin_event_timeout(
> +		(in_be32(guts + POWMGTCSR) & POWMGTCSR_JOG) == 0, 1000, 100))
> {
> +		pr_err("%s: timeout, fail to switch the core frequency.\n",
> +				__func__);
> +		ret = -1;
> +		goto err;
> +	}
> +
> +	clrbits32(guts + POWMGTCSR, POWMGTCSR_INT_MASK);
> +	in_be32(guts + POWMGTCSR);
> +
> +	atomic_set(&in_jog_process, 0);
> +err:
> +	local_irq_restore(flags);
> +	cpu_hotplug_enable_after_thaw();
> +
> +	/* verify */
> +	cur_pll =  get_pll(hw_cpu);
> +	if (cur_pll != pll) {
> +		pr_err("%s: error, the current PLL of core %d is %d instead
> of %d.\n",
> +				__func__, hw_cpu, cur_pll, pll);
> +		return -1;
> +	}
> +
> +	return ret;
> +}
> +
> +/*
> + * cpufreq functions
> + */
> +static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy) {
> +	unsigned int i, cur_pll;
> +	int hw_cpu = get_hard_smp_processor_id(policy->cpu);
> +
> +	if (!cpu_present(policy->cpu))
> +		return -ENODEV;
> +
> +	/* the latency of a transition, the unit is ns */
> +	policy->cpuinfo.transition_latency = 2000;
> +
> +	cur_pll = get_pll(hw_cpu);
> +
> +	/* initialize frequency table */
> +	pr_debug("core%d frequency table:\n", hw_cpu);
> +	for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
> +		if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
> +			/* The frequency unit is kHz. */
> +			mpc85xx_freqs[i].frequency =
> +				(sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
> +		} else {
> +			mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
> +		}
> +
> +		pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
> +
> +		if (mpc85xx_freqs[i].index == cur_pll)
> +			policy->cur = mpc85xx_freqs[i].frequency;
> +	}
> +	pr_debug("current pll is at %d, and core freq is%d\n",
> +			cur_pll, policy->cur);
> +
> +	cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
> +
> +	/*
> +	 * This ensures that policy->cpuinfo_min
> +	 * and policy->cpuinfo_max are set correctly.
> +	 */
> +	return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs); }
> +
> +static int mpc85xx_cpufreq_cpu_exit(struct cpufreq_policy *policy) {
> +	cpufreq_frequency_table_put_attr(policy->cpu);
> +
> +	return 0;
> +}
> +
> +static int mpc85xx_cpufreq_verify(struct cpufreq_policy *policy) {
> +	return cpufreq_frequency_table_verify(policy, mpc85xx_freqs); }
> +
> +static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
> +			      unsigned int target_freq,
> +			      unsigned int relation)
> +{
> +	struct cpufreq_freqs freqs;
> +	unsigned int new;
> +	int ret = 0;
> +
> +	if (!set_pll)
> +		return -ENODEV;
> +
> +	cpufreq_frequency_table_target(policy,
> +				       mpc85xx_freqs,
> +				       target_freq,
> +				       relation,
> +				       &new);
> +
> +	freqs.old = policy->cur;
> +	freqs.new = mpc85xx_freqs[new].frequency;
> +	freqs.cpu = policy->cpu;
> +
> +	mutex_lock(&mpc85xx_switch_mutex);
> +	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
> +
> +	ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
> +	if (!ret) {
> +		pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL
> ratio to %d:2\n",
> +			 policy->cpu, mpc85xx_freqs[new].frequency,
> +			 mpc85xx_freqs[new].index);
> +
> +		ppc_proc_freq = freqs.new * 1000ul;
> +	}
> +	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
> +	mutex_unlock(&mpc85xx_switch_mutex);
> +
> +	return ret;
> +}
> +
> +static struct cpufreq_driver mpc85xx_cpufreq_driver = {
> +	.verify		= mpc85xx_cpufreq_verify,
> +	.target		= mpc85xx_cpufreq_target,
> +	.init		= mpc85xx_cpufreq_cpu_init,
> +	.exit		= mpc85xx_cpufreq_cpu_exit,
> +	.name		= "mpc85xx-JOG",
> +	.owner		= THIS_MODULE,
> +	.flags		= CPUFREQ_CONST_LOOPS,
> +};
> +
> +static int mpc85xx_job_probe(struct platform_device *ofdev) {
> +	struct device_node *np = ofdev->dev.of_node;
> +	unsigned int svr;
> +
> +	if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
> +		svr = mfspr(SPRN_SVR);
> +		if ((svr & 0x7fff) == 0x10) {
> +			pr_err("MPC8536 Rev 1.0 do not support JOG.\n");
> +			return -ENODEV;
> +		}
> +		mpc85xx_freqs = mpc8536_freqs_table;
> +		set_pll = mpc8536_set_pll;
> +	} else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
> +		mpc85xx_freqs = p1022_freqs_table;
> +		set_pll = p1022_set_pll;
> +	} else {
> +		return -ENODEV;
> +	}
> +
> +	sysfreq = fsl_get_sys_freq();
> +
> +	guts = of_iomap(np, 0);
> +	if (!guts)
> +		return -ENODEV;
> +
> +	max_pll[0] = get_pll(0);
> +	if (mpc85xx_freqs == p1022_freqs_table)
> +		max_pll[1] = get_pll(1);
> +
> +	pr_info("Freescale MPC85xx CPU frequency switching(JOG) driver\n");
> +
> +	return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
> +}
> +
> +static int mpc85xx_jog_remove(struct platform_device *ofdev) {
> +	iounmap(guts);
> +	cpufreq_unregister_driver(&mpc85xx_cpufreq_driver);
> +
> +	return 0;
> +}
> +
> +static struct of_device_id mpc85xx_jog_ids[] = {
> +	{ .compatible = "fsl,mpc8536-guts", },
> +	{ .compatible = "fsl,p1022-guts", },
> +	{}
> +};
> +
> +static struct platform_driver mpc85xx_jog_driver = {
> +	.driver = {
> +		.name = "mpc85xx_cpufreq_jog",
> +		.owner = THIS_MODULE,
> +		.of_match_table = mpc85xx_jog_ids,
> +	},
> +	.probe = mpc85xx_job_probe,
> +	.remove = mpc85xx_jog_remove,
> +};
> +
> +static int __init mpc85xx_jog_init(void) {
> +	return platform_driver_register(&mpc85xx_jog_driver);
> +}
> +
> +static void __exit mpc85xx_jog_exit(void) {
> +	platform_driver_unregister(&mpc85xx_jog_driver);
> +}
> +
> +module_init(mpc85xx_jog_init);
> +module_exit(mpc85xx_jog_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Dave Liu <daveliu at freescale.com>");
> diff --git a/include/linux/cpu.h b/include/linux/cpu.h index
> ce7a074..df8f73d 100644
> --- a/include/linux/cpu.h
> +++ b/include/linux/cpu.h
> @@ -146,6 +146,8 @@ void notify_cpu_starting(unsigned int cpu);  extern
> void cpu_maps_update_begin(void);  extern void cpu_maps_update_done(void);
> 
> +extern void cpu_hotplug_disable_before_freeze(void);
> +extern void cpu_hotplug_enable_after_thaw(void);
>  #else	/* CONFIG_SMP */
> 
>  #define cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
> @@ -167,6 +169,8 @@ static inline void cpu_maps_update_done(void)  {  }
> 
> +static inline void cpu_hotplug_disable_before_freeze(void)	{}
> +static inline void cpu_hotplug_enable_after_thaw(void)	{}
>  #endif /* CONFIG_SMP */
>  extern struct bus_type cpu_subsys;
> 
> diff --git a/kernel/cpu.c b/kernel/cpu.c index b5e4ab2..6fdc6df 100644
> --- a/kernel/cpu.c
> +++ b/kernel/cpu.c
> @@ -454,6 +454,36 @@ out:
>  }
>  EXPORT_SYMBOL_GPL(cpu_up);
> 
> +/*
> + * Prevent regular CPU hotplug from racing with the freezer, by
> +disabling CPU
> + * hotplug when tasks are about to be frozen. Also, don't allow the
> +freezer
> + * to continue until any currently running CPU hotplug operation gets
> + * completed.
> + * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
> + * 'cpu_add_remove_lock'. And this same lock is also taken by the
> +regular
> + * CPU hotplug path and released only after it is complete. Thus, we
> + * (and hence the freezer) will block here until any currently running
> +CPU
> + * hotplug operation gets completed.
> + */
> +void cpu_hotplug_disable_before_freeze(void)
> +{
> +	cpu_maps_update_begin();
> +	cpu_hotplug_disabled = 1;
> +	cpu_maps_update_done();
> +}
> +
> +
> +/*
> + * When tasks have been thawed, re-enable regular CPU hotplug (which
> +had been
> + * disabled while beginning to freeze tasks).
> + */
> +void cpu_hotplug_enable_after_thaw(void)
> +{
> +	cpu_maps_update_begin();
> +	cpu_hotplug_disabled = 0;
> +	cpu_maps_update_done();
> +}
> +
>  #ifdef CONFIG_PM_SLEEP_SMP
>  static cpumask_var_t frozen_cpus;
> 
> @@ -541,36 +571,6 @@ static int __init alloc_frozen_cpus(void)
> core_initcall(alloc_frozen_cpus);
> 
>  /*
> - * Prevent regular CPU hotplug from racing with the freezer, by
> disabling CPU
> - * hotplug when tasks are about to be frozen. Also, don't allow the
> freezer
> - * to continue until any currently running CPU hotplug operation gets
> - * completed.
> - * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
> - * 'cpu_add_remove_lock'. And this same lock is also taken by the
> regular
> - * CPU hotplug path and released only after it is complete. Thus, we
> - * (and hence the freezer) will block here until any currently running
> CPU
> - * hotplug operation gets completed.
> - */
> -void cpu_hotplug_disable_before_freeze(void)
> -{
> -	cpu_maps_update_begin();
> -	cpu_hotplug_disabled = 1;
> -	cpu_maps_update_done();
> -}
> -
> -
> -/*
> - * When tasks have been thawed, re-enable regular CPU hotplug (which had
> been
> - * disabled while beginning to freeze tasks).
> - */
> -void cpu_hotplug_enable_after_thaw(void)
> -{
> -	cpu_maps_update_begin();
> -	cpu_hotplug_disabled = 0;
> -	cpu_maps_update_done();
> -}
> -
> -/*
>   * When callbacks for CPU hotplug notifications are being executed, we
> must
>   * ensure that the state of the system with respect to the tasks being
> frozen
>   * or not, as reported by the notification, remains unchanged
> *throughout the
> --
> 1.7.3
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev



More information about the Linuxppc-dev mailing list