diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-11 17:16:32 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-11 17:16:32 -0700 |
commit | da50ccc6a0f32ad29c1168837330a78e6e2e2923 (patch) | |
tree | 26b04cc168e1ad98a308f2771e913f213f46b5ac /drivers/cpuidle/cpuidle.c | |
parent | a4df1ac12dd2d2812713a5fdd56af954d1bc251d (diff) | |
parent | 3549dba2c334e82df90f5e00ff85d2a7a2cdd1af (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (23 commits)
ACPICA: fix stray va_end() caused by mis-merge
ACPI: Reject below-freezing temperatures as invalid critical temperatures
ACPICA: Fix for access to deleted object <regression>
ACPICA: Fix to make _SST method optional
ACPICA: Fix for Load operator, load table at the namespace root
ACPICA: Ignore ACPI table signature for Load() operator
ACPICA: Fix to allow zero-length ASL field declarations
ACPI: use memory_read_from_buffer()
bay: exit if notify handler cannot be installed
dock.c remove trailing printk whitespace
proper prototype for acpi_processor_tstate_has_changed()
ACPI: handle invalid ACPI SLIT table
PNPACPI: use _CRS IRQ descriptor length for _SRS
pnpacpi: fix shareable IRQ encode/decode
pnpacpi: fix IRQ flag decoding
MAINTAINERS: update ACPI homepage
ACPI 2.6.26-rc2: Add missing newline to DSDT/SSDT warning message
ACPI: EC: Use msleep instead of udelay while waiting for event.
thinkpad-acpi: fix LED handling on older ThinkPads
thinkpad-acpi: fix initialization error paths
...
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fc555a90bb2..23554b676d6 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); |