[PATCH 0/3] Add generic idle notifiers

STALE5541d

9 messages, 4 authors, 2011-07-13 · open the first message on its own page

[PATCH 0/3] Add generic idle notifiers

From: Todd Poynor <hidden>
Date: 2011-06-28 02:49:49

Add notifiers for idle entry and exit, called with IDLE_START when a
CPU goes idle and IDLE_END when it goes out of idle, based on the
existing idle notifiers for the x86_64 arch.

Convert x86_64 to use these notifiers, and call the notifiers on ARM.

Convert the ARM LEDs events for idle start/end to these notifiers.

 arch/arm/kernel/leds.c       |   27 ++++++++++++++++++++++++++-
 arch/arm/kernel/process.c    |    5 ++---
 arch/x86/include/asm/idle.h  |    7 -------
 arch/x86/kernel/process_64.c |   18 ++----------------
 include/linux/cpu.h          |    7 +++++++
 kernel/cpu.c                 |   20 ++++++++++++++++++++
 6 files changed, 57 insertions(+), 27 deletions(-)

-- 
1.7.3.1

[PATCH 1/3] Move x86_64 idle notifiers to generic

From: Todd Poynor <hidden>
Date: 2011-06-28 02:49:52

Move the x86_64 idle notifiers originally by Andi Kleen and Venkatesh
Pallipadi to generic.

Change-Id: Idf29cda15be151f494ff245933c12462643388d5
Signed-off-by: Todd Poynor <redacted>
---
 arch/x86/include/asm/idle.h  |    7 -------
 arch/x86/kernel/process_64.c |   18 ++----------------
 include/linux/cpu.h          |    7 +++++++
 kernel/cpu.c                 |   20 ++++++++++++++++++++
 4 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/arch/x86/include/asm/idle.h b/arch/x86/include/asm/idle.h
index f49253d7..f1e4268 100644
--- a/arch/x86/include/asm/idle.h
+++ b/arch/x86/include/asm/idle.h
@@ -1,13 +1,6 @@
 #ifndef _ASM_X86_IDLE_H
 #define _ASM_X86_IDLE_H
 
-#define IDLE_START 1
-#define IDLE_END 2
-
-struct notifier_block;
-void idle_notifier_register(struct notifier_block *n);
-void idle_notifier_unregister(struct notifier_block *n);
-
 #ifdef CONFIG_X86_64
 void enter_idle(void);
 void exit_idle(void);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index ca6f7ab..63c8aed 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -56,31 +56,17 @@ asmlinkage extern void ret_from_fork(void);
 DEFINE_PER_CPU(unsigned long, old_rsp);
 static DEFINE_PER_CPU(unsigned char, is_idle);
 
