Skip to content

Commit b9f103d

Browse files
gautshensuperm1
authored andcommitted
amd-pstate: Add sysfs support for floor_freq and floor_count
When Floor Performance feature is supported by the platform, expose two sysfs files: * amd_pstate_floor_freq to allow userspace to request the floor frequency for each CPU. * amd_pstate_floor_count which advertises the number of distinct levels of floor frequencies supported on this platform. Reset the floor_perf to bios_floor_perf in the suspend, offline, and exit paths, and restore the value to the cached user-request floor_freq on the resume and online paths mirroring how bios_min_perf is handled for MSR_AMD_CPPC_REQ. Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
1 parent 9783828 commit b9f103d

2 files changed

Lines changed: 89 additions & 6 deletions

File tree

drivers/cpufreq/amd-pstate.c

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,10 @@ static int amd_pstate_init_floor_perf(struct cpufreq_policy *policy)
383383
return ret;
384384
}
385385

386-
cpudata->bios_floor_perf = floor_perf;
387386

387+
cpudata->bios_floor_perf = floor_perf;
388+
cpudata->floor_freq = perf_to_freq(cpudata->perf, cpudata->nominal_freq,
389+
floor_perf);
388390
return 0;
389391
}
390392

@@ -1288,6 +1290,46 @@ static ssize_t show_energy_performance_preference(
12881290
return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]);
12891291
}
12901292

1293+
static ssize_t store_amd_pstate_floor_freq(struct cpufreq_policy *policy,
1294+
const char *buf, size_t count)
1295+
{
1296+
struct amd_cpudata *cpudata = policy->driver_data;
1297+
union perf_cached perf = READ_ONCE(cpudata->perf);
1298+
unsigned int freq;
1299+
u8 floor_perf;
1300+
int ret;
1301+
1302+
ret = kstrtouint(buf, 0, &freq);
1303+
if (ret)
1304+
return ret;
1305+
1306+
if (freq < policy->cpuinfo.min_freq || freq > policy->max)
1307+
return -EINVAL;
1308+
1309+
floor_perf = freq_to_perf(perf, cpudata->nominal_freq, freq);
1310+
ret = amd_pstate_set_floor_perf(policy, floor_perf);
1311+
1312+
if (!ret)
1313+
cpudata->floor_freq = freq;
1314+
1315+
return ret ?: count;
1316+
}
1317+
1318+
static ssize_t show_amd_pstate_floor_freq(struct cpufreq_policy *policy, char *buf)
1319+
{
1320+
struct amd_cpudata *cpudata = policy->driver_data;
1321+
1322+
return sysfs_emit(buf, "%u\n", cpudata->floor_freq);
1323+
}
1324+
1325+
static ssize_t show_amd_pstate_floor_count(struct cpufreq_policy *policy, char *buf)
1326+
{
1327+
struct amd_cpudata *cpudata = policy->driver_data;
1328+
u8 count = cpudata->floor_perf_cnt;
1329+
1330+
return sysfs_emit(buf, "%u\n", count);
1331+
}
1332+
12911333
cpufreq_freq_attr_ro(amd_pstate_max_freq);
12921334
cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
12931335

@@ -1296,6 +1338,8 @@ cpufreq_freq_attr_ro(amd_pstate_prefcore_ranking);
12961338
cpufreq_freq_attr_ro(amd_pstate_hw_prefcore);
12971339
cpufreq_freq_attr_rw(energy_performance_preference);
12981340
cpufreq_freq_attr_ro(energy_performance_available_preferences);
1341+
cpufreq_freq_attr_rw(amd_pstate_floor_freq);
1342+
cpufreq_freq_attr_ro(amd_pstate_floor_count);
12991343

13001344
struct freq_attr_visibility {
13011345
struct freq_attr *attr;
@@ -1320,6 +1364,12 @@ static bool epp_visibility(void)
13201364
return cppc_state == AMD_PSTATE_ACTIVE;
13211365
}
13221366

1367+
/* Determines whether amd_pstate_floor_freq related attributes should be visible */
1368+
static bool floor_freq_visibility(void)
1369+
{
1370+
return cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO);
1371+
}
1372+
13231373
static struct freq_attr_visibility amd_pstate_attr_visibility[] = {
13241374
{&amd_pstate_max_freq, always_visible},
13251375
{&amd_pstate_lowest_nonlinear_freq, always_visible},
@@ -1328,6 +1378,8 @@ static struct freq_attr_visibility amd_pstate_attr_visibility[] = {
13281378
{&amd_pstate_hw_prefcore, prefcore_visibility},
13291379
{&energy_performance_preference, epp_visibility},
13301380
{&energy_performance_available_preferences, epp_visibility},
1381+
{&amd_pstate_floor_freq, floor_freq_visibility},
1382+
{&amd_pstate_floor_count, floor_freq_visibility},
13311383
};
13321384

13331385
static struct freq_attr **get_freq_attrs(void)
@@ -1748,24 +1800,39 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
17481800

17491801
static int amd_pstate_cpu_online(struct cpufreq_policy *policy)
17501802
{
1751-
return amd_pstate_cppc_enable(policy);
1803+
struct amd_cpudata *cpudata = policy->driver_data;
1804+
union perf_cached perf = READ_ONCE(cpudata->perf);
1805+
u8 cached_floor_perf;
1806+
int ret;
1807+
1808+
ret = amd_pstate_cppc_enable(policy);
1809+
if (ret)
1810+
return ret;
1811+
1812+
cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq);
1813+
return amd_pstate_set_floor_perf(policy, cached_floor_perf);
17521814
}
17531815

