From 7884084f3bcc98adfbd8b90a2bd6bcf10c4df2cd Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Tue, 3 Nov 2015 17:34:17 -0500 Subject: [PATCH 1/6] cpuidle,x86: increase forced cut-off for polling to 20us The cpuidle menu governor has a forced cut-off for polling at 5us, in order to deal with firmware that gives the OS bad information on cpuidle states, leading to the system spending way too much time in polling. However, at least one x86 CPU family (Atom) has chips that have a 20us break-even point for C1. Forcing the polling cut-off to less than that wastes performance and power. Increase the polling cut-off to 20us. Systems with a lower C1 latency will be found in the states table by the menu governor, which will pick those states as appropriate. Signed-off-by: Rik van Riel Acked-by: Arjan van de Ven Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 22e4463d1787a..ecc242a586c9f 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -330,7 +330,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * We want to default to C1 (hlt), not to busy polling * unless the timer is happening really really soon. */ - if (data->next_timer_us > 5 && + if (data->next_timer_us > 20 && !drv->states[CPUIDLE_DRIVER_STATE_START].disabled && dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; From a9ceb78bc75ca47972096372ff3d48648b16317a Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Tue, 3 Nov 2015 17:34:18 -0500 Subject: [PATCH 2/6] cpuidle,menu: use interactivity_req to disable polling The menu governor carefully figures out how much time we typically sleep for an estimated sleep interval, or whether there is a repeating pattern going on, and corrects that estimate for the CPU load. Then it proceeds to ignore that information when determining whether or not to consider polling. This is not a big deal on most x86 CPUs, which have very low C1 latencies, and the patch should not have any effect on those CPUs. However, certain CPUs (eg. Atom) have much higher C1 latencies, and it would be good to not waste performance and power on those CPUs if we are expecting a very low wakeup latency. Disable polling based on the estimated interactivity requirement, not on the time to the next timer interrupt. Signed-off-by: Rik van Riel Acked-by: Arjan van de Ven Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ecc242a586c9f..b1a55731f9212 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -330,7 +330,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * We want to default to C1 (hlt), not to busy polling * unless the timer is happening really really soon. */ - if (data->next_timer_us > 20 && + if (interactivity_req > 20 && !drv->states[CPUIDLE_DRIVER_STATE_START].disabled && dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; From efddfd90fb7f5ba3c7d1bff923a3626a78eee553 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Tue, 3 Nov 2015 17:34:19 -0500 Subject: [PATCH 3/6] cpuidle,menu: smooth out measured_us calculation The cpuidle state tables contain the maximum exit latency for each cpuidle state. On x86, that is the exit latency for when the entire package goes into that same idle state. However, a lot of the time we only go into the core idle state, not the package idle state. This means we see a much smaller exit latency. We have no way to detect whether we went into the core or package idle state while idle, and that is ok. However, the current menu_update logic does have the potential to trip up the repeating pattern detection in get_typical_interval. If the system is experiencing an exit latency near the idle state's exit latency, some of the samples will have exit_us subtracted, while others will not. This turns a repeating pattern into mush, potentially breaking get_typical_interval. Furthermore, for smaller sleep intervals, we know the chance that all the cores in the package went to the same idle state are fairly small. Dividing the measured_us by two, instead of subtracting the full exit latency when hitting a small measured_us, will reduce the error. Signed-off-by: Rik van Riel Acked-by: Arjan van de Ven Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/menu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index b1a55731f9212..7b0971d97cc33 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -404,8 +404,10 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) measured_us = cpuidle_get_last_residency(dev); /* Deduct exit latency */ - if (measured_us > target->exit_latency) + if (measured_us > 2 * target->exit_latency) measured_us -= target->exit_latency; + else + measured_us /= 2; /* Make sure our coefficients do not exceed unity */ if (measured_us > data->next_timer_us) From 94e8057b8420ca6eea90df76f8598639d0df26ec Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 13 Dec 2015 18:57:10 -0500 Subject: [PATCH 4/6] drivers/cpuidle: make cpuidle-clps711x.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/cpuidle/Kconfig.arm:config ARM_CLPS711X_CPUIDLE drivers/cpuidle/Kconfig.arm: bool "CPU Idle Driver for CLPS711X processors" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Acked-by: Daniel Lezcano Signed-off-by: Paul Gortmaker Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle-clps711x.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/cpuidle/cpuidle-clps711x.c b/drivers/cpuidle/cpuidle-clps711x.c index 18a7f73805081..66a9f231ec411 100644 --- a/drivers/cpuidle/cpuidle-clps711x.c +++ b/drivers/cpuidle/cpuidle-clps711x.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #define CLPS711X_CPUIDLE_NAME "clps711x-cpuidle" @@ -56,8 +56,4 @@ static struct platform_driver clps711x_cpuidle_driver = { .name = CLPS711X_CPUIDLE_NAME, }, }; -module_platform_driver_probe(clps711x_cpuidle_driver, clps711x_cpuidle_probe); - -MODULE_AUTHOR("Alexander Shiyan "); -MODULE_DESCRIPTION("CLPS711X CPU idle driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver_probe(clps711x_cpuidle_driver, clps711x_cpuidle_probe); From fdc7d515adc302030f7e4113959130bd8d123546 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 13 Dec 2015 18:57:11 -0500 Subject: [PATCH 5/6] drivers/cpuidle: make cpuidle-ux500.c explicitly non-modular The Kconfig currently controlling compilation of this code is: cpuidle/Kconfig.arm:config ARM_U8500_CPUIDLE cpuidle/Kconfig.arm: bool "Cpu Idle Driver for the ST-E u8500 processors" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Acked-by: Daniel Lezcano Signed-off-by: Paul Gortmaker Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle-ux500.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c index 8bf895c0017df..7941a090bea6d 100644 --- a/drivers/cpuidle/cpuidle-ux500.c +++ b/drivers/cpuidle/cpuidle-ux500.c @@ -9,7 +9,7 @@ * published by the Free Software Foundation. */ -#include +#include #include #include #include @@ -124,5 +124,4 @@ static struct platform_driver dbx500_cpuidle_plat_driver = { }, .probe = dbx500_cpuidle_probe, }; - -module_platform_driver(dbx500_cpuidle_plat_driver); +builtin_platform_driver(dbx500_cpuidle_plat_driver); From 84599238ea78d98136fc6f6239a14083128ecf8b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 13 Dec 2015 18:57:12 -0500 Subject: [PATCH 6/6] drivers/cpuidle: make cpuidle-exynos.c explicitly non-modular The Kconfig currently controlling compilation of this code is: cpuidle/Kconfig.arm:config ARM_EXYNOS_CPUIDLE cpuidle/Kconfig.arm: bool "Cpu Idle Driver for the Exynos processors" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Acked-by: Daniel Lezcano Signed-off-by: Paul Gortmaker Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle-exynos.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c index b5f0a9cc8185c..00cd129b10a46 100644 --- a/drivers/cpuidle/cpuidle-exynos.c +++ b/drivers/cpuidle/cpuidle-exynos.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -142,5 +142,4 @@ static struct platform_driver exynos_cpuidle_driver = { .name = "exynos_cpuidle", }, }; - -module_platform_driver(exynos_cpuidle_driver); +builtin_platform_driver(exynos_cpuidle_driver);