summaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle/cpuidle.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-07-09 21:34:25 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-07-09 21:34:25 +0100
commitf974a8ec96571535ee07880a023bcce0e3f2c76b (patch)
tree5cf09207b1ad292a55275cd0b24999fa29b9dfe8 /drivers/cpuidle/cpuidle.c
parentc0b8556f2f8146bd38324b14b1ce00f249ba8ed9 (diff)
parent4ed47896935573c8423d05bddda3f269d6e6c613 (diff)
downloadop-kernel-dev-f974a8ec96571535ee07880a023bcce0e3f2c76b.zip
op-kernel-dev-f974a8ec96571535ee07880a023bcce0e3f2c76b.tar.gz
Merge branch 'machtypes' into pxa-palm
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r--drivers/cpuidle/cpuidle.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index fc555a9..23554b6 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -38,6 +38,8 @@ static void cpuidle_kick_cpus(void)
static void cpuidle_kick_cpus(void) {}
#endif
+static int __cpuidle_register_device(struct cpuidle_device *dev);
+
/**
* cpuidle_idle_call - the main idle loop
*
@@ -138,6 +140,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
if (!dev->state_count)
return -EINVAL;
+ if (dev->registered == 0) {
+ ret = __cpuidle_register_device(dev);
+ if (ret)
+ return ret;
+ }
+
if ((ret = cpuidle_add_state_sysfs(dev)))
return ret;
@@ -232,10 +240,13 @@ static void poll_idle_init(struct cpuidle_device *dev) {}
#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
/**
- * cpuidle_register_device - registers a CPU's idle PM feature
+ * __cpuidle_register_device - internal register function called before register
+ * and enable routines
* @dev: the cpu
+ *
+ * cpuidle_lock mutex must be held before this is called
*/
-int cpuidle_register_device(struct cpuidle_device *dev)
+static int __cpuidle_register_device(struct cpuidle_device *dev)
{
int ret;
struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
@@ -247,18 +258,34 @@ int cpuidle_register_device(struct cpuidle_device *dev)
init_completion(&dev->kobj_unregister);
- mutex_lock(&cpuidle_lock);
-
poll_idle_init(dev);
per_cpu(cpuidle_devices, dev->cpu) = dev;
list_add(&dev->device_list, &cpuidle_detected_devices);
if ((ret = cpuidle_add_sysfs(sys_dev))) {
- mutex_unlock(&cpuidle_lock);
module_put(cpuidle_curr_driver->owner);
return ret;
}
+ dev->registered = 1;
+ return 0;
+}
+
+/**
+ * cpuidle_register_device - registers a CPU's idle PM feature
+ * @dev: the cpu
+ */
+int cpuidle_register_device(struct cpuidle_device *dev)
+{
+ int ret;
+
+ mutex_lock(&cpuidle_lock);
+
+ if ((ret = __cpuidle_register_device(dev))) {
+ mutex_unlock(&cpuidle_lock);
+ return ret;
+ }
+
cpuidle_enable_device(dev);
cpuidle_install_idle_handler();
@@ -278,6 +305,9 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
{
struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
+ if (dev->registered == 0)
+ return;
+
cpuidle_pause_and_lock();
cpuidle_disable_device(dev);
OpenPOWER on IntegriCloud