summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2012-10-31 16:44:47 +0000
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-15 00:34:22 +0100
commit13dd52f11a04e616900f565d6a1e5138e58d579f (patch)
treee7ce9521c4dbd93d0be9c7acaa1ceb7b7269e1db
parent41682032715c2c969357c81391a442a24dd1c2c2 (diff)
cpuidle: prepare the cpuidle core to handle multiple drivers
This patch is a preparation for the multiple cpuidle drivers support. As the next patch will introduce the multiple drivers with the Kconfig option and we want to keep the code clean and understandable, this patch defines a set of functions for encapsulating some common parts and splits what should be done under a lock from the rest. [rjw: Modified the subject and changelog slightly.] Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-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);