diff options
Diffstat (limited to 'drivers/xen/xen-acpi-processor.c')
-rw-r--r-- | drivers/xen/xen-acpi-processor.c | 93 |
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'. */ |
52 | static unsigned long *acpi_ids_done; | 53 | static 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. */ |
54 | static unsigned long __initdata *acpi_id_present; | 55 | static 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 */ |
56 | static unsigned long __initdata *acpi_id_cst_present; | 57 | static unsigned long *acpi_id_cst_present; |
57 | 58 | ||
58 | static int push_cxx_to_hypervisor(struct acpi_processor *_pr) | 59 | static 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 | */ |
332 | static acpi_status __init | 333 | static acpi_status |
333 | read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv) | 334 | read_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 | } |
387 | static int __init check_acpi_ids(struct acpi_processor *pr_backup) | 388 | static 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 | ||
416 | upload: | ||
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 | } |
426 | static int __init check_prereq(void) | 429 | static 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 | ||
470 | static int __init xen_acpi_processor_init(void) | 473 | static 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 | |||
501 | static void xen_acpi_processor_resume(void) | ||
502 | { | ||
503 | bitmap_zero(acpi_ids_done, nr_acpi_bits); | ||
504 | xen_upload_processor_pm_data(); | ||
505 | } | ||
506 | |||
507 | static struct syscore_ops xap_syscore_ops = { | ||
508 | .resume = xen_acpi_processor_resume, | ||
509 | }; | ||
510 | |||
511 | static 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; |
536 | err_unregister: | 564 | err_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); |