3737#include <linux/uaccess.h>
3838#include <linux/static_call.h>
3939#include <linux/amd-pstate.h>
40+ #include <linux/topology.h>
4041
4142#include <acpi/processor.h>
4243#include <acpi/cppc_acpi.h>
4950
5051#define AMD_PSTATE_TRANSITION_LATENCY 20000
5152#define AMD_PSTATE_TRANSITION_DELAY 1000
53+ #define AMD_PSTATE_PREFCORE_THRESHOLD 166
5254
5355/*
5456 * TODO: We need more time to fine tune processors with shared memory solution
@@ -64,6 +66,7 @@ static struct cpufreq_driver amd_pstate_driver;
6466static struct cpufreq_driver amd_pstate_epp_driver ;
6567static int cppc_state = AMD_PSTATE_UNDEFINED ;
6668static bool cppc_enabled ;
69+ static bool amd_pstate_prefcore = true;
6770
6871/*
6972 * AMD Energy Preference Performance (EPP)
@@ -297,13 +300,14 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
297300 if (ret )
298301 return ret ;
299302
300- /*
301- * TODO: Introduce AMD specific power feature.
302- *
303- * CPPC entry doesn't indicate the highest performance in some ASICs .
303+ /* For platforms that do not support the preferred core feature, the
304+ * highest_pef may be configured with 166 or 255, to avoid max frequency
305+ * calculated wrongly. we take the AMD_CPPC_HIGHEST_PERF(cap1) value as
306+ * the default max perf .
304307 */
305- highest_perf = amd_get_highest_perf ();
306- if (highest_perf > AMD_CPPC_HIGHEST_PERF (cap1 ))
308+ if (cpudata -> hw_prefcore )
309+ highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD ;
310+ else
307311 highest_perf = AMD_CPPC_HIGHEST_PERF (cap1 );
308312
309313 WRITE_ONCE (cpudata -> highest_perf , highest_perf );
@@ -324,8 +328,9 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
324328 if (ret )
325329 return ret ;
326330
327- highest_perf = amd_get_highest_perf ();
328- if (highest_perf > cppc_perf .highest_perf )
331+ if (cpudata -> hw_prefcore )
332+ highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD ;
333+ else
329334 highest_perf = cppc_perf .highest_perf ;
330335
331336 WRITE_ONCE (cpudata -> highest_perf , highest_perf );
@@ -706,6 +711,80 @@ static void amd_perf_ctl_reset(unsigned int cpu)
706711 wrmsrl_on_cpu (cpu , MSR_AMD_PERF_CTL , 0 );
707712}
708713
714+ /*
715+ * Set amd-pstate preferred core enable can't be done directly from cpufreq callbacks
716+ * due to locking, so queue the work for later.
717+ */
718+ static void amd_pstste_sched_prefcore_workfn (struct work_struct * work )
719+ {
720+ sched_set_itmt_support ();
721+ }
722+ static DECLARE_WORK (sched_prefcore_work , amd_pstste_sched_prefcore_workfn ) ;
723+
724+ /*
725+ * Get the highest performance register value.
726+ * @cpu: CPU from which to get highest performance.
727+ * @highest_perf: Return address.
728+ *
729+ * Return: 0 for success, -EIO otherwise.
730+ */
731+ static int amd_pstate_get_highest_perf (int cpu , u32 * highest_perf )
732+ {
733+ int ret ;
734+
735+ if (boot_cpu_has (X86_FEATURE_CPPC )) {
736+ u64 cap1 ;
737+
738+ ret = rdmsrl_safe_on_cpu (cpu , MSR_AMD_CPPC_CAP1 , & cap1 );
739+ if (ret )
740+ return ret ;
741+ WRITE_ONCE (* highest_perf , AMD_CPPC_HIGHEST_PERF (cap1 ));
742+ } else {
743+ u64 cppc_highest_perf ;
744+
745+ ret = cppc_get_highest_perf (cpu , & cppc_highest_perf );
746+ if (ret )
747+ return ret ;
748+ WRITE_ONCE (* highest_perf , cppc_highest_perf );
749+ }
750+
751+ return (ret );
752+ }
753+
754+ #define CPPC_MAX_PERF U8_MAX
755+
756+ static void amd_pstate_init_prefcore (struct amd_cpudata * cpudata )
757+ {
758+ int ret , prio ;
759+ u32 highest_perf ;
760+
761+ ret = amd_pstate_get_highest_perf (cpudata -> cpu , & highest_perf );
762+ if (ret )
763+ return ;
764+
765+ cpudata -> hw_prefcore = true;
766+ /* check if CPPC preferred core feature is enabled*/
767+ if (highest_perf < CPPC_MAX_PERF )
768+ prio = (int )highest_perf ;
769+ else {
770+ pr_debug ("AMD CPPC preferred core is unsupported!\n" );
771+ cpudata -> hw_prefcore = false;
772+ return ;
773+ }
774+
775+ if (!amd_pstate_prefcore )
776+ return ;
777+
778+ /*
779+ * The priorities can be set regardless of whether or not
780+ * sched_set_itmt_support(true) has been called and it is valid to
781+ * update them at any time after it has been called.
782+ */
783+ sched_set_itmt_core_prio (prio , cpudata -> cpu );
784+
785+ schedule_work (& sched_prefcore_work );
786+ }
787+
709788static int amd_pstate_cpu_init (struct cpufreq_policy * policy )
710789{
711790 int min_freq , max_freq , nominal_freq , lowest_nonlinear_freq , ret ;
@@ -727,6 +806,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
727806
728807 cpudata -> cpu = policy -> cpu ;
729808
809+ amd_pstate_init_prefcore (cpudata );
810+
730811 ret = amd_pstate_init_perf (cpudata );
731812 if (ret )
732813 goto free_cpudata1 ;
@@ -877,6 +958,17 @@ static ssize_t show_amd_pstate_highest_perf(struct cpufreq_policy *policy,
877958 return sysfs_emit (buf , "%u\n" , perf );
878959}
879960
961+ static ssize_t show_amd_pstate_hw_prefcore (struct cpufreq_policy * policy ,
962+ char * buf )
963+ {
964+ bool hw_prefcore ;
965+ struct amd_cpudata * cpudata = policy -> driver_data ;
966+
967+ hw_prefcore = READ_ONCE (cpudata -> hw_prefcore );
968+
969+ return sysfs_emit (buf , "%s\n" , str_enabled_disabled (hw_prefcore ));
970+ }
971+
880972static ssize_t show_energy_performance_available_preferences (
881973 struct cpufreq_policy * policy , char * buf )
882974{
@@ -1074,32 +1166,43 @@ static ssize_t status_store(struct device *a, struct device_attribute *b,
10741166 return ret < 0 ? ret : count ;
10751167}
10761168
1169+ static ssize_t prefcore_show (struct device * dev ,
1170+ struct device_attribute * attr , char * buf )
1171+ {
1172+ return sysfs_emit (buf , "%s\n" , str_enabled_disabled (amd_pstate_prefcore ));
1173+ }
1174+
10771175cpufreq_freq_attr_ro (amd_pstate_max_freq );
10781176cpufreq_freq_attr_ro (amd_pstate_lowest_nonlinear_freq );
10791177
10801178cpufreq_freq_attr_ro (amd_pstate_highest_perf );
1179+ cpufreq_freq_attr_ro (amd_pstate_hw_prefcore );
10811180cpufreq_freq_attr_rw (energy_performance_preference );
10821181cpufreq_freq_attr_ro (energy_performance_available_preferences );
10831182static DEVICE_ATTR_RW (status );
1183+ static DEVICE_ATTR_RO (prefcore );
10841184
10851185static struct freq_attr * amd_pstate_attr [] = {
10861186 & amd_pstate_max_freq ,
10871187 & amd_pstate_lowest_nonlinear_freq ,
10881188 & amd_pstate_highest_perf ,
1189+ & amd_pstate_hw_prefcore ,
10891190 NULL ,
10901191};
10911192
10921193static struct freq_attr * amd_pstate_epp_attr [] = {
10931194 & amd_pstate_max_freq ,
10941195 & amd_pstate_lowest_nonlinear_freq ,
10951196 & amd_pstate_highest_perf ,
1197+ & amd_pstate_hw_prefcore ,
10961198 & energy_performance_preference ,
10971199 & energy_performance_available_preferences ,
10981200 NULL ,
10991201};
11001202
11011203static struct attribute * pstate_global_attributes [] = {
11021204 & dev_attr_status .attr ,
1205+ & dev_attr_prefcore .attr ,
11031206 NULL
11041207};
11051208
@@ -1151,6 +1254,8 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
11511254 cpudata -> cpu = policy -> cpu ;
11521255 cpudata -> epp_policy = 0 ;
11531256
1257+ amd_pstate_init_prefcore (cpudata );
1258+
11541259 ret = amd_pstate_init_perf (cpudata );
11551260 if (ret )
11561261 goto free_cpudata1 ;
@@ -1567,7 +1672,17 @@ static int __init amd_pstate_param(char *str)
15671672
15681673 return amd_pstate_set_driver (mode_idx );
15691674}
1675+
1676+ static int __init amd_prefcore_param (char * str )
1677+ {
1678+ if (!strcmp (str , "disable" ))
1679+ amd_pstate_prefcore = false;
1680+
1681+ return 0 ;
1682+ }
1683+
15701684early_param ("amd_pstate" , amd_pstate_param );
1685+ early_param ("amd_prefcore" , amd_prefcore_param );
15711686
15721687MODULE_AUTHOR ("Huang Rui <ray.huang@amd.com>" );
15731688MODULE_DESCRIPTION ("AMD Processor P-state Frequency Driver" );
0 commit comments