aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorVenkatesh Pallipadi <venkatesh.pallipadi@intel.com>2008-05-19 19:09:27 -0400
committerLen Brown <len.brown@intel.com>2008-06-11 19:13:45 -0400
commitdcb84f335bee9c9a7781cfc5d74492dccaf066d2 (patch)
treee24d4ca7df49b2a87862aa69c09d21ad45a024b7 /drivers/acpi
parente1094bfa26e5e94af2fea79e004614dbce42b008 (diff)
cpuidle acpi driver: fix oops on AC<->DC
cpuidle and acpi driver interaction bug with the way cpuidle_register_driver() is called. Due to this bug, there will be oops on AC<->DC on some systems, where they support C-states in one DC and not in AC. The current code does ON BOOT: Look at CST and other C-state info to see whether more than C1 is supported. If it is, then acpi processor_idle does a cpuidle_register_driver() call, which internally enables the device. ON CST change notification (AC<->DC) and on suspend-resume: acpi driver temporarily disables device, updates the device with any new C-states, and reenables the device. The problem is is on boot, there are no C2, C3 states supported and we skip the register. Later on AC<->DC, we may get a CST notification and we try to reevaluate CST and enabled the device, without actually registering it. This causes breakage as we try to create /sys fs sub directory, without the parent directory which is created at register time. Thanks to Sanjeev for reporting the problem here. http://bugzilla.kernel.org/show_bug.cgi?id=10394 Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/processor_idle.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 2dd2c1f3a01c..556ee1585192 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1669,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1669 return -EINVAL; 1669 return -EINVAL;
1670 } 1670 }
1671 1671
1672 dev->cpu = pr->id;
1672 for (i = 0; i < CPUIDLE_STATE_MAX; i++) { 1673 for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
1673 dev->states[i].name[0] = '\0'; 1674 dev->states[i].name[0] = '\0';
1674 dev->states[i].desc[0] = '\0'; 1675 dev->states[i].desc[0] = '\0';
@@ -1738,7 +1739,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1738 1739
1739int acpi_processor_cst_has_changed(struct acpi_processor *pr) 1740int acpi_processor_cst_has_changed(struct acpi_processor *pr)
1740{ 1741{
1741 int ret; 1742 int ret = 0;
1742 1743
1743 if (boot_option_idle_override) 1744 if (boot_option_idle_override)
1744 return 0; 1745 return 0;
@@ -1756,8 +1757,10 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
1756 cpuidle_pause_and_lock(); 1757 cpuidle_pause_and_lock();
1757 cpuidle_disable_device(&pr->power.dev); 1758 cpuidle_disable_device(&pr->power.dev);
1758 acpi_processor_get_power_info(pr); 1759 acpi_processor_get_power_info(pr);
1759 acpi_processor_setup_cpuidle(pr); 1760 if (pr->flags.power) {
1760 ret = cpuidle_enable_device(&pr->power.dev); 1761 acpi_processor_setup_cpuidle(pr);
1762 ret = cpuidle_enable_device(&pr->power.dev);
1763 }
1761 cpuidle_resume_and_unlock(); 1764 cpuidle_resume_and_unlock();
1762 1765
1763 return ret; 1766 return ret;
@@ -1813,7 +1816,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
1813 if (pr->flags.power) { 1816 if (pr->flags.power) {
1814#ifdef CONFIG_CPU_IDLE 1817#ifdef CONFIG_CPU_IDLE
1815 acpi_processor_setup_cpuidle(pr); 1818 acpi_processor_setup_cpuidle(pr);
1816 pr->power.dev.cpu = pr->id;
1817 if (cpuidle_register_device(&pr->power.dev)) 1819 if (cpuidle_register_device(&pr->power.dev))
1818 return -EIO; 1820 return -EIO;
1819#endif 1821#endif
@@ -1850,8 +1852,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
1850 return 0; 1852 return 0;
1851 1853
1852#ifdef CONFIG_CPU_IDLE 1854#ifdef CONFIG_CPU_IDLE
1853 if (pr->flags.power) 1855 cpuidle_unregister_device(&pr->power.dev);
1854 cpuidle_unregister_device(&pr->power.dev);
1855#endif 1856#endif
1856 pr->flags.power_setup_done = 0; 1857 pr->flags.power_setup_done = 0;
1857 1858