Skip to content

Commit e67a5b6

Browse files
gautshensuperm1
authored andcommitted
amd-pstate: Make certain freq_attrs conditionally visible
Certain amd_pstate freq_attrs such as amd_pstate_hw_prefcore and amd_pstate_prefcore_ranking are enabled even when preferred core is not supported on the platform. Similarly there are common freq_attrs between the amd-pstate and the amd-pstate-epp drivers (eg: amd_pstate_max_freq, amd_pstate_lowest_nonlinear_freq, etc.) but are duplicated in two different freq_attr structs. Unify all the attributes in a single place and associate each of them with a visibility function that determines whether the attribute should be visible based on the underlying platform support and the current amd_pstate mode. 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 fcc25a2 commit e67a5b6

1 file changed

Lines changed: 93 additions & 31 deletions

File tree

drivers/cpufreq/amd-pstate.c

Lines changed: 93 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,12 +1220,87 @@ static ssize_t show_energy_performance_preference(
12201220
return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]);
12211221
}
12221222

1223+
cpufreq_freq_attr_ro(amd_pstate_max_freq);
1224+
cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
1225+
1226+
cpufreq_freq_attr_ro(amd_pstate_highest_perf);
1227+
cpufreq_freq_attr_ro(amd_pstate_prefcore_ranking);
1228+
cpufreq_freq_attr_ro(amd_pstate_hw_prefcore);
1229+
cpufreq_freq_attr_rw(energy_performance_preference);
1230+
cpufreq_freq_attr_ro(energy_performance_available_preferences);
1231+
1232+
struct freq_attr_visibility {
1233+
struct freq_attr *attr;
1234+
bool (*visibility_fn)(void);
1235+
};
1236+
1237+
/* For attributes which are always visible */
1238+
static bool always_visible(void)
1239+
{
1240+
return true;
1241+
}
1242+
1243+
/* Determines whether prefcore related attributes should be visible */
1244+
static bool prefcore_visibility(void)
1245+
{
1246+
return amd_pstate_prefcore;
1247+
}
1248+
1249+
/* Determines whether energy performance preference should be visible */
1250+
static bool epp_visibility(void)
1251+
{
1252+
return cppc_state == AMD_PSTATE_ACTIVE;
1253+
}
1254+
1255+
static struct freq_attr_visibility amd_pstate_attr_visibility[] = {
1256+
{&amd_pstate_max_freq, always_visible},
1257+
{&amd_pstate_lowest_nonlinear_freq, always_visible},
1258+
{&amd_pstate_highest_perf, always_visible},
1259+
{&amd_pstate_prefcore_ranking, prefcore_visibility},
1260+
{&amd_pstate_hw_prefcore, prefcore_visibility},
1261+
{&energy_performance_preference, epp_visibility},
1262+
{&energy_performance_available_preferences, epp_visibility},
1263+
};
1264+
1265+
static struct freq_attr **get_freq_attrs(void)
1266+
{
1267+
bool attr_visible[ARRAY_SIZE(amd_pstate_attr_visibility)];
1268+
struct freq_attr **attrs;
1269+
int i, j, count;
1270+
1271+
for (i = 0, count = 0; i < ARRAY_SIZE(amd_pstate_attr_visibility); i++) {
1272+
struct freq_attr_visibility *v = &amd_pstate_attr_visibility[i];
1273+
1274+
attr_visible[i] = v->visibility_fn();
1275+
if (attr_visible[i])
1276+
count++;
1277+
}
1278+
1279+
/* amd_pstate_{max_freq, lowest_nonlinear_freq, highest_perf} should always be visible */
1280+
BUG_ON(!count);
1281+
1282+
attrs = kcalloc(count + 1, sizeof(struct freq_attr *), GFP_KERNEL);
1283+
if (!attrs)
1284+
return ERR_PTR(-ENOMEM);
1285+
1286+
for (i = 0, j = 0; i < ARRAY_SIZE(amd_pstate_attr_visibility); i++) {
1287+
if (!attr_visible[i])
1288+
continue;
1289+
1290+
attrs[j++] = amd_pstate_attr_visibility[i].attr;
1291+
}
1292+
1293+
return attrs;
1294+
}
1295+
12231296
static void amd_pstate_driver_cleanup(void)
12241297
{
12251298
if (amd_pstate_prefcore)
12261299
sched_clear_itmt_support();
12271300

12281301
cppc_state = AMD_PSTATE_DISABLE;
1302+
kfree(current_pstate_driver->attr);
1303+
current_pstate_driver->attr = NULL;
12291304
current_pstate_driver = NULL;
12301305
}
12311306

