aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/xen-acpi-processor.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/xen-acpi-processor.c')
-rw-r--r--drivers/xen/xen-acpi-processor.c93
1 files changed, 62 insertions, 31 deletions
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 316df65163cf..8abd7d579037 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{
@@ -329,7 +330,7 @@ static unsigned int __init get_max_acpi_id(void)
329 * for_each_[present|online]_cpu macros which are banded to the virtual 330 * for_each_[present|online]_cpu macros which are banded to the virtual
330 * CPU amount. 331 * CPU amount.
331 */ 332 */
332static acpi_status __init 333static acpi_status
333read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv) 334read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
334{ 335{
335 u32 acpi_id; 336 u32 acpi_id;
@@ -384,12 +385,16 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
384 385
385 return AE_OK; 386 return AE_OK;
386} 387}
387static int __init check_acpi_ids(struct acpi_processor *pr_backup) 388static int check_acpi_ids(struct acpi_processor *pr_backup)
388{ 389{
389 390
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)
@@ -500,38 +540,26 @@ static int __init xen_acpi_processor_init(void)
500 (void)acpi_processor_preregister_performance(acpi_perf_data); 540 (void)acpi_processor_preregister_performance(acpi_perf_data);
501 541
502 for_each_possible_cpu(i) { 542 for_each_possible_cpu(i) {
543 struct acpi_processor *pr;
503 struct acpi_processor_performance *perf; 544 struct acpi_processor_performance *perf;
504 545
546 pr = per_cpu(processors, i);
505 perf = per_cpu_ptr(acpi_perf_data, i); 547 perf = per_cpu_ptr(acpi_perf_data, i);
506 rc = acpi_processor_register_performance(perf, i); 548 if (!pr)
507 if (rc)
508 goto err_out;
509 }
510 rc = acpi_processor_notify_smm(THIS_MODULE);
511 if (rc)
512 goto err_unregister;
513
514 for_each_possible_cpu(i) {
515 struct acpi_processor *_pr;
516 _pr = per_cpu(processors, i /* APIC ID */);
517 if (!_pr)
518 continue; 549 continue;
519 550
520 if (!pr_backup) { 551 pr->performance = perf;
521 pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); 552 rc = acpi_processor_get_performance_info(pr);
522 if (pr_backup) 553 if (rc)
523 memcpy(pr_backup, _pr, sizeof(struct acpi_processor)); 554 goto err_out;
524 }
525 (void)upload_pm_data(_pr);
526 } 555 }
527 rc = check_acpi_ids(pr_backup);
528
529 kfree(pr_backup);
530 pr_backup = NULL;
531 556
557 rc = xen_upload_processor_pm_data();
532 if (rc) 558 if (rc)
533 goto err_unregister; 559 goto err_unregister;
534 560
561 register_syscore_ops(&xap_syscore_ops);
562
535 return 0; 563 return 0;
536err_unregister: 564err_unregister:
537 for_each_possible_cpu(i) { 565 for_each_possible_cpu(i) {
@@ -549,7 +577,10 @@ static void __exit xen_acpi_processor_exit(void)
549{ 577{
550 int i; 578 int i;
551 579
580 unregister_syscore_ops(&xap_syscore_ops);
552 kfree(acpi_ids_done); 581 kfree(acpi_ids_done);
582 kfree(acpi_id_present);
583 kfree(acpi_id_cst_present);
553 for_each_possible_cpu(i) { 584 for_each_possible_cpu(i) {
554 struct acpi_processor_performance *perf; 585 struct acpi_processor_performance *perf;
555 perf = per_cpu_ptr(acpi_perf_data, i); 586 perf = per_cpu_ptr(acpi_perf_data, i);