summaryrefslogtreecommitdiffstats
path: root/kernel/sched/idle.c
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2014-03-03 08:48:51 +0100
committerIngo Molnar <mingo@kernel.org>2014-03-11 11:52:45 +0100
commit30cdd69e2a266505ca8229c944d361ff350a6959 (patch)
treed92aad45235d3855429050a1acfb08e588704d34 /kernel/sched/idle.c
parentidle/cpuidle: Split cpuidle_idle_call main function into smaller functions (diff)
downloadlinux-30cdd69e2a266505ca8229c944d361ff350a6959.tar.xz
linux-30cdd69e2a266505ca8229c944d361ff350a6959.zip
cpuidle/idle: Move the cpuidle_idle_call function to idle.c
The cpuidle_idle_call does nothing more than calling the three individuals function and is no longer used by any arch specific code but only in the cpuidle framework code. We can move this function into the idle task code to ensure better proximity to the scheduler code. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: rjw@rjwysocki.net Cc: preeti@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/1393832934-11625-2-git-send-email-daniel.lezcano@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/idle.c')
-rw-r--r--kernel/sched/idle.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index b7976a127178..d5aaf5eb4531 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -63,6 +63,62 @@ void __weak arch_cpu_idle(void)
local_irq_enable();
}
+#ifdef CONFIG_CPU_IDLE
+/**
+ * cpuidle_idle_call - the main idle function
+ *
+ * NOTE: no locks or semaphores should be used here
+ * return non-zero on failure
+ */
+static int cpuidle_idle_call(void)
+{
+ struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+ int next_state, entered_state, ret;
+ bool broadcast;
+
+ ret = cpuidle_enabled(drv, dev);
+ if (ret < 0)
+ return ret;
+
+ /* ask the governor for the next state */
+ next_state = cpuidle_select(drv, dev);
+
+ if (need_resched()) {
+ dev->last_residency = 0;
+ /* give the governor an opportunity to reflect on the outcome */
+ cpuidle_reflect(dev, next_state);
+ local_irq_enable();
+ return 0;
+ }
+
+ broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP);
+
+ if (broadcast &&
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
+ return -EBUSY;
+
+ trace_cpu_idle_rcuidle(next_state, dev->cpu);
+
+ entered_state = cpuidle_enter(drv, dev, next_state);
+
+ trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
+
+ if (broadcast)
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+
+ /* give the governor an opportunity to reflect on the outcome */
+ cpuidle_reflect(dev, entered_state);
+
+ return 0;
+}
+#else
+static inline int cpuidle_idle_call(void)
+{
+ return -ENODEV;
+}
+#endif
+
/*
* Generic idle loop implementation
*/