summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)
/*
* Check if the idle task must be rescheduled. If it is the
- * case, exit the function after re-enabling the local irq and
- * set again the polling flag
+ * case, exit the function after re-enabling the local irq.
*/
- if (current_clr_polling_and_test()) {
+ if (need_resched()) {
local_irq_enable();
- __current_set_polling();
return 0;
}
@@ -127,7 +125,7 @@ static int cpuidle_idle_call(void)
broadcast = !!(drv->states[next_state].flags &
CPUIDLE_FLAG_TIMER_STOP);
- if (broadcast)
+ if (broadcast) {
/*
* Tell the time framework to switch
* to a broadcast timer because our
@@ -139,6 +137,7 @@ static int cpuidle_idle_call(void)
ret = clockevents_notify(
CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
&dev->cpu);
+ }
if (!ret) {
trace_cpu_idle_rcuidle(next_state, dev->cpu);
@@ -175,8 +174,12 @@ static int cpuidle_idle_call(void)
* We can't use the cpuidle framework, let's use the default
* idle routine
*/
- if (ret)
- arch_cpu_idle();
+ if (ret) {
+ if (!current_clr_polling_and_test())
+ arch_cpu_idle();
+ else
+ local_irq_enable();
+ }
__current_set_polling();