From f94be00a5ab96e6a03bf0f1443c3f9470cdfaf79 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 15 Jan 2013 14:18:04 +0100 Subject: [PATCH] UPSTREAM: cpuidle: remove the power_specified field in the driver We realized that the power usage field is never filled and when it is filled for tegra, the power_specified flag is not set causing all of these values to be reset when the driver is initialized with set_power_state(). However, the power_specified flag can be simply removed under the assumption that the states are always backward sorted, which is the case with the current code. This change allows the menu governor select function and the cpuidle_play_dead() to be simplified. Moreover, the set_power_states() function can removed as it does not make sense any more. Drop the power_specified flag from struct cpuidle_driver and make the related changes as described above. As a consequence, this also fixes the bug where on the dynamic C-states system, the power fields are not initialized. [rjw: Changelog] References: https://bugzilla.kernel.org/show_bug.cgi?id=42870 References: https://bugzilla.kernel.org/show_bug.cgi?id=43349 References: https://lkml.org/lkml/2012/10/16/518 Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki (cherry picked from commit 8aef33a7cf40ca9da188e8578b2abe7267a38c52) BUG=chromium-os:35320 TEST=Boot a ZGB on AC and unplug it afterwards. Run powertop and notice how the device correctly goes down into C3. Change-Id: If4f34246ce62d77094bf8f1a1718631a4b8e8030 Reviewed-on: https://gerrit.chromium.org/gerrit/42433 Reviewed-by: Sameer Nanda Commit-Queue: Julius Werner Tested-by: Julius Werner --- drivers/cpuidle/cpuidle.c | 17 ++++------------- drivers/cpuidle/driver.c | 24 ------------------------ drivers/cpuidle/governors/menu.c | 8 ++------ include/linux/cpuidle.h | 2 +- 4 files changed, 7 insertions(+), 44 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 05c4ebff66032..2be11a9eed101 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -80,24 +80,15 @@ int cpuidle_play_dead(void) { struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv = cpuidle_get_driver(); - int i, dead_state = -1; - int power_usage = -1; + int i; if (!drv) return -ENODEV; /* Find lowest-power state that supports long-term idle */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { - struct cpuidle_state *s = &drv->states[i]; - - if (s->power_usage < power_usage && s->enter_dead) { - power_usage = s->power_usage; - dead_state = i; - } - } - - if (dead_state != -1) - return drv->states[dead_state].enter_dead(dev, dead_state); + for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--) + if (drv->states[i].enter_dead) + return drv->states[i].enter_dead(dev, i); return -ENODEV; } diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 40cd3f3024df4..2265fcfe86630 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -17,29 +17,6 @@ static struct cpuidle_driver *cpuidle_curr_driver; DEFINE_SPINLOCK(cpuidle_driver_lock); -static void __cpuidle_register_driver(struct cpuidle_driver *drv) -{ - int i; - /* - * cpuidle driver should set the drv->power_specified bit - * before registering if the driver provides - * power_usage numbers. - * - * If power_specified is not set, - * we fill in power_usage with decreasing values as the - * cpuidle code has an implicit assumption that state Cn - * uses less power than C(n-1). - * - * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned - * an power value of -1. So we use -2, -3, etc, for other - * c-states. - */ - if (!drv->power_specified) { - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) - drv->states[i].power_usage = -1 - i; - } -} - /** * cpuidle_register_driver - registers a driver @@ -58,7 +35,6 @@ int cpuidle_register_driver(struct cpuidle_driver *drv) spin_unlock(&cpuidle_driver_lock); return -EBUSY; } - __cpuidle_register_driver(drv); cpuidle_curr_driver = drv; spin_unlock(&cpuidle_driver_lock); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 06335756ea142..2df35d174afeb 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -236,7 +236,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &__get_cpu_var(menu_devices); int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); - int power_usage = -1; int i; int multiplier; struct timespec t; @@ -300,11 +299,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) if (s->exit_latency * multiplier > data->predicted_us) continue; - if (s->power_usage < power_usage) { - power_usage = s->power_usage; - data->last_state_idx = i; - data->exit_us = s->exit_latency; - } + data->last_state_idx = i; + data->exit_us = s->exit_latency; } return data->last_state_idx; diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6c26a3da0e031..10f74f2cade02 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -124,9 +124,9 @@ struct cpuidle_driver { const char *name; struct module *owner; - unsigned int power_specified:1; /* set to 1 to use the core cpuidle time keeping (for all states). */ unsigned int en_core_tk_irqen:1; + /* states array must be ordered in decreasing power consumption */ struct cpuidle_state states[CPUIDLE_STATE_MAX]; int state_count; int safe_state_index; -- 2.39.5