mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
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 <[email protected]> Signed-off-by: Len Brown <[email protected]>
This commit is contained in:
parent
e1094bfa26
commit
dcb84f335b
3 changed files with 43 additions and 11 deletions
|
|
@ -1669,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->cpu = pr->id;
|
||||
for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
|
||||
dev->states[i].name[0] = '\0';
|
||||
dev->states[i].desc[0] = '\0';
|
||||
|
|
@ -1738,7 +1739,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
|
|||
|
||||
int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (boot_option_idle_override)
|
||||
return 0;
|
||||
|
|
@ -1756,8 +1757,10 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
|||
cpuidle_pause_and_lock();
|
||||
cpuidle_disable_device(&pr->power.dev);
|
||||
acpi_processor_get_power_info(pr);
|
||||
acpi_processor_setup_cpuidle(pr);
|
||||
ret = cpuidle_enable_device(&pr->power.dev);
|
||||
if (pr->flags.power) {
|
||||
acpi_processor_setup_cpuidle(pr);
|
||||
ret = cpuidle_enable_device(&pr->power.dev);
|
||||
}
|
||||
cpuidle_resume_and_unlock();
|
||||
|
||||
return ret;
|
||||
|
|
@ -1813,7 +1816,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
|||
if (pr->flags.power) {
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
acpi_processor_setup_cpuidle(pr);
|
||||
pr->power.dev.cpu = pr->id;
|
||||
if (cpuidle_register_device(&pr->power.dev))
|
||||
return -EIO;
|
||||
#endif
|
||||
|
|
@ -1850,8 +1852,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
|
|||
return 0;
|
||||
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
if (pr->flags.power)
|
||||
cpuidle_unregister_device(&pr->power.dev);
|
||||
cpuidle_unregister_device(&pr->power.dev);
|
||||
#endif
|
||||
pr->flags.power_setup_done = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue