| From: Ankur Arora <ankur.a.arora@oracle.com> |
| Date: Tue, 21 Mar 2017 15:43:38 -0700 |
| Subject: xen/acpi: upload PM state from init-domain to Xen |
| |
| commit 1914f0cd203c941bba72f9452c8290324f1ef3dc upstream. |
| |
| This was broken in commit cd979883b9ed ("xen/acpi-processor: |
| fix enabling interrupts on syscore_resume"). do_suspend (from |
| xen/manage.c) and thus xen_resume_notifier never get called on |
| the initial-domain at resume (it is if running as guest.) |
| |
| The rationale for the breaking change was that upload_pm_data() |
| potentially does blocking work in syscore_resume(). This patch |
| addresses the original issue by scheduling upload_pm_data() to |
| execute in workqueue context. |
| |
| Cc: Stanislaw Gruszka <sgruszka@redhat.com> |
| Based-on-patch-by: Konrad Wilk <konrad.wilk@oracle.com> |
| Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com> |
| Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com> |
| Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/xen/xen-acpi-processor.c | 34 ++++++++++++++++++++++++++-------- |
| 1 file changed, 26 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/xen/xen-acpi-processor.c |
| +++ b/drivers/xen/xen-acpi-processor.c |
| @@ -27,10 +27,10 @@ |
| #include <linux/init.h> |
| #include <linux/module.h> |
| #include <linux/types.h> |
| +#include <linux/syscore_ops.h> |
| #include <linux/acpi.h> |
| #include <acpi/processor.h> |
| #include <xen/xen.h> |
| -#include <xen/xen-ops.h> |
| #include <xen/interface/platform.h> |
| #include <asm/xen/hypercall.h> |
| |
| @@ -466,15 +466,33 @@ static int xen_upload_processor_pm_data( |
| return rc; |
| } |
| |
| -static int xen_acpi_processor_resume(struct notifier_block *nb, |
| - unsigned long action, void *data) |
| +static void xen_acpi_processor_resume_worker(struct work_struct *dummy) |
| { |
| + int rc; |
| + |
| bitmap_zero(acpi_ids_done, nr_acpi_bits); |
| - return xen_upload_processor_pm_data(); |
| + |
| + rc = xen_upload_processor_pm_data(); |
| + if (rc != 0) |
| + pr_info("ACPI data upload failed, error = %d\n", rc); |
| +} |
| + |
| +static void xen_acpi_processor_resume(void) |
| +{ |
| + static DECLARE_WORK(wq, xen_acpi_processor_resume_worker); |
| + |
| + /* |
| + * xen_upload_processor_pm_data() calls non-atomic code. |
| + * However, the context for xen_acpi_processor_resume is syscore |
| + * with only the boot CPU online and in an atomic context. |
| + * |
| + * So defer the upload for some point safer. |
| + */ |
| + schedule_work(&wq); |
| } |
| |
| -struct notifier_block xen_acpi_processor_resume_nb = { |
| - .notifier_call = xen_acpi_processor_resume, |
| +static struct syscore_ops xap_syscore_ops = { |
| + .resume = xen_acpi_processor_resume, |
| }; |
| |
| static int __init xen_acpi_processor_init(void) |
| @@ -527,7 +545,7 @@ static int __init xen_acpi_processor_ini |
| if (rc) |
| goto err_unregister; |
| |
| - xen_resume_notifier_register(&xen_acpi_processor_resume_nb); |
| + register_syscore_ops(&xap_syscore_ops); |
| |
| return 0; |
| err_unregister: |
| @@ -546,7 +564,7 @@ static void __exit xen_acpi_processor_ex |
| { |
| int i; |
| |
| - xen_resume_notifier_unregister(&xen_acpi_processor_resume_nb); |
| + unregister_syscore_ops(&xap_syscore_ops); |
| kfree(acpi_ids_done); |
| kfree(acpi_id_present); |
| kfree(acpi_id_cst_present); |