17541816
static int amd_pstate_cpu_offline(struct cpufreq_policy *policy)
17551817
{
17561818
struct amd_cpudata *cpudata = policy->driver_data;
17571819
union perf_cached perf = READ_ONCE(cpudata->perf);
1820+
int ret;
17581821

17591822
/*
17601823
* Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified
17611824
* min_perf value across kexec reboots. If this CPU is just onlined normally after this, the
17621825
* limits, epp and desired perf will get reset to the cached values in cpudata struct
17631826
*/
1764-
return amd_pstate_update_perf(policy, perf.bios_min_perf,
1827+
ret = amd_pstate_update_perf(policy, perf.bios_min_perf,
17651828
FIELD_GET(AMD_CPPC_DES_PERF_MASK, cpudata->cppc_req_cached),
17661829
FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached),
17671830
FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached),
17681831
false);
1832+
if (ret)
1833+
return ret;
1834+
1835+
return amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf);
17691836
}
17701837

17711838
static int amd_pstate_suspend(struct cpufreq_policy *policy)
@@ -1787,6 +1854,10 @@ static int amd_pstate_suspend(struct cpufreq_policy *policy)
17871854
if (ret)
17881855
return ret;
17891856

1857+
ret = amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf);
1858+
if (ret)
1859+
return ret;
1860+
17901861
/* set this flag to avoid setting core offline*/
17911862
cpudata->suspended = true;
17921863

@@ -1798,15 +1869,24 @@ static int amd_pstate_resume(struct cpufreq_policy *policy)
17981869
struct amd_cpudata *cpudata = policy->driver_data;
17991870
union perf_cached perf = READ_ONCE(cpudata->perf);
18001871
int cur_perf = freq_to_perf(perf, cpudata->nominal_freq, policy->cur);
1872+
u8 cached_floor_perf;
1873+
int ret;
18011874

18021875
/* Set CPPC_REQ to last sane value until the governor updates it */
1803-
return amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf,
1804-
0U, false);
1876+
ret = amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf,
1877+
0U, false);
1878+
if (ret)
1879+
return ret;
1880+
1881+
cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq);
1882+
return amd_pstate_set_floor_perf(policy, cached_floor_perf);
18051883
}
18061884

18071885
static int amd_pstate_epp_resume(struct cpufreq_policy *policy)
18081886
{
18091887
struct amd_cpudata *cpudata = policy->driver_data;
1888+
union perf_cached perf = READ_ONCE(cpudata->perf);
1889+
u8 cached_floor_perf;
18101890

18111891
if (cpudata->suspended) {
18121892
int ret;
@@ -1819,7 +1899,8 @@ static int amd_pstate_epp_resume(struct cpufreq_policy *policy)
18191899
cpudata->suspended = false;
18201900
}
18211901

1822-
return 0;
1902+
cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq);
1903+
return amd_pstate_set_floor_perf(policy, cached_floor_perf);
18231904
}
18241905

18251906
static struct cpufreq_driver amd_pstate_driver = {

drivers/cpufreq/amd-pstate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct amd_aperf_mperf {
7474
* @max_limit_freq: Cached value of policy->max (in khz)
7575
* @nominal_freq: the frequency (in khz) that mapped to nominal_perf
7676
* @lowest_nonlinear_freq: the frequency (in khz) that mapped to lowest_nonlinear_perf
77+
* @floor_freq: Cached value of the user requested floor_freq
7778
* @cur: Difference of Aperf/Mperf/tsc count between last and current sample
7879
* @prev: Last Aperf/Mperf/tsc count value read from register
7980
* @freq: current cpu frequency value (in khz)
@@ -103,6 +104,7 @@ struct amd_cpudata {
103104
u32 max_limit_freq;
104105
u32 nominal_freq;
105106
u32 lowest_nonlinear_freq;
107+
u32 floor_freq;
106108

107109
struct amd_aperf_mperf cur;
108110
struct amd_aperf_mperf prev;

0 commit comments

Comments
 (0)