99#include <asm/processor.h>
1010#include <asm/topology.h>
1111
12+ #define CPPC_HIGHEST_PERF_PREFCORE 166
13+
14+ enum amd_pref_core {
15+ AMD_PREF_CORE_UNKNOWN = 0 ,
16+ AMD_PREF_CORE_SUPPORTED ,
17+ AMD_PREF_CORE_UNSUPPORTED ,
18+ };
19+ static enum amd_pref_core amd_pref_core_detected ;
20+ static u64 boost_numerator ;
21+
1222/* Refer to drivers/acpi/cppc_acpi.c for the description of functions */
1323
1424bool cpc_supported_by_cpu (void )
@@ -146,6 +156,66 @@ int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf)
146156}
147157EXPORT_SYMBOL_GPL (amd_get_highest_perf );
148158
159+ /**
160+ * amd_detect_prefcore: Detect if CPUs in the system support preferred cores
161+ * @detected: Output variable for the result of the detection.
162+ *
163+ * Determine whether CPUs in the system support preferred cores. On systems
164+ * that support preferred cores, different highest perf values will be found
165+ * on different cores. On other systems, the highest perf value will be the
166+ * same on all cores.
167+ *
168+ * The result of the detection will be stored in the 'detected' parameter.
169+ *
170+ * Return: 0 for success, negative error code otherwise
171+ */
172+ int amd_detect_prefcore (bool * detected )
173+ {
174+ int cpu , count = 0 ;
175+ u64 highest_perf [2 ] = {0 };
176+
177+ if (WARN_ON (!detected ))
178+ return - EINVAL ;
179+
180+ switch (amd_pref_core_detected ) {
181+ case AMD_PREF_CORE_SUPPORTED :
182+ * detected = true;
183+ return 0 ;
184+ case AMD_PREF_CORE_UNSUPPORTED :
185+ * detected = false;
186+ return 0 ;
187+ default :
188+ break ;
189+ }
190+
191+ for_each_present_cpu (cpu ) {
192+ u32 tmp ;
193+ int ret ;
194+
195+ ret = amd_get_highest_perf (cpu , & tmp );
196+ if (ret )
197+ return ret ;
198+
199+ if (!count || (count == 1 && tmp != highest_perf [0 ]))
200+ highest_perf [count ++ ] = tmp ;
201+
202+ if (count == 2 )
203+ break ;
204+ }
205+
206+ * detected = (count == 2 );
207+ boost_numerator = highest_perf [0 ];
208+
209+ amd_pref_core_detected = * detected ? AMD_PREF_CORE_SUPPORTED :
210+ AMD_PREF_CORE_UNSUPPORTED ;
211+
212+ pr_debug ("AMD CPPC preferred core is %ssupported (highest perf: 0x%llx)\n" ,
213+ * detected ? "" : "un" , highest_perf [0 ]);
214+
215+ return 0 ;
216+ }
217+ EXPORT_SYMBOL_GPL (amd_detect_prefcore );
218+
149219/**
150220 * amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation
151221 * @cpu: CPU to get numerator for.
@@ -155,24 +225,27 @@ EXPORT_SYMBOL_GPL(amd_get_highest_perf);
155225 * a CPU. On systems that support preferred cores, this will be a hardcoded
156226 * value. On other systems this will the highest performance register value.
157227 *
228+ * If booting the system with amd-pstate enabled but preferred cores disabled then
229+ * the correct boost numerator will be returned to match hardware capabilities
230+ * even if the preferred cores scheduling hints are not enabled.
231+ *
158232 * Return: 0 for success, negative error code otherwise.
159233 */
160234int amd_get_boost_ratio_numerator (unsigned int cpu , u64 * numerator )
161235{
162- struct cpuinfo_x86 * c = & boot_cpu_data ;
236+ bool prefcore ;
237+ int ret ;
163238
164- if (c -> x86 == 0x17 && ((c -> x86_model >= 0x30 && c -> x86_model < 0x40 ) ||
165- (c -> x86_model >= 0x70 && c -> x86_model < 0x80 ))) {
166- * numerator = 166 ;
167- return 0 ;
168- }
239+ ret = amd_detect_prefcore (& prefcore );
240+ if (ret )
241+ return ret ;
169242
170- if ( c -> x86 == 0x19 && (( c -> x86_model >= 0x20 && c -> x86_model < 0x30 ) ||
171- ( c -> x86_model >= 0x40 && c -> x86_model < 0x70 )) ) {
172- * numerator = 166 ;
243+ /* without preferred cores, return the highest perf register value */
244+ if (! prefcore ) {
245+ * numerator = boost_numerator ;
173246 return 0 ;
174247 }
175- * numerator = 255 ;
248+ * numerator = CPPC_HIGHEST_PERF_PREFCORE ;
176249
177250 return 0 ;
178251}
0 commit comments