summaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorJakub Kądziołka <niedzejkob@invisiblethingslab.com>2022-03-23 02:21:03 +0100
committerBoris Ostrovsky <boris.ostrovsky@oracle.com>2022-03-25 14:22:15 -0500
commitff32baa1f39b1adb519479a51e7acbcbfdd2206c (patch)
treea0f939e111048f10f935bcf6cdb45a2c45821154 /drivers/xen
parent309b517276f21dc7e6315c6637792f8bbfdf7ec4 (diff)
downloadlinux-ff32baa1f39b1adb519479a51e7acbcbfdd2206c.tar.gz
linux-ff32baa1f39b1adb519479a51e7acbcbfdd2206c.tar.bz2
linux-ff32baa1f39b1adb519479a51e7acbcbfdd2206c.zip
xen: don't hang when resuming PCI device
If a xen domain with at least two VCPUs has a PCI device attached which enters the D3hot state during suspend, the kernel may hang while resuming, depending on the core on which an async resume task gets scheduled. The bug occurs because xen's do_suspend calls dpm_resume_start while only the timer of the boot CPU has been resumed (when xen_suspend called syscore_resume), before calling xen_arch_suspend to resume the timers of the other CPUs. This breaks pci_dev_d3_sleep. Thus this patch moves the call to xen_arch_resume before the call to dpm_resume_start, eliminating the hangs and restoring the stack-like structure of the suspend/restore procedure. Signed-off-by: Jakub Kądziołka <niedzejkob@invisiblethingslab.com> Reviewed-by: Juergen Gross <jgross@suse.com> Link: https://lore.kernel.org/r/20220323012103.2537-1-niedzejkob@invisiblethingslab.com Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/manage.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 374d36de7f5a..3d5a384d65f7 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -141,6 +141,8 @@ static void do_suspend(void)
raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
+ xen_arch_resume();
+
dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
if (err) {
@@ -148,8 +150,6 @@ static void do_suspend(void)
si.cancelled = 1;
}
- xen_arch_resume();
-
out_resume:
if (!si.cancelled)
xs_resume();