summaryrefslogtreecommitdiffstats
path: root/kernel/kexec.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-05-24 21:15:07 +0200
committerRafael J. Wysocki <rjw@sisk.pl>2009-05-24 21:15:07 +0200
commit32bdfac5462d777f35b00838893c4f87baf23efe (patch)
tree92e4ef3af7b68007e8004eaca978865a29e543b0 /kernel/kexec.c
parent59a3759d0fe8d969888c741bb33f4946e4d3750d (diff)
downloadlinux-32bdfac5462d777f35b00838893c4f87baf23efe.tar.gz
linux-32bdfac5462d777f35b00838893c4f87baf23efe.tar.bz2
linux-32bdfac5462d777f35b00838893c4f87baf23efe.zip
PM: Do not hold dpm_list_mtx while disabling/enabling nonboot CPUs
We shouldn't hold dpm_list_mtx while executing [disable|enable]_nonboot_cpus(), because theoretically this may lead to a deadlock as shown by the following example (provided by Johannes Berg): CPU 3 CPU 2 CPU 1 suspend/hibernate something: rtnl_lock() device_pm_lock() -> mutex_lock(&dpm_list_mtx) mutex_lock(&dpm_list_mtx) linkwatch_work -> rtnl_lock() disable_nonboot_cpus() -> flush CPU 3 workqueue Fortunately, device drivers are supposed to stop any activities that might lead to the registration of new device objects way before disable_nonboot_cpus() is called, so it shouldn't be necessary to hold dpm_list_mtx over the entire late part of device suspend and early part of device resume. Thus, during the late suspend and the early resume of devices acquire dpm_list_mtx only when dpm_list is going to be traversed and release it right after that. This patch is reported to fix the regressions tracked as http://bugzilla.kernel.org/show_bug.cgi?id=13245. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Alan Stern <stern@rowland.harvard.edu> Reported-by: Miles Lane <miles.lane@gmail.com> Tested-by: Ming Lei <tom.leiming@gmail.com>
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r--kernel/kexec.c2
1 files changed, 0 insertions, 2 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 5a758c6e4950..e4983770913b 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1451,7 +1451,6 @@ int kernel_kexec(void)
error = device_suspend(PMSG_FREEZE);
if (error)
goto Resume_console;
- device_pm_lock();
/* At this point, device_suspend() has been called,
* but *not* device_power_down(). We *must*
* device_power_down() now. Otherwise, drivers for
@@ -1489,7 +1488,6 @@ int kernel_kexec(void)
enable_nonboot_cpus();
device_power_up(PMSG_RESTORE);
Resume_devices:
- device_pm_unlock();
device_resume(PMSG_RESTORE);
Resume_console:
resume_console();