ACPI/CPUIDLE: prevent setting pm_idle to NULL
pm_idle_save resp. pm_idle_old can be NULL when the restore code in acpi_processor_cst_has_changed() resp. cpuidle_uninstall_idle_handler() is called. This can set pm_idle unconditinally to NULL, which causes the kernel to panic when calling pm_idle in the x86 idle code. This was covered by an extra check for !pm_idle in the x86 idle code, which was removed during the x86 idle code refactoring. Instead of restoring the pm_idle check in the x86 code prevent the acpi/cpuidle code to set pm_idle to NULL. Reported by: Dhaval Giani http://lkml.org/lkml/2008/7/2/309 Based on a debug patch from Ingo Molnar Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
9ffc1699e3
Коммит
b032bf70df
|
@ -1332,9 +1332,15 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
||||||
if (!pr->flags.power_setup_done)
|
if (!pr->flags.power_setup_done)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Fall back to the default idle loop */
|
/*
|
||||||
pm_idle = pm_idle_save;
|
* Fall back to the default idle loop, when pm_idle_save had
|
||||||
synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
|
* been initialized.
|
||||||
|
*/
|
||||||
|
if (pm_idle_save) {
|
||||||
|
pm_idle = pm_idle_save;
|
||||||
|
/* Relies on interrupts forcing exit from idle. */
|
||||||
|
synchronize_sched();
|
||||||
|
}
|
||||||
|
|
||||||
pr->flags.power = 0;
|
pr->flags.power = 0;
|
||||||
result = acpi_processor_get_power_info(pr);
|
result = acpi_processor_get_power_info(pr);
|
||||||
|
@ -1896,7 +1902,8 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
|
||||||
|
|
||||||
/* Unregister the idle handler when processor #0 is removed. */
|
/* Unregister the idle handler when processor #0 is removed. */
|
||||||
if (pr->id == 0) {
|
if (pr->id == 0) {
|
||||||
pm_idle = pm_idle_save;
|
if (pm_idle_save)
|
||||||
|
pm_idle = pm_idle_save;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are about to unload the current idle thread pm callback
|
* We are about to unload the current idle thread pm callback
|
||||||
|
|
|
@ -94,7 +94,7 @@ void cpuidle_install_idle_handler(void)
|
||||||
*/
|
*/
|
||||||
void cpuidle_uninstall_idle_handler(void)
|
void cpuidle_uninstall_idle_handler(void)
|
||||||
{
|
{
|
||||||
if (enabled_devices && (pm_idle != pm_idle_old)) {
|
if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
|
||||||
pm_idle = pm_idle_old;
|
pm_idle = pm_idle_old;
|
||||||
cpuidle_kick_cpus();
|
cpuidle_kick_cpus();
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче