diff options
author | Gary King <gking@nvidia.com> | 2010-06-04 16:35:49 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-06-07 09:01:32 -0700 |
commit | cdbce62ac97f228bcd6e4bb37d24d4de6abc0d3f (patch) | |
tree | 2cd1b14a5b5591b1c2f69fd67f51e66e396af139 | |
parent | e742fe51f766a091bf2a31f4adb165e9750f44c3 (diff) |
[ARM/tegra] cpufreq: disable dynamic hotplug during suspend
to ensure that no CPUs are added or removed between the time the
system starts to suspend and the time it exits resume, register a
pm_notifier which disabled dynamic hotplug on SUSPEND_PREPARE and
re-enables it on POST_SUSPEND.
Change-Id: I6b24495b7992b4a3e47ad3c31e48ef9bd65eb2f0
Reviewed-on: http://git-master/r/2153
Reviewed-by: Trivikram Kasivajhula <tkasivajhula@nvidia.com>
Tested-by: Trivikram Kasivajhula <tkasivajhula@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/cpufreq.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/cpufreq.c b/arch/arm/mach-tegra/cpufreq.c index dd5c45b8a77d..149ad936b00c 100644 --- a/arch/arm/mach-tegra/cpufreq.c +++ b/arch/arm/mach-tegra/cpufreq.c @@ -33,6 +33,7 @@ #include <linux/kthread.h> #include <linux/workqueue.h> #include <linux/smp_lock.h> +#include <linux/suspend.h> #include <asm/system.h> #include <asm/smp_twd.h> @@ -50,12 +51,20 @@ static struct clk *clk_cpu = NULL; static DEFINE_MUTEX(init_mutex); +#ifdef CONFIG_HOTPLUG_CPU +static int disable_hotplug = 0; +#endif + static void tegra_cpufreq_hotplug(NvRmPmRequest req) { int rc = 0; #ifdef CONFIG_HOTPLUG_CPU unsigned int cpu; + smp_rmb(); + if (disable_hotplug) + return; + if (req & NvRmPmRequest_CpuOnFlag) { struct cpumask m; @@ -78,6 +87,28 @@ static void tegra_cpufreq_hotplug(NvRmPmRequest req) } +#ifdef CONFIG_HOTPLUG_CPU +static int tegra_cpufreq_pm_notifier(struct notifier_block *nfb, + unsigned long event, void *data) +{ + switch (event) { + case PM_SUSPEND_PREPARE: + disable_hotplug = 1; + smp_wmb(); + break; + case PM_POST_SUSPEND: + disable_hotplug = 0; + smp_wmb(); + break; + default: + pr_err("%s: unknown event %lu\n", __func__, event); + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} +#endif + static int tegra_cpufreq_dfsd(void *arg) { unsigned long rate, last_rate; @@ -250,6 +281,9 @@ static struct cpufreq_driver s_tegra_cpufreq_driver = { static int __init tegra_cpufreq_init(void) { +#ifdef CONFIG_HOTPLUG_CPU + pm_notifier(tegra_cpufreq_pm_notifier, 0); +#endif return cpufreq_register_driver(&s_tegra_cpufreq_driver); } |