summaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-06-16 15:20:11 +0200
committerRafael J. Wysocki <rjw@sisk.pl>2012-07-03 19:06:25 +0200
commit6e797a078824b30afbfae6cc4b1c2b21c51761ef (patch)
tree7f58824b2c1e62b954683900024a5b97a4d30b4d /drivers/cpuidle
parentcpuidle: move field disable from per-driver to per-cpu (diff)
downloadlinux-6e797a078824b30afbfae6cc4b1c2b21c51761ef.tar.xz
linux-6e797a078824b30afbfae6cc4b1c2b21c51761ef.zip
PM / cpuidle: Add driver reference counter
Add a reference counter for the cpuidle driver, so that it can't be unregistered when it is in use. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/driver.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 40cd3f3024df..58bf3b1ac9c4 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -16,6 +16,7 @@
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)
{
@@ -89,8 +90,34 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)
}
spin_lock(&cpuidle_driver_lock);
- cpuidle_curr_driver = NULL;
+
+ if (!WARN_ON(cpuidle_driver_refcount > 0))
+ cpuidle_curr_driver = NULL;
+
spin_unlock(&cpuidle_driver_lock);
}
EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+
+struct cpuidle_driver *cpuidle_driver_ref(void)
+{
+ struct cpuidle_driver *drv;
+
+ spin_lock(&cpuidle_driver_lock);
+
+ drv = cpuidle_curr_driver;
+ cpuidle_driver_refcount++;
+
+ spin_unlock(&cpuidle_driver_lock);
+ return drv;
+}
+
+void cpuidle_driver_unref(void)
+{
+ spin_lock(&cpuidle_driver_lock);
+
+ if (!WARN_ON(cpuidle_driver_refcount <= 0))
+ cpuidle_driver_refcount--;
+
+ spin_unlock(&cpuidle_driver_lock);
+}