summaryrefslogtreecommitdiff
path: root/drivers/cpuidle
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/cpuidle.c2
-rw-r--r--drivers/cpuidle/driver.c18
-rw-r--r--drivers/cpuidle/governors/ladder.c6
3 files changed, 15 insertions, 11 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index e28f6ea46f1a..7f15b8514a18 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -368,7 +368,7 @@ EXPORT_SYMBOL_GPL(cpuidle_enable_device);
*/
void cpuidle_disable_device(struct cpuidle_device *dev)
{
- if (!dev->enabled)
+ if (!dev || !dev->enabled)
return;
if (!cpuidle_get_driver() || !cpuidle_curr_governor)
return;
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 58bf3b1ac9c4..87db3877fead 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -18,9 +18,10 @@ static struct cpuidle_driver *cpuidle_curr_driver;
DEFINE_SPINLOCK(cpuidle_driver_lock);
int cpuidle_driver_refcount;
-static void __cpuidle_register_driver(struct cpuidle_driver *drv)
+static void set_power_states(struct cpuidle_driver *drv)
{
int i;
+
/*
* cpuidle driver should set the drv->power_specified bit
* before registering if the driver provides
@@ -35,13 +36,10 @@ static void __cpuidle_register_driver(struct cpuidle_driver *drv)
* 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;
- }
+ for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
+ drv->states[i].power_usage = -1 - i;
}
-
/**
* cpuidle_register_driver - registers a driver
* @drv: the driver
@@ -59,13 +57,16 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
spin_unlock(&cpuidle_driver_lock);
return -EBUSY;
}
- __cpuidle_register_driver(drv);
+
+ if (!drv->power_specified)
+ set_power_states(drv);
+
cpuidle_curr_driver = drv;
+
spin_unlock(&cpuidle_driver_lock);
return 0;
}
-
EXPORT_SYMBOL_GPL(cpuidle_register_driver);
/**
@@ -96,7 +97,6 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)
spin_unlock(&cpuidle_driver_lock);
}
-
EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
struct cpuidle_driver *cpuidle_driver_ref(void)
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index b6a09ea859b1..9b784051ec12 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -88,6 +88,8 @@ static int ladder_select_state(struct cpuidle_driver *drv,
/* consider promotion */
if (last_idx < drv->state_count - 1 &&
+ !drv->states[last_idx + 1].disabled &&
+ !dev->states_usage[last_idx + 1].disable &&
last_residency > last_state->threshold.promotion_time &&
drv->states[last_idx + 1].exit_latency <= latency_req) {
last_state->stats.promotion_count++;
@@ -100,7 +102,9 @@ static int ladder_select_state(struct cpuidle_driver *drv,
/* consider demotion */
if (last_idx > CPUIDLE_DRIVER_STATE_START &&
- drv->states[last_idx].exit_latency > latency_req) {
+ (drv->states[last_idx].disabled ||
+ dev->states_usage[last_idx].disable ||
+ drv->states[last_idx].exit_latency > latency_req)) {
int i;
for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {