aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2014-04-11 07:47:16 -0400
committerIngo Molnar <mingo@kernel.org>2014-05-08 03:16:58 -0400
commitc444117f0f39d59733ec23da67c44424df529230 (patch)
treea03cc217b98a5a0d0072258a5da364406fb5df99 /kernel
parentfd99f91aa007ba255aac44fe6cf21c1db398243a (diff)
sched/idle: Delay clearing the polling bit
With the generic idle functions assuming !polling we should only clear the polling bit at the very last opportunity in order to avoid spurious IPIs. Ideally we'd flip the default to polling, but that means auditing all arch idle functions. Signed-off-by: Peter Zijlstra <peterz@infradead.org> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: http://lkml.kernel.org/n/tip-vq7719foqzf6z5h4j7eh7f9e@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/idle.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 8f4390a079c7..ed67f0cd2906 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -78,12 +78,10 @@ static int cpuidle_idle_call(void)
78 78
79 /* 79 /*
80 * Check if the idle task must be rescheduled. If it is the 80 * Check if the idle task must be rescheduled. If it is the
81 * case, exit the function after re-enabling the local irq and 81 * case, exit the function after re-enabling the local irq.
82 * set again the polling flag
83 */ 82 */
84 if (current_clr_polling_and_test()) { 83 if (need_resched()) {
85 local_irq_enable(); 84 local_irq_enable();
86 __current_set_polling();
87 return 0; 85 return 0;
88 } 86 }
89 87
@@ -127,7 +125,7 @@ static int cpuidle_idle_call(void)
127 broadcast = !!(drv->states[next_state].flags & 125 broadcast = !!(drv->states[next_state].flags &
128 CPUIDLE_FLAG_TIMER_STOP); 126 CPUIDLE_FLAG_TIMER_STOP);
129 127
130 if (broadcast) 128 if (broadcast) {
131 /* 129 /*
132 * Tell the time framework to switch 130 * Tell the time framework to switch
133 * to a broadcast timer because our 131 * to a broadcast timer because our
@@ -139,6 +137,7 @@ static int cpuidle_idle_call(void)
139 ret = clockevents_notify( 137 ret = clockevents_notify(
140 CLOCK_EVT_NOTIFY_BROADCAST_ENTER, 138 CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
141 &dev->cpu); 139 &dev->cpu);
140 }
142 141
143 if (!ret) { 142 if (!ret) {
144 trace_cpu_idle_rcuidle(next_state, dev->cpu); 143 trace_cpu_idle_rcuidle(next_state, dev->cpu);
@@ -175,8 +174,12 @@ static int cpuidle_idle_call(void)
175 * We can't use the cpuidle framework, let's use the default 174 * We can't use the cpuidle framework, let's use the default
176 * idle routine 175 * idle routine
177 */ 176 */
178 if (ret) 177 if (ret) {
179 arch_cpu_idle(); 178 if (!current_clr_polling_and_test())
179 arch_cpu_idle();
180 else
181 local_irq_enable();
182 }
180 183
181 __current_set_polling(); 184 __current_set_polling();
182 185