summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-06-04 16:35:49 -0700
committerGary King <gking@nvidia.com>2010-06-07 09:01:32 -0700
commitcdbce62ac97f228bcd6e4bb37d24d4de6abc0d3f (patch)
tree2cd1b14a5b5591b1c2f69fd67f51e66e396af139
parente742fe51f766a091bf2a31f4adb165e9750f44c3 (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.c34
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);
}