diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 08:41:41 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 13:07:53 -0400 |
| commit | 816724e65c72a90a44fbad0ef0b59b186c85fa90 (patch) | |
| tree | 421fa29aedff988e392f92780637553e275d37a0 /drivers/acpi/processor_perflib.c | |
| parent | 70ac4385a13f78bc478f26d317511893741b05bd (diff) | |
| parent | d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts:
fs/nfs/inode.c
fs/super.c
Fix conflicts between patch 'NFS: Split fs/nfs/inode.c' and patch
'VFS: Permit filesystem to override root dentry on mount'
Diffstat (limited to 'drivers/acpi/processor_perflib.c')
| -rw-r--r-- | drivers/acpi/processor_perflib.c | 247 |
1 files changed, 236 insertions, 11 deletions
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index f36db22ce1ae..41aaaba74b19 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF | 34 | #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF |
| 35 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
| 36 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
| 37 | #include <linux/mutex.h> | ||
| 37 | 38 | ||
| 38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
| 39 | #endif | 40 | #endif |
| @@ -48,7 +49,7 @@ | |||
| 48 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 49 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 49 | ACPI_MODULE_NAME("acpi_processor") | 50 | ACPI_MODULE_NAME("acpi_processor") |
| 50 | 51 | ||
| 51 | static DECLARE_MUTEX(performance_sem); | 52 | static DEFINE_MUTEX(performance_mutex); |
| 52 | 53 | ||
| 53 | /* | 54 | /* |
| 54 | * _PPC support is implemented as a CPUfreq policy notifier: | 55 | * _PPC support is implemented as a CPUfreq policy notifier: |
| @@ -72,7 +73,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, | |||
| 72 | struct acpi_processor *pr; | 73 | struct acpi_processor *pr; |
| 73 | unsigned int ppc = 0; | 74 | unsigned int ppc = 0; |
| 74 | 75 | ||
| 75 | down(&performance_sem); | 76 | mutex_lock(&performance_mutex); |
| 76 | 77 | ||
| 77 | if (event != CPUFREQ_INCOMPATIBLE) | 78 | if (event != CPUFREQ_INCOMPATIBLE) |
| 78 | goto out; | 79 | goto out; |
| @@ -93,7 +94,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, | |||
| 93 | core_frequency * 1000); | 94 | core_frequency * 1000); |
| 94 | 95 | ||
| 95 | out: | 96 | out: |
| 96 | up(&performance_sem); | 97 | mutex_unlock(&performance_mutex); |
| 97 | 98 | ||
| 98 | return 0; | 99 | return 0; |
| 99 | } | 100 | } |
| @@ -553,6 +554,230 @@ static void acpi_cpufreq_remove_file(struct acpi_processor *pr) | |||
| 553 | } | 554 | } |
| 554 | #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ | 555 | #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ |
| 555 | 556 | ||
| 557 | static int acpi_processor_get_psd(struct acpi_processor *pr) | ||
| 558 | { | ||
| 559 | int result = 0; | ||
| 560 | acpi_status status = AE_OK; | ||
| 561 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
| 562 | struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"}; | ||
| 563 | struct acpi_buffer state = {0, NULL}; | ||
| 564 | union acpi_object *psd = NULL; | ||
| 565 | struct acpi_psd_package *pdomain; | ||
| 566 | |||
| 567 | status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer); | ||
| 568 | if (ACPI_FAILURE(status)) { | ||
| 569 | return -ENODEV; | ||
| 570 | } | ||
| 571 | |||
| 572 | psd = (union acpi_object *) buffer.pointer; | ||
| 573 | if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { | ||
| 574 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); | ||
| 575 | result = -EFAULT; | ||
| 576 | goto end; | ||
| 577 | } | ||
| 578 | |||
| 579 | if (psd->package.count != 1) { | ||
| 580 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); | ||
| 581 | result = -EFAULT; | ||
| 582 | goto end; | ||
| 583 | } | ||
| 584 | |||
| 585 | pdomain = &(pr->performance->domain_info); | ||
| 586 | |||
| 587 | state.length = sizeof(struct acpi_psd_package); | ||
| 588 | state.pointer = pdomain; | ||
| 589 | |||
| 590 | status = acpi_extract_package(&(psd->package.elements[0]), | ||
| 591 | &format, &state); | ||
| 592 | if (ACPI_FAILURE(status)) { | ||
| 593 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); | ||
| 594 | result = -EFAULT; | ||
| 595 | goto end; | ||
| 596 | } | ||
| 597 | |||
| 598 | if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) { | ||
| 599 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n")); | ||
| 600 | result = -EFAULT; | ||
| 601 | goto end; | ||
| 602 | } | ||
| 603 | |||
| 604 | if (pdomain->revision != ACPI_PSD_REV0_REVISION) { | ||
| 605 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n")); | ||
| 606 | result = -EFAULT; | ||
| 607 | goto end; | ||
| 608 | } | ||
| 609 | |||
| 610 | end: | ||
| 611 | acpi_os_free(buffer.pointer); | ||
| 612 | return result; | ||
| 613 | } | ||
| 614 | |||
| 615 | int acpi_processor_preregister_performance( | ||
| 616 | struct acpi_processor_performance **performance) | ||
| 617 | { | ||
| 618 | int count, count_target; | ||
| 619 | int retval = 0; | ||
| 620 | unsigned int i, j; | ||
| 621 | cpumask_t covered_cpus; | ||
| 622 | struct acpi_processor *pr; | ||
| 623 | struct acpi_psd_package *pdomain; | ||
| 624 | struct acpi_processor *match_pr; | ||
| 625 | struct acpi_psd_package *match_pdomain; | ||
| 626 | |||
| 627 | mutex_lock(&performance_mutex); | ||
| 628 | |||
| 629 | retval = 0; | ||
| 630 | |||
| 631 | /* Call _PSD for all CPUs */ | ||
| 632 | for_each_possible_cpu(i) { | ||
| 633 | pr = processors[i]; | ||
| 634 | if (!pr) { | ||
| 635 | /* Look only at processors in ACPI namespace */ | ||
| 636 | continue; | ||
| 637 | } | ||
| 638 | |||
| 639 | if (pr->performance) { | ||
| 640 | retval = -EBUSY; | ||
| 641 | continue; | ||
| 642 | } | ||
| 643 | |||
| 644 | if (!performance || !performance[i]) { | ||
| 645 | retval = -EINVAL; | ||
| 646 | continue; | ||
| 647 | } | ||
| 648 | |||
| 649 | pr->performance = performance[i]; | ||
| 650 | cpu_set(i, pr->performance->shared_cpu_map); | ||
| 651 | if (acpi_processor_get_psd(pr)) { | ||
| 652 | retval = -EINVAL; | ||
| 653 | continue; | ||
| 654 | } | ||
| 655 | } | ||
| 656 | if (retval) | ||
| 657 | goto err_ret; | ||
| 658 | |||
| 659 | /* | ||
| 660 | * Now that we have _PSD data from all CPUs, lets setup P-state | ||
| 661 | * domain info. | ||
| 662 | */ | ||
| 663 | for_each_possible_cpu(i) { | ||
| 664 | pr = processors[i]; | ||
| 665 | if (!pr) | ||
| 666 | continue; | ||
| 667 | |||
| 668 | /* Basic validity check for domain info */ | ||
| 669 | pdomain = &(pr->performance->domain_info); | ||
| 670 | if ((pdomain->revision != ACPI_PSD_REV0_REVISION) || | ||
| 671 | (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) { | ||
| 672 | retval = -EINVAL; | ||
| 673 | goto err_ret; | ||
| 674 | } | ||
| 675 | if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && | ||
| 676 | pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && | ||
| 677 | pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { | ||
| 678 | retval = -EINVAL; | ||
| 679 | goto err_ret; | ||
| 680 | } | ||
| 681 | } | ||
| 682 | |||
| 683 | cpus_clear(covered_cpus); | ||
| 684 | for_each_possible_cpu(i) { | ||
| 685 | pr = processors[i]; | ||
| 686 | if (!pr) | ||
| 687 | continue; | ||
| 688 | |||
| 689 | if (cpu_isset(i, covered_cpus)) | ||
| 690 | continue; | ||
| 691 | |||
| 692 | pdomain = &(pr->performance->domain_info); | ||
| 693 | cpu_set(i, pr->performance->shared_cpu_map); | ||
| 694 | cpu_set(i, covered_cpus); | ||
| 695 | if (pdomain->num_processors <= 1) | ||
| 696 | continue; | ||
| 697 | |||
| 698 | /* Validate the Domain info */ | ||
| 699 | count_target = pdomain->num_processors; | ||
| 700 | count = 1; | ||
| 701 | if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL || | ||
| 702 | pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) { | ||
| 703 | pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; | ||
| 704 | } else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) { | ||
| 705 | pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY; | ||
| 706 | } | ||
| 707 | |||
| 708 | for_each_possible_cpu(j) { | ||
| 709 | if (i == j) | ||
| 710 | continue; | ||
| 711 | |||
| 712 | match_pr = processors[j]; | ||
| 713 | if (!match_pr) | ||
| 714 | continue; | ||
| 715 | |||
| 716 | match_pdomain = &(match_pr->performance->domain_info); | ||
| 717 | if (match_pdomain->domain != pdomain->domain) | ||
| 718 | continue; | ||
| 719 | |||
| 720 | /* Here i and j are in the same domain */ | ||
| 721 | |||
| 722 | if (match_pdomain->num_processors != count_target) { | ||
| 723 | retval = -EINVAL; | ||
| 724 | goto err_ret; | ||
| 725 | } | ||
| 726 | |||
| 727 | if (pdomain->coord_type != match_pdomain->coord_type) { | ||
| 728 | retval = -EINVAL; | ||
| 729 | goto err_ret; | ||
| 730 | } | ||
| 731 | |||
| 732 | cpu_set(j, covered_cpus); | ||
| 733 | cpu_set(j, pr->performance->shared_cpu_map); | ||
| 734 | count++; | ||
| 735 | } | ||
| 736 | |||
| 737 | for_each_possible_cpu(j) { | ||
| 738 | if (i == j) | ||
| 739 | continue; | ||
| 740 | |||
| 741 | match_pr = processors[j]; | ||
| 742 | if (!match_pr) | ||
| 743 | continue; | ||
| 744 | |||
| 745 | match_pdomain = &(match_pr->performance->domain_info); | ||
| 746 | if (match_pdomain->domain != pdomain->domain) | ||
| 747 | continue; | ||
| 748 | |||
| 749 | match_pr->performance->shared_type = | ||
| 750 | pr->performance->shared_type; | ||
| 751 | match_pr->performance->shared_cpu_map = | ||
| 752 | pr->performance->shared_cpu_map; | ||
| 753 | } | ||
| 754 | } | ||
| 755 | |||
| 756 | err_ret: | ||
| 757 | if (retval) { | ||
| 758 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error while parsing _PSD domain information. Assuming no coordination\n")); | ||
| 759 | } | ||
| 760 | |||
| 761 | for_each_possible_cpu(i) { | ||
| 762 | pr = processors[i]; | ||
| 763 | if (!pr || !pr->performance) | ||
| 764 | continue; | ||
| 765 | |||
| 766 | /* Assume no coordination on any error parsing domain info */ | ||
| 767 | if (retval) { | ||
| 768 | cpus_clear(pr->performance->shared_cpu_map); | ||
| 769 | cpu_set(i, pr->performance->shared_cpu_map); | ||
| 770 | pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; | ||
| 771 | } | ||
| 772 | pr->performance = NULL; /* Will be set for real in register */ | ||
| 773 | } | ||
| 774 | |||
| 775 | mutex_unlock(&performance_mutex); | ||
| 776 | return retval; | ||
| 777 | } | ||
| 778 | EXPORT_SYMBOL(acpi_processor_preregister_performance); | ||
| 779 | |||
| 780 | |||
| 556 | int | 781 | int |
| 557 | acpi_processor_register_performance(struct acpi_processor_performance | 782 | acpi_processor_register_performance(struct acpi_processor_performance |
| 558 | *performance, unsigned int cpu) | 783 | *performance, unsigned int cpu) |
| @@ -564,16 +789,16 @@ acpi_processor_register_performance(struct acpi_processor_performance | |||
| 564 | if (!(acpi_processor_ppc_status & PPC_REGISTERED)) | 789 | if (!(acpi_processor_ppc_status & PPC_REGISTERED)) |
| 565 | return_VALUE(-EINVAL); | 790 | return_VALUE(-EINVAL); |
| 566 | 791 | ||
| 567 | down(&performance_sem); | 792 | mutex_lock(&performance_mutex); |
| 568 | 793 | ||
| 569 | pr = processors[cpu]; | 794 | pr = processors[cpu]; |
| 570 | if (!pr) { | 795 | if (!pr) { |
| 571 | up(&performance_sem); | 796 | mutex_unlock(&performance_mutex); |
| 572 | return_VALUE(-ENODEV); | 797 | return_VALUE(-ENODEV); |
| 573 | } | 798 | } |
| 574 | 799 | ||
| 575 | if (pr->performance) { | 800 | if (pr->performance) { |
| 576 | up(&performance_sem); | 801 | mutex_unlock(&performance_mutex); |
| 577 | return_VALUE(-EBUSY); | 802 | return_VALUE(-EBUSY); |
| 578 | } | 803 | } |
| 579 | 804 | ||
| @@ -583,13 +808,13 @@ acpi_processor_register_performance(struct acpi_processor_performance | |||
| 583 | 808 | ||
| 584 | if (acpi_processor_get_performance_info(pr)) { | 809 | if (acpi_processor_get_performance_info(pr)) { |
| 585 | pr->performance = NULL; | 810 | pr->performance = NULL; |
| 586 | up(&performance_sem); | 811 | mutex_unlock(&performance_mutex); |
| 587 | return_VALUE(-EIO); | 812 | return_VALUE(-EIO); |
| 588 | } | 813 | } |
| 589 | 814 | ||
| 590 | acpi_cpufreq_add_file(pr); | 815 | acpi_cpufreq_add_file(pr); |
| 591 | 816 | ||
| 592 | up(&performance_sem); | 817 | mutex_unlock(&performance_mutex); |
| 593 | return_VALUE(0); | 818 | return_VALUE(0); |
| 594 | } | 819 | } |
| 595 | 820 | ||
| @@ -603,11 +828,11 @@ acpi_processor_unregister_performance(struct acpi_processor_performance | |||
| 603 | 828 | ||
| 604 | ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance"); | 829 | ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance"); |
| 605 | 830 | ||
| 606 | down(&performance_sem); | 831 | mutex_lock(&performance_mutex); |
| 607 | 832 | ||
| 608 | pr = processors[cpu]; | 833 | pr = processors[cpu]; |
| 609 | if (!pr) { | 834 | if (!pr) { |
| 610 | up(&performance_sem); | 835 | mutex_unlock(&performance_mutex); |
| 611 | return_VOID; | 836 | return_VOID; |
| 612 | } | 837 | } |
| 613 | 838 | ||
| @@ -617,7 +842,7 @@ acpi_processor_unregister_performance(struct acpi_processor_performance | |||
| 617 | 842 | ||
| 618 | acpi_cpufreq_remove_file(pr); | 843 | acpi_cpufreq_remove_file(pr); |
| 619 | 844 | ||
| 620 | up(&performance_sem); | 845 | mutex_unlock(&performance_mutex); |
| 621 | 846 | ||
| 622 | return_VOID; | 847 | return_VOID; |
| 623 | } | 848 | } |
