diff options
author | Daniel Lezcano <daniel.lezcano@linaro.org> | 2014-06-24 19:16:21 +0200 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2015-11-05 11:02:55 +0100 |
commit | 67763db9878465df1b43479149aee4cc80192638 (patch) | |
tree | 74654520e10505dd1c1589297cfbd27aecb3d556 | |
parent | 511c0801da29dbd2db383b5b47b4aa907d2cde63 (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/Kconfig | 4 | ||||
-rw-r--r-- | drivers/cpuidle/governors/Makefile | 1 | ||||
-rw-r--r-- | drivers/cpuidle/governors/irq.c | 56 |
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); |