@@ -1250,6 +1325,7 @@ static int amd_pstate_set_driver(int mode_idx)
12501325

12511326
static int amd_pstate_register_driver(int mode)
12521327
{
1328+
struct freq_attr **attr = NULL;
12531329
int ret;
12541330

12551331
ret = amd_pstate_set_driver(mode);
@@ -1258,6 +1334,22 @@ static int amd_pstate_register_driver(int mode)
12581334

12591335
cppc_state = mode;
12601336

1337+
/*
1338+
* Note: It is important to compute the attrs _after_
1339+
* re-initializing the cppc_state. Some attributes become
1340+
* visible only when cppc_state is AMD_PSTATE_ACTIVE.
1341+
*/
1342+
attr = get_freq_attrs();
1343+
if (IS_ERR(attr)) {
1344+
ret = (int) PTR_ERR(attr);
1345+
pr_err("Couldn't compute freq_attrs for current mode %s [%d]\n",
1346+
amd_pstate_get_mode_string(cppc_state), ret);
1347+
amd_pstate_driver_cleanup();
1348+
return ret;
1349+
}
1350+
1351+
current_pstate_driver->attr = attr;
1352+
12611353
/* at least one CPU supports CPB */
12621354
current_pstate_driver->boost_enabled = cpu_feature_enabled(X86_FEATURE_CPB);
12631355

@@ -1399,37 +1491,9 @@ static ssize_t prefcore_show(struct device *dev,
13991491
return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore));
14001492
}
14011493

1402-
cpufreq_freq_attr_ro(amd_pstate_max_freq);
1403-
cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
1404-
1405-
cpufreq_freq_attr_ro(amd_pstate_highest_perf);
1406-
cpufreq_freq_attr_ro(amd_pstate_prefcore_ranking);
1407-
cpufreq_freq_attr_ro(amd_pstate_hw_prefcore);
1408-
cpufreq_freq_attr_rw(energy_performance_preference);
1409-
cpufreq_freq_attr_ro(energy_performance_available_preferences);
14101494
static DEVICE_ATTR_RW(status);
14111495
static DEVICE_ATTR_RO(prefcore);
14121496

1413-
static struct freq_attr *amd_pstate_attr[] = {
1414-
&amd_pstate_max_freq,
1415-
&amd_pstate_lowest_nonlinear_freq,
1416-
&amd_pstate_highest_perf,
1417-
&amd_pstate_prefcore_ranking,
1418-
&amd_pstate_hw_prefcore,
1419-
NULL,
1420-
};
1421-
1422-
static struct freq_attr *amd_pstate_epp_attr[] = {
1423-
&amd_pstate_max_freq,
1424-
&amd_pstate_lowest_nonlinear_freq,
1425-
&amd_pstate_highest_perf,
1426-
&amd_pstate_prefcore_ranking,
1427-
&amd_pstate_hw_prefcore,
1428-
&energy_performance_preference,
1429-
&energy_performance_available_preferences,
1430-
NULL,
1431-
};
1432-
14331497
static struct attribute *pstate_global_attributes[] = {
14341498
&dev_attr_status.attr,
14351499
&dev_attr_prefcore.attr,
@@ -1696,7 +1760,6 @@ static struct cpufreq_driver amd_pstate_driver = {
16961760
.set_boost = amd_pstate_set_boost,
16971761
.update_limits = amd_pstate_update_limits,
16981762
.name = "amd-pstate",
1699-
.attr = amd_pstate_attr,
17001763
};
17011764

17021765
static struct cpufreq_driver amd_pstate_epp_driver = {
@@ -1712,7 +1775,6 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
17121775
.update_limits = amd_pstate_update_limits,
17131776
.set_boost = amd_pstate_set_boost,
17141777
.name = "amd-pstate-epp",
1715-
.attr = amd_pstate_epp_attr,
17161778
};
17171779

17181780
/*
@@ -1858,7 +1920,7 @@ static int __init amd_pstate_init(void)
18581920
return ret;
18591921

18601922
global_attr_free:
1861-
cpufreq_unregister_driver(current_pstate_driver);
1923+
amd_pstate_unregister_driver(0);
18621924
return ret;
18631925
}
18641926
device_initcall(amd_pstate_init);

0 commit comments

Comments
 (0)