summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/cpuidle/driver.c60
1 files changed, 42 insertions, 18 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 3e5907569233..8246662f594a 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -39,11 +39,20 @@ static void set_power_states(struct cpuidle_driver *drv)
drv->states[i].power_usage = -1 - i;
}
-/**
- * cpuidle_register_driver - registers a driver
- * @drv: the driver
- */
-int cpuidle_register_driver(struct cpuidle_driver *drv)
+static void __cpuidle_driver_init(struct cpuidle_driver *drv)
+{
+ drv->refcnt = 0;
+
+ if (!drv->power_specified)
+ set_power_states(drv);
+}
+
+static void cpuidle_set_driver(struct cpuidle_driver *drv)
+{
+ cpuidle_curr_driver = drv;
+}
+
+static int __cpuidle_register_driver(struct cpuidle_driver *drv)
{
if (!drv || !drv->state_count)
return -EINVAL;
@@ -51,22 +60,38 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
if (cpuidle_disabled())
return -ENODEV;
- spin_lock(&cpuidle_driver_lock);
- if (cpuidle_curr_driver) {
- spin_unlock(&cpuidle_driver_lock);
+ if (cpuidle_get_driver())
return -EBUSY;
- }
- if (!drv->power_specified)
- set_power_states(drv);
+ __cpuidle_driver_init(drv);
- drv->refcnt = 0;
+ cpuidle_set_driver(drv);
- cpuidle_curr_driver = drv;
+ return 0;
+}
+
+static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
+{
+ if (drv != cpuidle_get_driver())
+ return;
+
+ if (!WARN_ON(drv->refcnt > 0))
+ cpuidle_set_driver(NULL);
+}
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+ int ret;
+
+ spin_lock(&cpuidle_driver_lock);
+ ret = __cpuidle_register_driver(drv);
spin_unlock(&cpuidle_driver_lock);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(cpuidle_register_driver);
@@ -86,8 +111,7 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);
void cpuidle_unregister_driver(struct cpuidle_driver *drv)
{
spin_lock(&cpuidle_driver_lock);
- if (drv == cpuidle_curr_driver && !WARN_ON(drv->refcnt > 0))
- cpuidle_curr_driver = NULL;
+ __cpuidle_unregister_driver(drv);
spin_unlock(&cpuidle_driver_lock);
}
EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
@@ -98,7 +122,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
spin_lock(&cpuidle_driver_lock);
- drv = cpuidle_curr_driver;
+ drv = cpuidle_get_driver();
drv->refcnt++;
spin_unlock(&cpuidle_driver_lock);
@@ -107,7 +131,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
void cpuidle_driver_unref(void)
{
- struct cpuidle_driver *drv = cpuidle_curr_driver;
+ struct cpuidle_driver *drv = cpuidle_get_driver();
spin_lock(&cpuidle_driver_lock);