aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_perflib.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-24 08:41:41 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-24 13:07:53 -0400
commit816724e65c72a90a44fbad0ef0b59b186c85fa90 (patch)
tree421fa29aedff988e392f92780637553e275d37a0 /drivers/acpi/processor_perflib.c
parent70ac4385a13f78bc478f26d317511893741b05bd (diff)
parentd384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (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.c247
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
49ACPI_MODULE_NAME("acpi_processor") 50ACPI_MODULE_NAME("acpi_processor")
50 51
51static DECLARE_MUTEX(performance_sem); 52static 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
557static 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
610end:
611 acpi_os_free(buffer.pointer);
612 return result;
613}
614
615int 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
756err_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}
778EXPORT_SYMBOL(acpi_processor_preregister_performance);
779
780
556int 781int
557acpi_processor_register_performance(struct acpi_processor_performance 782acpi_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}