aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Guthro <benjamin.guthro@citrix.com>2013-04-17 09:18:49 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-04-17 10:43:56 -0400
commit3fac10145b766a2244422788f62dc35978613fd8 (patch)
treee5d3ced010bb1936599c7ea883996ba46ce0c6b2
parentb12abaa192c4340de50ddd86853b3583c255c449 (diff)
xen: Re-upload processor PM data to hypervisor after S3 resume (v2)
Upon resume, it was found that ACPI C-states were missing from non-boot CPUs. This change registers a syscore_ops handler for this case, and re-uploads the PM information to the hypervisor to properly reset the C-state on these processors. v2: v1 did not go through the check_acpi_ids() code-path, and missed some cases when xen was running with the dom0_max_vcpus= command line parameter. Signed-Off-By: Ben Guthro <benjamin.guthro@citrix.com> [v3: Ate some tabs, s/printk/pr_info/] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--drivers/xen/xen-acpi-processor.c78
1 files changed, 53 insertions, 25 deletions
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 90e34ac7e522..e2a53337725d 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -25,6 +25,7 @@
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/syscore_ops.h>
28#include <acpi/acpi_bus.h> 29#include <acpi/acpi_bus.h>
29#include <acpi/acpi_drivers.h> 30#include <acpi/acpi_drivers.h>
30#include <acpi/processor.h> 31#include <acpi/processor.h>
@@ -51,9 +52,9 @@ static DEFINE_MUTEX(acpi_ids_mutex);
51/* Which ACPI ID we have processed from 'struct acpi_processor'. */ 52/* Which ACPI ID we have processed from 'struct acpi_processor'. */
52static unsigned long *acpi_ids_done; 53static unsigned long *acpi_ids_done;
53/* Which ACPI ID exist in the SSDT/DSDT processor definitions. */ 54/* Which ACPI ID exist in the SSDT/DSDT processor definitions. */
54static unsigned long __initdata *acpi_id_present; 55static unsigned long *acpi_id_present;
55/* And if there is an _CST definition (or a PBLK) for the ACPI IDs */ 56/* And if there is an _CST definition (or a PBLK) for the ACPI IDs */
56static unsigned long __initdata *acpi_id_cst_present; 57static unsigned long *acpi_id_cst_present;
57 58
58static int push_cxx_to_hypervisor(struct acpi_processor *_pr) 59static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
59{ 60{
@@ -390,6 +391,10 @@ static int __init check_acpi_ids(struct acpi_processor *pr_backup)
390 if (!pr_backup) 391 if (!pr_backup)
391 return -ENODEV; 392 return -ENODEV;
392 393
394 if (acpi_id_present && acpi_id_cst_present)
395 /* OK, done this once .. skip to uploading */
396 goto upload;
397
393 /* All online CPUs have been processed at this stage. Now verify 398 /* All online CPUs have been processed at this stage. Now verify
394 * whether in fact "online CPUs" == physical CPUs. 399 * whether in fact "online CPUs" == physical CPUs.
395 */ 400 */
@@ -408,6 +413,7 @@ static int __init check_acpi_ids(struct acpi_processor *pr_backup)
408 read_acpi_id, NULL, NULL, NULL); 413 read_acpi_id, NULL, NULL, NULL);
409 acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL); 414 acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL);
410 415
416upload:
411 if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) { 417 if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) {
412 unsigned int i; 418 unsigned int i;
413 for_each_set_bit(i, acpi_id_present, nr_acpi_bits) { 419 for_each_set_bit(i, acpi_id_present, nr_acpi_bits) {
@@ -417,10 +423,7 @@ static int __init check_acpi_ids(struct acpi_processor *pr_backup)
417 (void)upload_pm_data(pr_backup); 423 (void)upload_pm_data(pr_backup);
418 } 424 }
419 } 425 }
420 kfree(acpi_id_present); 426
421 acpi_id_present = NULL;
422 kfree(acpi_id_cst_present);
423 acpi_id_cst_present = NULL;
424 return 0; 427 return 0;
425} 428}
426static int __init check_prereq(void) 429static int __init check_prereq(void)
@@ -467,10 +470,47 @@ static void free_acpi_perf_data(void)
467 free_percpu(acpi_perf_data); 470 free_percpu(acpi_perf_data);
468} 471}
469 472
470static int __init xen_acpi_processor_init(void) 473static int xen_upload_processor_pm_data(void)
471{ 474{
472 struct acpi_processor *pr_backup = NULL; 475 struct acpi_processor *pr_backup = NULL;
473 unsigned int i; 476 unsigned int i;
477 int rc = 0;
478
479 pr_info(DRV_NAME "Uploading Xen processor PM info\n");
480
481 for_each_possible_cpu(i) {
482 struct acpi_processor *_pr;
483 _pr = per_cpu(processors, i /* APIC ID */);
484 if (!_pr)
485 continue;
486
487 if (!pr_backup) {
488 pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
489 if (pr_backup)
490 memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
491 }
492 (void)upload_pm_data(_pr);
493 }
494
495 rc = check_acpi_ids(pr_backup);
496 kfree(pr_backup);
497
498 return rc;
499}
500
501static void xen_acpi_processor_resume(void)
502{
503 bitmap_zero(acpi_ids_done, nr_acpi_bits);
504 xen_upload_processor_pm_data();
505}
506
507static struct syscore_ops xap_syscore_ops = {
508 .resume = xen_acpi_processor_resume,
509};
510
511static int __init xen_acpi_processor_init(void)
512{
513 unsigned int i;
474 int rc = check_prereq(); 514 int rc = check_prereq();
475 515
476 if (rc) 516 if (rc)
@@ -514,27 +554,12 @@ static int __init xen_acpi_processor_init(void)
514 goto err_out; 554 goto err_out;
515 } 555 }
516 556
517 for_each_possible_cpu(i) { 557 rc = xen_upload_processor_pm_data();
518 struct acpi_processor *_pr;
519 _pr = per_cpu(processors, i /* APIC ID */);
520 if (!_pr)
521 continue;
522
523 if (!pr_backup) {
524 pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
525 if (pr_backup)
526 memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
527 }
528 (void)upload_pm_data(_pr);
529 }
530 rc = check_acpi_ids(pr_backup);
531
532 kfree(pr_backup);
533 pr_backup = NULL;
534
535 if (rc) 558 if (rc)
536 goto err_unregister; 559 goto err_unregister;
537 560
561 register_syscore_ops(&xap_syscore_ops);
562
538 return 0; 563 return 0;
539err_unregister: 564err_unregister:
540 for_each_possible_cpu(i) { 565 for_each_possible_cpu(i) {
@@ -552,7 +577,10 @@ static void __exit xen_acpi_processor_exit(void)
552{ 577{
553 int i; 578 int i;
554 579
580 unregister_syscore_ops(&xap_syscore_ops);
555 kfree(acpi_ids_done); 581 kfree(acpi_ids_done);
582 kfree(acpi_id_present);
583 kfree(acpi_id_cst_present);
556 for_each_possible_cpu(i) { 584 for_each_possible_cpu(i) {
557 struct acpi_processor_performance *perf; 585 struct acpi_processor_performance *perf;
558 perf = per_cpu_ptr(acpi_perf_data, i); 586 perf = per_cpu_ptr(acpi_perf_data, i);