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 | } |