-static ATOMIC_NOTIFIER_HEAD(idle_notifier);
-
-void idle_notifier_register(struct notifier_block *n)
-{
-	atomic_notifier_chain_register(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_register);
-
-void idle_notifier_unregister(struct notifier_block *n)
-{
-	atomic_notifier_chain_unregister(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_unregister);
-
 void enter_idle(void)
 {
 	percpu_write(is_idle, 1);
-	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+	idle_notifier_call_chain(IDLE_START);
 }
 
 static void __exit_idle(void)
 {
 	if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
 		return;
-	atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+	idle_notifier_call_chain(IDLE_END);
 }
 
 /* Called from interrupts to signify idle end */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 5f09323..97f1ca7 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -174,4 +174,11 @@ static inline int disable_nonboot_cpus(void) { return 0; }
 static inline void enable_nonboot_cpus(void) {}
 #endif /* !CONFIG_PM_SLEEP_SMP */
 
+#define IDLE_START 1
+#define IDLE_END 2
+
+void idle_notifier_register(struct notifier_block *n);
+void idle_notifier_unregister(struct notifier_block *n);
+void idle_notifier_call_chain(unsigned long val);
+
 #endif /* _LINUX_CPU_H_ */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 12b7458..4047707 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -594,3 +594,23 @@ void init_cpu_online(const struct cpumask *src)
 {
 	cpumask_copy(to_cpumask(cpu_online_bits), src);
 }
+
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+	atomic_notifier_chain_register(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+	atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
+
+void idle_notifier_call_chain(unsigned long val)
+{
+	atomic_notifier_call_chain(&idle_notifier, val, NULL);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_call_chain);
-- 
1.7.3.1

[PATCH 3/3] ARM: Move leds idle start/stop calls to idle notifiers

From: Todd Poynor <hidden>
Date: 2011-06-28 02:49:55

Change-Id: I5d8e4e85b17bbab7992ecb477f0bdb5e4138b166
Signed-off-by: Todd Poynor <redacted>
---
 arch/arm/kernel/leds.c    |   27 ++++++++++++++++++++++++++-
 arch/arm/kernel/process.c |    3 ---
 2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c
index 0f107dc..136e837 100644
--- a/arch/arm/kernel/leds.c
+++ b/arch/arm/kernel/leds.c
@@ -9,6 +9,8 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
 #include <linux/sysdev.h>
 #include <linux/syscore_ops.h>
 
@@ -101,6 +103,25 @@ static struct syscore_ops leds_syscore_ops = {
 	.resume		= leds_resume,
 };
 
+static int leds_idle_notifier(struct notifier_block *nb, unsigned long val,
+                                void *data)
+{
+	switch (val) {
+	case IDLE_START:
+		leds_event(led_idle_start);
+		break;
+	case IDLE_END:
+		leds_event(led_idle_end);
+		break;
+	}
+
+	return 0;
+}
+
+static struct notifier_block leds_idle_nb = {
+	.notifier_call = leds_idle_notifier,
+};
+
 static int __init leds_init(void)
 {
 	int ret;
@@ -109,8 +130,12 @@ static int __init leds_init(void)
 		ret = sysdev_register(&leds_device);
 	if (ret == 0)
 		ret = sysdev_create_file(&leds_device, &attr_event);
-	if (ret == 0)
+
+	if (ret == 0) {
 		register_syscore_ops(&leds_syscore_ops);
+		idle_notifier_register(&leds_idle_nb);
+	}
+
 	return ret;
 }
 
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 1b9101e..6adf53f 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -32,7 +32,6 @@
 #include <linux/hw_breakpoint.h>
 
 #include <asm/cacheflush.h>
-#include <asm/leds.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/thread_notify.h>
@@ -183,7 +182,6 @@ void cpu_idle(void)
 	/* endless idle loop with no priority at all */
 	while (1) {
 		tick_nohz_stop_sched_tick(1);
-		leds_event(led_idle_start);
 		idle_notifier_call_chain(IDLE_START);
 		while (!need_resched()) {
 #ifdef CONFIG_HOTPLUG_CPU
@@ -208,7 +206,6 @@ void cpu_idle(void)
 				local_irq_enable();
 			}
 		}
-		leds_event(led_idle_end);
 		idle_notifier_call_chain(IDLE_END);
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
-- 
1.7.3.1

[PATCH 2/3] ARM: Call idle notifiers

From: Todd Poynor <hidden>
Date: 2011-06-28 02:49:59

Change-Id: Id833e61c13baa1783705ac9e9046d1f0cc90c95e
Signed-off-by: Todd Poynor <redacted>
---
 arch/arm/kernel/process.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 5e1e541..1b9101e 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -184,6 +184,7 @@ void cpu_idle(void)
 	while (1) {
 		tick_nohz_stop_sched_tick(1);
 		leds_event(led_idle_start);
+		idle_notifier_call_chain(IDLE_START);
 		while (!need_resched()) {
 #ifdef CONFIG_HOTPLUG_CPU
 			if (cpu_is_offline(smp_processor_id()))
@@ -208,6 +209,7 @@ void cpu_idle(void)
 			}
 		}
 		leds_event(led_idle_end);
+		idle_notifier_call_chain(IDLE_END);
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
 		schedule();
-- 
1.7.3.1

Re: [PATCH 0/3] Add generic idle notifiers

From: Bryan Wu <hidden>
Date: 2011-06-28 09:05:26

On Tue, Jun 28, 2011 at 10:46 AM, Todd Poynor [off-list ref] wrote:
Add notifiers for idle entry and exit, called with IDLE_START when a
CPU goes idle and IDLE_END when it goes out of idle, based on the
existing idle notifiers for the x86_64 arch.

Convert x86_64 to use these notifiers, and call the notifiers on ARM.

Convert the ARM LEDs events for idle start/end to these notifiers.
LinusW and I is working on consolidation LED events interface in ARM.
Please take a look at https://patchwork.kernel.org/patch/918792/

I do like to add notifiers into ledtrig-cpu driver, which can be also
shared by x86

Thanks,
-Bryan
?arch/arm/kernel/leds.c ? ? ? | ? 27 ++++++++++++++++++++++++++-
?arch/arm/kernel/process.c ? ?| ? ?5 ++---
?arch/x86/include/asm/idle.h ?| ? ?7 -------
?arch/x86/kernel/process_64.c | ? 18 ++----------------
?include/linux/cpu.h ? ? ? ? ?| ? ?7 +++++++
?kernel/cpu.c ? ? ? ? ? ? ? ? | ? 20 ++++++++++++++++++++
?6 files changed, 57 insertions(+), 27 deletions(-)

--
1.7.3.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


-- 
Bryan Wu [off-list ref]
Kernel Developer ? ?+86.138-1617-6545 Mobile
Ubuntu Kernel Team
Canonical Ltd. ? ? ?www.canonical.com
Ubuntu - Linux for human beings | www.ubuntu.com

Re: [PATCH 0/3] Add generic idle notifiers

From: Nicolas Pitre <nico@fluxnic.net>
Date: 2011-06-28 18:29:33

On Mon, 27 Jun 2011, Todd Poynor wrote:
Add notifiers for idle entry and exit, called with IDLE_START when a
CPU goes idle and IDLE_END when it goes out of idle, based on the
existing idle notifiers for the x86_64 arch.

Convert x86_64 to use these notifiers, and call the notifiers on ARM.

Convert the ARM LEDs events for idle start/end to these notifiers.
This is nice.

Acked-by: Nicolas Pitre <redacted>

for all 3 patches.


Nicolas

Re: [PATCH 0/3] Add generic idle notifiers

From: Nicolas Pitre <nico@fluxnic.net>
Date: 2011-06-28 18:30:27

On Tue, 28 Jun 2011, Bryan Wu wrote:
On Tue, Jun 28, 2011 at 10:46 AM, Todd Poynor [off-list ref] wrote:
quoted
Add notifiers for idle entry and exit, called with IDLE_START when a
CPU goes idle and IDLE_END when it goes out of idle, based on the
existing idle notifiers for the x86_64 arch.

Convert x86_64 to use these notifiers, and call the notifiers on ARM.

Convert the ARM LEDs events for idle start/end to these notifiers.
LinusW and I is working on consolidation LED events interface in ARM.
Please take a look at https://patchwork.kernel.org/patch/918792/
There is no conflict between those two series as one deals with the way 
the LED events are generated and the other with the way those events are 
acted upon.  The LED event mechanism in the middle is still untouched 
(could be deprecated eventually when all its users have migrated to the 
common LED API but not yet).


Nicolas

Re: [PATCH 2/3] ARM: Call idle notifiers

From: Frederic Weisbecker <hidden>
Date: 2011-07-11 19:50:11

On Mon, Jun 27, 2011 at 07:46:29PM -0700, Todd Poynor wrote:
quoted hunk
Change-Id: Id833e61c13baa1783705ac9e9046d1f0cc90c95e
Signed-off-by: Todd Poynor <redacted>
---
 arch/arm/kernel/process.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 5e1e541..1b9101e 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -184,6 +184,7 @@ void cpu_idle(void)
 	while (1) {
 		tick_nohz_stop_sched_tick(1);
 		leds_event(led_idle_start);
+		idle_notifier_call_chain(IDLE_START);
 		while (!need_resched()) {
 #ifdef CONFIG_HOTPLUG_CPU
 			if (cpu_is_offline(smp_processor_id()))
@@ -208,6 +209,7 @@ void cpu_idle(void)
 			}
 		}
 		leds_event(led_idle_end);
+		idle_notifier_call_chain(IDLE_END);
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
 		schedule();
You seem to use this notifier with different semantics than x86.
x86 notifies idle state when it knows it goes to sleep and exit it any
time it gets interrupted. And it does that every time in the need_resched()
loop.

But here in ARM you enter idle only once before the loop (and you don't even
know if you will enter the loop). And you don't notify idle exit state on interrupts.

So if in the end this idle notifier is something that is really wanted, it needs
to have a consistant behaviour across archs.

Re: [PATCH 2/3] ARM: Call idle notifiers

From: Todd Poynor <hidden>
Date: 2011-07-13 22:54:03

On Mon, Jul 11, 2011 at 09:50:04PM +0200, Frederic Weisbecker wrote:
On Mon, Jun 27, 2011 at 07:46:29PM -0700, Todd Poynor wrote:
quoted
Change-Id: Id833e61c13baa1783705ac9e9046d1f0cc90c95e
Signed-off-by: Todd Poynor <redacted>
---
 arch/arm/kernel/process.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 5e1e541..1b9101e 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -184,6 +184,7 @@ void cpu_idle(void)
 	while (1) {
 		tick_nohz_stop_sched_tick(1);
 		leds_event(led_idle_start);
+		idle_notifier_call_chain(IDLE_START);
 		while (!need_resched()) {
 #ifdef CONFIG_HOTPLUG_CPU
 			if (cpu_is_offline(smp_processor_id()))
@@ -208,6 +209,7 @@ void cpu_idle(void)
 			}
 		}
 		leds_event(led_idle_end);
+		idle_notifier_call_chain(IDLE_END);
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
 		schedule();
You seem to use this notifier with different semantics than x86.
x86 notifies idle state when it knows it goes to sleep and exit it any
time it gets interrupted. And it does that every time in the need_resched()
loop.

But here in ARM you enter idle only once before the loop (and you don't even
know if you will enter the loop). And you don't notify idle exit state on interrupts.

So if in the end this idle notifier is something that is really wanted, it needs
to have a consistant behaviour across archs.
Yes, I didn't want to change the behavior of the existing notifiers
being converted in these patches, but eventually one would want
cross-arch idle callbacks with consistent behavior, and the
existing arch-specific notifications have different semantics.
My goal is to notify when the OS scheduler enters and exits its idle
loop, so the existing ARM semantics are what I'm aiming for; the x86_64
behavior is probably further evidence that it is really a
cpuidle-style operation being performed.  If the idle notifiers do
find any traction then it sounds like moving the notification to the
common schedule code would be the right thing to do.


Thanks -- Todd
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help