2828#include <linux/kernel.h>
2929#include <linux/module.h>
3030#include <linux/moduleparam.h>
31+ #include <linux/mm.h>
3132#include <linux/fs.h>
3233#include <linux/cleanup.h>
3334
@@ -41,6 +42,7 @@ static char *test_list;
4142module_param (test_list , charp , 0444 );
4243MODULE_PARM_DESC (test_list ,
4344 "Comma-delimited list of tests to run (empty means run all tests)" );
45+ DEFINE_FREE (cleanup_page , void * , if (_T ) free_page ((unsigned long )_T ))
4446
4547struct amd_pstate_ut_struct {
4648 const char * name ;
@@ -54,6 +56,7 @@ static int amd_pstate_ut_acpi_cpc_valid(u32 index);
5456static int amd_pstate_ut_check_enabled (u32 index );
5557static int amd_pstate_ut_check_perf (u32 index );
5658static int amd_pstate_ut_check_freq (u32 index );
59+ static int amd_pstate_ut_epp (u32 index );
5760static int amd_pstate_ut_check_driver (u32 index );
5861static int amd_pstate_ut_check_freq_attrs (u32 index );
5962
@@ -62,6 +65,7 @@ static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = {
6265 {"amd_pstate_ut_check_enabled" , amd_pstate_ut_check_enabled },
6366 {"amd_pstate_ut_check_perf" , amd_pstate_ut_check_perf },
6467 {"amd_pstate_ut_check_freq" , amd_pstate_ut_check_freq },
68+ {"amd_pstate_ut_epp" , amd_pstate_ut_epp },
6569 {"amd_pstate_ut_check_driver" , amd_pstate_ut_check_driver },
6670 {"amd_pstate_ut_check_freq_attrs" , amd_pstate_ut_check_freq_attrs },
6771};
@@ -268,6 +272,111 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode)
268272 return amd_pstate_update_status (mode_str , strlen (mode_str ));
269273}
270274
275+ static int amd_pstate_ut_epp (u32 index )
276+ {
277+ struct cpufreq_policy * policy __free (put_cpufreq_policy ) = NULL ;
278+ char * buf __free (cleanup_page ) = NULL ;
279+ static const char * const epp_strings [] = {
280+ "performance" ,
281+ "balance_performance" ,
282+ "balance_power" ,
283+ "power" ,
284+ };
285+ struct amd_cpudata * cpudata ;
286+ enum amd_pstate_mode orig_mode ;
287+ bool orig_dynamic_epp ;
288+ int ret , cpu = 0 ;
289+ int i ;
290+ u16 epp ;
291+
292+ policy = cpufreq_cpu_get (cpu );
293+ if (!policy )
294+ return - ENODEV ;
295+
296+ cpudata = policy -> driver_data ;
297+ orig_mode = amd_pstate_get_status ();
298+ orig_dynamic_epp = cpudata -> dynamic_epp ;
299+
300+ /* disable dynamic EPP before running test */
301+ if (cpudata -> dynamic_epp ) {
302+ pr_debug ("Dynamic EPP is enabled, disabling it\n" );
303+ amd_pstate_clear_dynamic_epp (policy );
304+ }
305+
306+ buf = (char * )__get_free_page (GFP_KERNEL );
307+ if (!buf )
308+ return - ENOMEM ;
309+
310+ ret = amd_pstate_set_mode (AMD_PSTATE_ACTIVE );
311+ if (ret )
312+ goto out ;
313+
314+ for (epp = 0 ; epp <= U8_MAX ; epp ++ ) {
315+ u8 val ;
316+
317+ /* write all EPP values */
318+ memset (buf , 0 , PAGE_SIZE );
319+ snprintf (buf , PAGE_SIZE , "%d" , epp );
320+ ret = store_energy_performance_preference (policy , buf , strlen (buf ));
321+ if (ret < 0 )
322+ goto out ;
323+
324+ /* check if the EPP value reads back correctly for raw numbers */
325+ memset (buf , 0 , PAGE_SIZE );
326+ ret = show_energy_performance_preference (policy , buf );
327+ if (ret < 0 )
328+ goto out ;
329+ strreplace (buf , '\n' , '\0' );
330+ ret = kstrtou8 (buf , 0 , & val );
331+ if (!ret && epp != val ) {
332+ pr_err ("Raw EPP value mismatch: %d != %d\n" , epp , val );
333+ ret = - EINVAL ;
334+ goto out ;
335+ }
336+ }
337+
338+ for (i = 0 ; i < ARRAY_SIZE (epp_strings ); i ++ ) {
339+ memset (buf , 0 , PAGE_SIZE );
340+ snprintf (buf , PAGE_SIZE , "%s" , epp_strings [i ]);
341+ ret = store_energy_performance_preference (policy , buf , strlen (buf ));
342+ if (ret < 0 )
343+ goto out ;
344+
345+ memset (buf , 0 , PAGE_SIZE );
346+ ret = show_energy_performance_preference (policy , buf );
347+ if (ret < 0 )
348+ goto out ;
349+ strreplace (buf , '\n' , '\0' );
350+
351+ if (strcmp (buf , epp_strings [i ])) {
352+ pr_err ("String EPP value mismatch: %s != %s\n" , buf , epp_strings [i ]);
353+ ret = - EINVAL ;
354+ goto out ;
355+ }
356+ }
357+
358+ ret = 0 ;
359+
360+ out :
361+ if (orig_dynamic_epp ) {
362+ int ret2 ;
363+
364+ ret2 = amd_pstate_set_mode (AMD_PSTATE_DISABLE );
365+ if (!ret && ret2 )
366+ ret = ret2 ;
367+ }
368+
369+ if (orig_mode != amd_pstate_get_status ()) {
370+ int ret2 ;
371+
372+ ret2 = amd_pstate_set_mode (orig_mode );
373+ if (!ret && ret2 )
374+ ret = ret2 ;
375+ }
376+
377+ return ret ;
378+ }
379+
271380static int amd_pstate_ut_check_driver (u32 index )
272381{
273382 enum amd_pstate_mode mode1 , mode2 = AMD_PSTATE_DISABLE ;
0 commit comments