@@ -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+
12231296static 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
12511326static 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 );
14101494static DEVICE_ATTR_RW (status );
14111495static 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-
14331497static 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
17021765static 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
18601922global_attr_free :
1861- cpufreq_unregister_driver ( current_pstate_driver );
1923+ amd_pstate_unregister_driver ( 0 );
18621924 return ret ;
18631925}
18641926device_initcall (amd_pstate_init );
0 commit comments