linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: daniel.lezcano@linaro.org (Daniel Lezcano)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 5/5] ARM: exynos: enable/disable cpuidle when cpu1 is down/up
Date: Fri,  4 Jan 2013 17:59:59 +0100	[thread overview]
Message-ID: <1357318799-24378-5-git-send-email-daniel.lezcano@linaro.org> (raw)
In-Reply-To: <1357318799-24378-1-git-send-email-daniel.lezcano@linaro.org>

What we have now is (1) cpu0 going always to WFI when cpu1 is up,
(2) cpu0 going to all states when cpu1 is down.

In other words, cpuidle is disabled when cpu1 is up and enabled
when cpu1 is down.

This patch use the cpu hotplug notifier to enable/disable cpuidle,
when the cpu1 is plugged or unplugged. That clarifies the code and
make it simpler.

Signed-off: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 arch/arm/mach-exynos/cpuidle.c |  117 +++++++++++++++++++++++-----------------
 1 file changed, 69 insertions(+), 48 deletions(-)

diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index e6f006b..d8f6f33 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
 #include <linux/io.h>
 #include <linux/export.h>
 #include <linux/time.h>
@@ -36,31 +38,8 @@
 
 #define S5P_CHECK_AFTR		0xFCBA0D10
 
-static int exynos4_enter_lowpower(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index);
-
 static struct cpuidle_device exynos4_cpuidle_device;
 
-static struct cpuidle_driver exynos4_idle_driver = {
-	.name			= "exynos4_idle",
-	.owner			= THIS_MODULE,
-	.en_core_tk_irqen	= 1,
-	.states = {
-		[0] = ARM_CPUIDLE_WFI_STATE,
-		[1] = {
-			.enter            = exynos4_enter_lowpower,
-			.exit_latency     = 300,
-			.target_residency = 100000,
-			.flags            = CPUIDLE_FLAG_TIME_VALID,
-			.name             = "C1",
-			.desc             = "ARM power down",
-		},
-	},
-	.state_count = 2,
-	.safe_state_index = 0,
-};
-
 /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
 static void exynos4_set_wakeupmask(void)
 {
@@ -93,9 +72,9 @@ static int idle_finisher(unsigned long flags)
 	return 1;
 }
 
-static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
+static int exynos4_enter_lowpower(struct cpuidle_device *dev,
+				  struct cpuidle_driver *drv,
+				  int index)
 {
 	unsigned long tmp;
 
@@ -143,22 +122,6 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
 	return index;
 }
 
-static int exynos4_enter_lowpower(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
-{
-	int new_index = index;
-
-	/* This mode only can be entered when other core's are offline */
-	if (num_online_cpus() > 1)
-		new_index = drv->safe_state_index;
-
-	if (new_index == 0)
-		return arm_cpuidle_simple_enter(dev, drv, new_index);
-	else
-		return exynos4_enter_core0_aftr(dev, drv, new_index);
-}
-
 static void __init exynos5_core_down_clk(void)
 {
 	unsigned int tmp;
@@ -191,6 +154,62 @@ static void __init exynos5_core_down_clk(void)
 	__raw_writel(tmp, EXYNOS5_PWR_CTRL2);
 }
 
+static int cpu_hotplug_notify(struct notifier_block *n,
+			      unsigned long action, void *hcpu)
+{
+	int ret;
+
+	/*
+	 * cpu0 can't be shutdown on Origen, so this routine is
+	 * called only for cpu1.
+	 */
+
+	switch (action & 0xf) {
+
+	case CPU_ONLINE:
+		cpuidle_pause_and_lock();
+		cpuidle_disable_device(&exynos4_cpuidle_device);
+		cpuidle_resume_and_unlock();
+		break;
+
+	case CPU_DEAD:
+		if (!exynos4_cpuidle_device.registered) {
+			ret = cpuidle_register_device(&exynos4_cpuidle_device);
+			WARN_ONCE(ret, "Failed to register cpuidle device");
+		} else {
+			cpuidle_pause_and_lock();
+			cpuidle_enable_device(&exynos4_cpuidle_device);
+			cpuidle_resume_and_unlock();
+		}
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpu_hotplug_notifier = {
+	.notifier_call = cpu_hotplug_notify,
+};
+
+static struct cpuidle_driver exynos4_idle_driver = {
+	.name			= "exynos4_idle",
+	.owner			= THIS_MODULE,
+	.en_core_tk_irqen	= 1,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE,
+		[1] = {
+			.enter            = exynos4_enter_lowpower,
+			.exit_latency     = 300,
+			.target_residency = 100000,
+			.flags            = CPUIDLE_FLAG_TIME_VALID,
+			.name             = "C1",
+			.desc             = "ARM power down",
+		},
+	},
+	.state_count = 2,
+	.safe_state_index = 0,
+};
+
 static int __init exynos4_init_cpuidle(void)
 {
 	int ret;
@@ -204,12 +223,14 @@ static int __init exynos4_init_cpuidle(void)
 		return ret;
 	}
 
-	ret = cpuidle_register_device(&exynos4_cpuidle_device);
-	if (ret) {
-		printk(KERN_ERR "CPUidle register device failed\n");
-		return ret;
-	}
+	ret = register_cpu_notifier(&cpu_hotplug_notifier);
+	if (ret)
+		goto out_unregister_driver;
+out:
+	return ret;
 
-	return 0;
+out_unregister_driver:
+	cpuidle_unregister_driver(&exynos4_idle_driver);
+	goto out;
 }
 device_initcall(exynos4_init_cpuidle);
-- 
1.7.9.5

  parent reply	other threads:[~2013-01-04 16:59 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-04 16:59 [PATCH 1/5] ARM: exynos: factor out the idle states Daniel Lezcano
2013-01-04 16:59 ` [PATCH 2/5] ARM: exynos: handle properly the return values Daniel Lezcano
2013-01-04 16:59 ` [PATCH 3/5] ARM: exynos: replace cpumask by the corresponding macro Daniel Lezcano
2013-01-04 16:59 ` [PATCH 4/5] ARM: exynos: only register cpuidle for cpu0 Daniel Lezcano
2013-01-04 16:59 ` Daniel Lezcano [this message]
2013-01-10 20:07   ` [PATCH 5/5] ARM: exynos: enable/disable cpuidle when cpu1 is down/up amit daniel kachhap
2013-01-10 21:32     ` Daniel Lezcano
2013-01-10 22:33       ` amit daniel kachhap
2013-01-15 12:56         ` Daniel Lezcano
2013-01-18  3:51           ` Kukjin Kim
2013-01-18  8:18             ` Daniel Lezcano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1357318799-24378-5-git-send-email-daniel.lezcano@linaro.org \
    --to=daniel.lezcano@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).