summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2014-06-24 19:16:21 +0200
committerDaniel Lezcano <daniel.lezcano@linaro.org>2015-11-05 11:02:55 +0100
commit67763db9878465df1b43479149aee4cc80192638 (patch)
tree74654520e10505dd1c1589297cfbd27aecb3d556
parent511c0801da29dbd2db383b5b47b4aa907d2cde63 (diff)
cpuidle: Add a simple irq governor
This simple governor takes into account the predictable events: the timer sleep duration and the next expected irq sleep duration. By mixing both it deduced what idle state fits better. The main purpose of this governor is to handle the guessed next events in a categorized way: 1. deterministic events : timers 2. guessed events : IOs 3. predictable events : keystroke, incoming network packet, ... This governor is aimed to be moved later near the scheduler, so this one can inspect/inject more informations and act proactively rather than reactively. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Conflicts: drivers/cpuidle/Kconfig
-rw-r--r--drivers/cpuidle/Kconfig4
-rw-r--r--drivers/cpuidle/governors/Makefile1
-rw-r--r--drivers/cpuidle/governors/irq.c56
3 files changed, 61 insertions, 0 deletions
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 8c7930b5a65f..c58796f3d624 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -25,6 +25,10 @@ config CPU_IDLE_GOV_MENU
bool "Menu governor (for tickless system)"
default y
+config CPU_IDLE_GOV_IRQ
+ bool "Irq governor (for tickless system)"
+ default y
+
config DT_IDLE_STATES
bool
diff --git a/drivers/cpuidle/governors/Makefile b/drivers/cpuidle/governors/Makefile
index 1b512722689f..8804ee2f550c 100644
--- a/drivers/cpuidle/governors/Makefile
+++ b/drivers/cpuidle/governors/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o
obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o
+obj-$(CONFIG_CPU_IDLE_GOV_IRQ) += irq.o
diff --git a/drivers/cpuidle/governors/irq.c b/drivers/cpuidle/governors/irq.c
new file mode 100644
index 000000000000..1bc806f1dc01
--- /dev/null
+++ b/drivers/cpuidle/governors/irq.c
@@ -0,0 +1,56 @@
+/*
+ * irq.c - the irq governor
+ *
+ * Copyright (C) 2015 Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+*/
+#include <linux/ktime.h>
+#include <linux/tick.h>
+#include <linux/irq.h>
+#include <linux/cpuidle.h>
+#include <linux/pm_qos.h>
+
+static int select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
+{
+ s64 next_irq_event = irqt_get_next_prediction(dev->cpu);
+ s64 next_timer_event = ktime_to_us(tick_nohz_get_sleep_length());
+ s64 next_event = next_irq_event ?
+ min(next_irq_event, next_timer_event) : next_timer_event;
+
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
+ int i, index = 0;
+
+ /*
+ * Find the idle state with the lowest power while satisfying
+ * our constraints.
+ */
+ for (i = 0; i < drv->state_count; i++) {
+ struct cpuidle_state *s = &drv->states[i];
+ struct cpuidle_state_usage *su = &dev->states_usage[i];
+
+ if (s->disabled || su->disable)
+ continue;
+ if (s->target_residency > next_event)
+ continue;
+ if (s->exit_latency > latency_req)
+ continue;
+
+ index = i;
+ }
+
+ return index;
+}
+
+static struct cpuidle_governor irq_governor = {
+ .name = "irq",
+ .rating = 10,
+ .select = select,
+ .owner = THIS_MODULE,
+};
+
+static int __init irq_init(void)
+{
+ return cpuidle_register_governor(&irq_governor);
+}
+
+postcore_initcall(irq_init);