@@ -156,6 +156,9 @@ show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, highest_perf);
156
156
show_cppc_data (cppc_get_perf_caps , cppc_perf_caps , lowest_perf );
157
157
show_cppc_data (cppc_get_perf_caps , cppc_perf_caps , nominal_perf );
158
158
show_cppc_data (cppc_get_perf_caps , cppc_perf_caps , lowest_nonlinear_perf );
159
+ show_cppc_data (cppc_get_perf_caps , cppc_perf_caps , lowest_freq );
160
+ show_cppc_data (cppc_get_perf_caps , cppc_perf_caps , nominal_freq );
161
+
159
162
show_cppc_data (cppc_get_perf_ctrs , cppc_perf_fb_ctrs , reference_perf );
160
163
show_cppc_data (cppc_get_perf_ctrs , cppc_perf_fb_ctrs , wraparound_time );
161
164
@@ -183,6 +186,8 @@ static struct attribute *cppc_attrs[] = {
183
186
& lowest_perf .attr ,
184
187
& lowest_nonlinear_perf .attr ,
185
188
& nominal_perf .attr ,
189
+ & nominal_freq .attr ,
190
+ & lowest_freq .attr ,
186
191
NULL
187
192
};
188
193
@@ -613,7 +618,6 @@ bool __weak cpc_ffh_supported(void)
613
618
return false;
614
619
}
615
620
616
-
617
621
/**
618
622
* pcc_data_alloc() - Allocate the pcc_data memory for pcc subspace
619
623
*
@@ -641,6 +645,34 @@ int pcc_data_alloc(int pcc_ss_id)
641
645
642
646
return 0 ;
643
647
}
648
+
649
+ /* Check if CPPC revision + num_ent combination is supported */
650
+ static bool is_cppc_supported (int revision , int num_ent )
651
+ {
652
+ int expected_num_ent ;
653
+
654
+ switch (revision ) {
655
+ case CPPC_V2_REV :
656
+ expected_num_ent = CPPC_V2_NUM_ENT ;
657
+ break ;
658
+ case CPPC_V3_REV :
659
+ expected_num_ent = CPPC_V3_NUM_ENT ;
660
+ break ;
661
+ default :
662
+ pr_debug ("Firmware exports unsupported CPPC revision: %d\n" ,
663
+ revision );
664
+ return false;
665
+ }
666
+
667
+ if (expected_num_ent != num_ent ) {
668
+ pr_debug ("Firmware exports %d entries. Expected: %d for CPPC rev:%d\n" ,
669
+ num_ent , expected_num_ent , revision );
670
+ return false;
671
+ }
672
+
673
+ return true;
674
+ }
675
+
644
676
/*
645
677
* An example CPC table looks like the following.
646
678
*
@@ -731,14 +763,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
731
763
cpc_obj -> type );
732
764
goto out_free ;
733
765
}
734
-
735
- /* Only support CPPCv2. Bail otherwise. */
736
- if (num_ent != CPPC_NUM_ENT ) {
737
- pr_debug ("Firmware exports %d entries. Expected: %d\n" ,
738
- num_ent , CPPC_NUM_ENT );
739
- goto out_free ;
740
- }
741
-
742
766
cpc_ptr -> num_entries = num_ent ;
743
767
744
768
/* Second entry should be revision. */
@@ -750,12 +774,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
750
774
cpc_obj -> type );
751
775
goto out_free ;
752
776
}
777
+ cpc_ptr -> version = cpc_rev ;
753
778
754
- if (cpc_rev != CPPC_REV ) {
755
- pr_debug ("Firmware exports revision:%d. Expected:%d\n" ,
756
- cpc_rev , CPPC_REV );
779
+ if (!is_cppc_supported (cpc_rev , num_ent ))
757
780
goto out_free ;
758
- }
759
781
760
782
/* Iterate through remaining entries in _CPC */
761
783
for (i = 2 ; i < num_ent ; i ++ ) {
@@ -808,6 +830,18 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
808
830
}
809
831
}
810
832
per_cpu (cpu_pcc_subspace_idx , pr -> id ) = pcc_subspace_id ;
833
+
834
+ /*
835
+ * Initialize the remaining cpc_regs as unsupported.
836
+ * Example: In case FW exposes CPPC v2, the below loop will initialize
837
+ * LOWEST_FREQ and NOMINAL_FREQ regs as unsupported
838
+ */
839
+ for (i = num_ent - 2 ; i < MAX_CPC_REG_ENT ; i ++ ) {
840
+ cpc_ptr -> cpc_regs [i ].type = ACPI_TYPE_INTEGER ;
841
+ cpc_ptr -> cpc_regs [i ].cpc_entry .int_value = 0 ;
842
+ }
843
+
844
+
811
845
/* Store CPU Logical ID */
812
846
cpc_ptr -> cpu_id = pr -> id ;
813
847
@@ -1037,8 +1071,9 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
1037
1071
{
1038
1072
struct cpc_desc * cpc_desc = per_cpu (cpc_desc_ptr , cpunum );
1039
1073
struct cpc_register_resource * highest_reg , * lowest_reg ,
1040
- * lowest_non_linear_reg , * nominal_reg ;
1041
- u64 high , low , nom , min_nonlinear ;
1074
+ * lowest_non_linear_reg , * nominal_reg ,
1075
+ * low_freq_reg = NULL , * nom_freq_reg = NULL ;
1076
+ u64 high , low , nom , min_nonlinear , low_f = 0 , nom_f = 0 ;
1042
1077
int pcc_ss_id = per_cpu (cpu_pcc_subspace_idx , cpunum );
1043
1078
struct cppc_pcc_data * pcc_ss_data ;
1044
1079
int ret = 0 , regs_in_pcc = 0 ;
@@ -1053,10 +1088,13 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
1053
1088
lowest_reg = & cpc_desc -> cpc_regs [LOWEST_PERF ];
1054
1089
lowest_non_linear_reg = & cpc_desc -> cpc_regs [LOW_NON_LINEAR_PERF ];
1055
1090
nominal_reg = & cpc_desc -> cpc_regs [NOMINAL_PERF ];
1091
+ low_freq_reg = & cpc_desc -> cpc_regs [LOWEST_FREQ ];
1092
+ nom_freq_reg = & cpc_desc -> cpc_regs [NOMINAL_FREQ ];
1056
1093
1057
1094
/* Are any of the regs PCC ?*/
1058
1095
if (CPC_IN_PCC (highest_reg ) || CPC_IN_PCC (lowest_reg ) ||
1059
- CPC_IN_PCC (lowest_non_linear_reg ) || CPC_IN_PCC (nominal_reg )) {
1096
+ CPC_IN_PCC (lowest_non_linear_reg ) || CPC_IN_PCC (nominal_reg ) ||
1097
+ CPC_IN_PCC (low_freq_reg ) || CPC_IN_PCC (nom_freq_reg )) {
1060
1098
regs_in_pcc = 1 ;
1061
1099
down_write (& pcc_ss_data -> pcc_lock );
1062
1100
/* Ring doorbell once to update PCC subspace */
@@ -1081,6 +1119,17 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
1081
1119
if (!high || !low || !nom || !min_nonlinear )
1082
1120
ret = - EFAULT ;
1083
1121
1122
+ /* Read optional lowest and nominal frequencies if present */
1123
+ if (CPC_SUPPORTED (low_freq_reg ))
1124
+ cpc_read (cpunum , low_freq_reg , & low_f );
1125
+
1126
+ if (CPC_SUPPORTED (nom_freq_reg ))
1127
+ cpc_read (cpunum , nom_freq_reg , & nom_f );
1128
+
1129
+ perf_caps -> lowest_freq = low_f ;
1130
+ perf_caps -> nominal_freq = nom_f ;
1131
+
1132
+
1084
1133
out_err :
1085
1134
if (regs_in_pcc )
1086
1135
up_write (& pcc_ss_data -> pcc_lock );
0 commit comments