test/power: round CPU frequency to check
[dpdk.git] / app / test / test_power_cpufreq.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <unistd.h>
8 #include <limits.h>
9 #include <string.h>
10 #include <inttypes.h>
11 #include <rte_cycles.h>
12
13 #include "test.h"
14
15 #ifndef RTE_LIB_POWER
16
17 static int
18 test_power_cpufreq(void)
19 {
20         printf("Power management library not supported, skipping test\n");
21         return TEST_SKIPPED;
22 }
23
24 static int
25 test_power_caps(void)
26 {
27         printf("Power management library not supported, skipping test\n");
28         return TEST_SKIPPED;
29 }
30
31 #else
32 #include <rte_power.h>
33
34 #define TEST_POWER_LCORE_ID      2U
35 #define TEST_POWER_LCORE_INVALID ((unsigned)RTE_MAX_LCORE)
36 #define TEST_POWER_FREQS_NUM_MAX ((unsigned)RTE_MAX_LCORE_FREQS)
37
38 /* macros used for rounding frequency to nearest 100000 */
39 #define TEST_FREQ_ROUNDING_DELTA 50000
40 #define TEST_ROUND_FREQ_TO_N_100000 100000
41
42 #define TEST_POWER_SYSFILE_CUR_FREQ \
43         "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_cur_freq"
44
45 static uint32_t total_freq_num;
46 static uint32_t freqs[TEST_POWER_FREQS_NUM_MAX];
47
48 static int
49 check_cur_freq(unsigned lcore_id, uint32_t idx)
50 {
51 #define TEST_POWER_CONVERT_TO_DECIMAL 10
52 #define MAX_LOOP 100
53         FILE *f;
54         char fullpath[PATH_MAX];
55         char buf[BUFSIZ];
56         uint32_t cur_freq;
57         int ret = -1;
58         int i;
59
60         if (snprintf(fullpath, sizeof(fullpath),
61                 TEST_POWER_SYSFILE_CUR_FREQ, lcore_id) < 0) {
62                 return 0;
63         }
64         f = fopen(fullpath, "r");
65         if (f == NULL) {
66                 return 0;
67         }
68         for (i = 0; i < MAX_LOOP; i++) {
69                 fflush(f);
70                 if (fgets(buf, sizeof(buf), f) == NULL)
71                         goto fail_all;
72
73                 cur_freq = strtoul(buf, NULL, TEST_POWER_CONVERT_TO_DECIMAL);
74
75                 /* convert the frequency to nearest 100000 value
76                  * Ex: if cur_freq=1396789 then freq_conv=1400000
77                  * Ex: if cur_freq=800030 then freq_conv=800000
78                  */
79                 unsigned int freq_conv = 0;
80                 freq_conv = (cur_freq + TEST_FREQ_ROUNDING_DELTA)
81                                         / TEST_ROUND_FREQ_TO_N_100000;
82                 freq_conv = freq_conv * TEST_ROUND_FREQ_TO_N_100000;
83
84                 ret = (freqs[idx] == freq_conv ? 0 : -1);
85
86                 if (ret == 0)
87                         break;
88
89                 if (fseek(f, 0, SEEK_SET) < 0) {
90                         printf("Fail to set file position indicator to 0\n");
91                         goto fail_all;
92                 }
93
94                 /* wait for the value to be updated */
95                 rte_delay_ms(10);
96         }
97
98 fail_all:
99         fclose(f);
100
101         return ret;
102 }
103
104 /* Check rte_power_freqs() */
105 static int
106 check_power_freqs(void)
107 {
108         uint32_t ret;
109
110         total_freq_num = 0;
111         memset(freqs, 0, sizeof(freqs));
112
113         /* test with an invalid lcore id */
114         ret = rte_power_freqs(TEST_POWER_LCORE_INVALID, freqs,
115                                         TEST_POWER_FREQS_NUM_MAX);
116         if (ret > 0) {
117                 printf("Unexpectedly get available freqs successfully on "
118                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
119                 return -1;
120         }
121
122         /* test with NULL buffer to save available freqs */
123         ret = rte_power_freqs(TEST_POWER_LCORE_ID, NULL,
124                                 TEST_POWER_FREQS_NUM_MAX);
125         if (ret > 0) {
126                 printf("Unexpectedly get available freqs successfully with "
127                         "NULL buffer on lcore %u\n", TEST_POWER_LCORE_ID);
128                 return -1;
129         }
130
131         /* test of getting zero number of freqs */
132         ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs, 0);
133         if (ret > 0) {
134                 printf("Unexpectedly get available freqs successfully with "
135                         "zero buffer size on lcore %u\n", TEST_POWER_LCORE_ID);
136                 return -1;
137         }
138
139         /* test with all valid input parameters */
140         ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs,
141                                 TEST_POWER_FREQS_NUM_MAX);
142         if (ret == 0 || ret > TEST_POWER_FREQS_NUM_MAX) {
143                 printf("Fail to get available freqs on lcore %u\n",
144                                                 TEST_POWER_LCORE_ID);
145                 return -1;
146         }
147
148         /* Save the total number of available freqs */
149         total_freq_num = ret;
150
151         return 0;
152 }
153
154 /* Check rte_power_get_freq() */
155 static int
156 check_power_get_freq(void)
157 {
158         int ret;
159         uint32_t count;
160
161         /* test with an invalid lcore id */
162         count = rte_power_get_freq(TEST_POWER_LCORE_INVALID);
163         if (count < TEST_POWER_FREQS_NUM_MAX) {
164                 printf("Unexpectedly get freq index successfully on "
165                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
166                 return -1;
167         }
168
169         count = rte_power_get_freq(TEST_POWER_LCORE_ID);
170         if (count >= TEST_POWER_FREQS_NUM_MAX) {
171                 printf("Fail to get the freq index on lcore %u\n",
172                                                 TEST_POWER_LCORE_ID);
173                 return -1;
174         }
175
176         /* Check the current frequency */
177         ret = check_cur_freq(TEST_POWER_LCORE_ID, count);
178         if (ret < 0)
179                 return -1;
180
181         return 0;
182 }
183
184 /* Check rte_power_set_freq() */
185 static int
186 check_power_set_freq(void)
187 {
188         int ret;
189
190         /* test with an invalid lcore id */
191         ret = rte_power_set_freq(TEST_POWER_LCORE_INVALID, 0);
192         if (ret >= 0) {
193                 printf("Unexpectedly set freq index successfully on "
194                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
195                 return -1;
196         }
197
198         /* test with an invalid freq index */
199         ret = rte_power_set_freq(TEST_POWER_LCORE_ID,
200                                 TEST_POWER_FREQS_NUM_MAX);
201         if (ret >= 0) {
202                 printf("Unexpectedly set an invalid freq index (%u)"
203                         "successfully on lcore %u\n", TEST_POWER_FREQS_NUM_MAX,
204                                                         TEST_POWER_LCORE_ID);
205                 return -1;
206         }
207
208         /**
209          * test with an invalid freq index which is right one bigger than
210          * total number of freqs
211          */
212         ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num);
213         if (ret >= 0) {
214                 printf("Unexpectedly set an invalid freq index (%u)"
215                         "successfully on lcore %u\n", total_freq_num,
216                                                 TEST_POWER_LCORE_ID);
217                 return -1;
218         }
219         ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
220         if (ret < 0) {
221                 printf("Fail to set freq index on lcore %u\n",
222                                         TEST_POWER_LCORE_ID);
223                 return -1;
224         }
225
226         /* Check the current frequency */
227         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
228         if (ret < 0)
229                 return -1;
230
231         return 0;
232 }
233
234 /* Check rte_power_freq_down() */
235 static int
236 check_power_freq_down(void)
237 {
238         int ret;
239
240         /* test with an invalid lcore id */
241         ret = rte_power_freq_down(TEST_POWER_LCORE_INVALID);
242         if (ret >= 0) {
243                 printf("Unexpectedly scale down successfully the freq on "
244                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
245                 return -1;
246         }
247
248         /* Scale down to min and then scale down one step */
249         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
250         if (ret < 0) {
251                 printf("Fail to scale down the freq to min on lcore %u\n",
252                                                         TEST_POWER_LCORE_ID);
253                 return -1;
254         }
255         ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
256         if (ret < 0) {
257                 printf("Fail to scale down the freq on lcore %u\n",
258                                                 TEST_POWER_LCORE_ID);
259                 return -1;
260         }
261
262         /* Check the current frequency */
263         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
264         if (ret < 0)
265                 return -1;
266
267         /* Scale up to max and then scale down one step */
268         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
269         if (ret < 0) {
270                 printf("Fail to scale up the freq to max on lcore %u\n",
271                                                         TEST_POWER_LCORE_ID);
272                 return -1;
273         }
274         ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
275         if (ret < 0) {
276                 printf("Fail to scale down the freq on lcore %u\n",
277                                                 TEST_POWER_LCORE_ID);
278                 return -1;
279         }
280
281         /* Check the current frequency */
282         ret = check_cur_freq(TEST_POWER_LCORE_ID, 1);
283         if (ret < 0)
284                 return -1;
285
286         return 0;
287 }
288
289 /* Check rte_power_freq_up() */
290 static int
291 check_power_freq_up(void)
292 {
293         int ret;
294
295         /* test with an invalid lcore id */
296         ret = rte_power_freq_up(TEST_POWER_LCORE_INVALID);
297         if (ret >= 0) {
298                 printf("Unexpectedly scale up successfully the freq on %u\n",
299                                                 TEST_POWER_LCORE_INVALID);
300                 return -1;
301         }
302
303         /* Scale down to min and then scale up one step */
304         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
305         if (ret < 0) {
306                 printf("Fail to scale down the freq to min on lcore %u\n",
307                                                         TEST_POWER_LCORE_ID);
308                 return -1;
309         }
310         ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
311         if (ret < 0) {
312                 printf("Fail to scale up the freq on lcore %u\n",
313                                                 TEST_POWER_LCORE_ID);
314                 return -1;
315         }
316
317         /* Check the current frequency */
318         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 2);
319         if (ret < 0)
320                 return -1;
321
322         /* Scale up to max and then scale up one step */
323         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
324         if (ret < 0) {
325                 printf("Fail to scale up the freq to max on lcore %u\n",
326                                                 TEST_POWER_LCORE_ID);
327                 return -1;
328         }
329         ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
330         if (ret < 0) {
331                 printf("Fail to scale up the freq on lcore %u\n",
332                                                 TEST_POWER_LCORE_ID);
333                 return -1;
334         }
335
336         /* Check the current frequency */
337         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
338         if (ret < 0)
339                 return -1;
340
341         return 0;
342 }
343
344 /* Check rte_power_freq_max() */
345 static int
346 check_power_freq_max(void)
347 {
348         int ret;
349
350         /* test with an invalid lcore id */
351         ret = rte_power_freq_max(TEST_POWER_LCORE_INVALID);
352         if (ret >= 0) {
353                 printf("Unexpectedly scale up successfully the freq to max on "
354                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
355                 return -1;
356         }
357         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
358         if (ret < 0) {
359                 printf("Fail to scale up the freq to max on lcore %u\n",
360                                                 TEST_POWER_LCORE_ID);
361                 return -1;
362         }
363
364         /* Check the current frequency */
365         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
366         if (ret < 0)
367                 return -1;
368
369         return 0;
370 }
371
372 /* Check rte_power_freq_min() */
373 static int
374 check_power_freq_min(void)
375 {
376         int ret;
377
378         /* test with an invalid lcore id */
379         ret = rte_power_freq_min(TEST_POWER_LCORE_INVALID);
380         if (ret >= 0) {
381                 printf("Unexpectedly scale down successfully the freq to min "
382                                 "on lcore %u\n", TEST_POWER_LCORE_INVALID);
383                 return -1;
384         }
385         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
386         if (ret < 0) {
387                 printf("Fail to scale down the freq to min on lcore %u\n",
388                                                         TEST_POWER_LCORE_ID);
389                 return -1;
390         }
391
392         /* Check the current frequency */
393         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
394         if (ret < 0)
395                 return -1;
396
397         return 0;
398 }
399
400 /* Check rte_power_turbo() */
401 static int
402 check_power_turbo(void)
403 {
404         int ret;
405
406         if (rte_power_turbo_status(TEST_POWER_LCORE_ID) == 0) {
407                 printf("Turbo not available on lcore %u, skipping test\n",
408                                 TEST_POWER_LCORE_ID);
409                 return 0;
410         }
411
412         /* test with an invalid lcore id */
413         ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_INVALID);
414         if (ret >= 0) {
415                 printf("Unexpectedly enable turbo successfully on lcore %u\n",
416                                 TEST_POWER_LCORE_INVALID);
417                 return -1;
418         }
419         ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_ID);
420         if (ret < 0) {
421                 printf("Fail to enable turbo on lcore %u\n",
422                                 TEST_POWER_LCORE_ID);
423                 return -1;
424         }
425
426         /* Check the current frequency */
427         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
428         if (ret < 0)
429                 return -1;
430
431         /* test with an invalid lcore id */
432         ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_INVALID);
433         if (ret >= 0) {
434                 printf("Unexpectedly disable turbo successfully on lcore %u\n",
435                                 TEST_POWER_LCORE_INVALID);
436                 return -1;
437         }
438         ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_ID);
439         if (ret < 0) {
440                 printf("Fail to disable turbo on lcore %u\n",
441                                 TEST_POWER_LCORE_ID);
442                 return -1;
443         }
444
445         /* Check the current frequency */
446         ret = check_cur_freq(TEST_POWER_LCORE_ID, 1);
447         if (ret < 0)
448                 return -1;
449
450         return 0;
451 }
452
453 static int
454 test_power_cpufreq(void)
455 {
456         int ret = -1;
457         enum power_management_env env;
458
459         /* Test initialisation of a valid lcore */
460         ret = rte_power_init(TEST_POWER_LCORE_ID);
461         if (ret < 0) {
462                 printf("Cannot initialise power management for lcore %u, this "
463                                 "may occur if environment is not configured "
464                                 "correctly(APCI cpufreq) or operating in another valid "
465                                 "Power management environment\n",
466                                 TEST_POWER_LCORE_ID);
467                 rte_power_unset_env();
468                 return TEST_SKIPPED;
469         }
470
471         /* Test environment configuration */
472         env = rte_power_get_env();
473         if ((env != PM_ENV_ACPI_CPUFREQ) && (env != PM_ENV_PSTATE_CPUFREQ)) {
474                 printf("Unexpectedly got an environment other than ACPI/PSTATE\n");
475                 goto fail_all;
476         }
477
478         /* verify that function pointers are not NULL */
479         if (rte_power_freqs == NULL) {
480                 printf("rte_power_freqs should not be NULL, environment has not been "
481                                 "initialised\n");
482                 goto fail_all;
483         }
484         if (rte_power_get_freq == NULL) {
485                 printf("rte_power_get_freq should not be NULL, environment has not "
486                                 "been initialised\n");
487                 goto fail_all;
488         }
489         if (rte_power_set_freq == NULL) {
490                 printf("rte_power_set_freq should not be NULL, environment has not "
491                                 "been initialised\n");
492                 goto fail_all;
493         }
494         if (rte_power_freq_up == NULL) {
495                 printf("rte_power_freq_up should not be NULL, environment has not "
496                                 "been initialised\n");
497                 goto fail_all;
498         }
499         if (rte_power_freq_down == NULL) {
500                 printf("rte_power_freq_down should not be NULL, environment has not "
501                                 "been initialised\n");
502                 goto fail_all;
503         }
504         if (rte_power_freq_max == NULL) {
505                 printf("rte_power_freq_max should not be NULL, environment has not "
506                                 "been initialised\n");
507                 goto fail_all;
508         }
509         if (rte_power_freq_min == NULL) {
510                 printf("rte_power_freq_min should not be NULL, environment has not "
511                                 "been initialised\n");
512                 goto fail_all;
513         }
514         if (rte_power_turbo_status == NULL) {
515                 printf("rte_power_turbo_status should not be NULL, environment has not "
516                                 "been initialised\n");
517                 goto fail_all;
518         }
519         if (rte_power_freq_enable_turbo == NULL) {
520                 printf("rte_power_freq_enable_turbo should not be NULL, environment has not "
521                                 "been initialised\n");
522                 goto fail_all;
523         }
524         if (rte_power_freq_disable_turbo == NULL) {
525                 printf("rte_power_freq_disable_turbo should not be NULL, environment has not "
526                                 "been initialised\n");
527                 goto fail_all;
528         }
529
530         ret = rte_power_exit(TEST_POWER_LCORE_ID);
531         if (ret < 0) {
532                 printf("Cannot exit power management for lcore %u\n",
533                                                 TEST_POWER_LCORE_ID);
534                 rte_power_unset_env();
535                 return -1;
536         }
537
538         /* test of init power management for an invalid lcore */
539         ret = rte_power_init(TEST_POWER_LCORE_INVALID);
540         if (ret == 0) {
541                 printf("Unexpectedly initialise power management successfully "
542                                 "for lcore %u\n", TEST_POWER_LCORE_INVALID);
543                 rte_power_unset_env();
544                 return -1;
545         }
546
547         /* Test initialisation of a valid lcore */
548         ret = rte_power_init(TEST_POWER_LCORE_ID);
549         if (ret < 0) {
550                 printf("Cannot initialise power management for lcore %u, this "
551                                 "may occur if environment is not configured "
552                                 "correctly(APCI cpufreq) or operating in another valid "
553                                 "Power management environment\n", TEST_POWER_LCORE_ID);
554                 rte_power_unset_env();
555                 return TEST_SKIPPED;
556         }
557
558         /**
559          * test of initialising power management for the lcore which has
560          * been initialised
561          */
562         ret = rte_power_init(TEST_POWER_LCORE_ID);
563         if (ret == 0) {
564                 printf("Unexpectedly init successfully power twice on "
565                                         "lcore %u\n", TEST_POWER_LCORE_ID);
566                 goto fail_all;
567         }
568
569         ret = check_power_freqs();
570         if (ret < 0)
571                 goto fail_all;
572
573         if (total_freq_num < 2) {
574                 rte_power_exit(TEST_POWER_LCORE_ID);
575                 printf("Frequency can not be changed due to CPU itself\n");
576                 rte_power_unset_env();
577                 return 0;
578         }
579
580         ret = check_power_get_freq();
581         if (ret < 0)
582                 goto fail_all;
583
584         ret = check_power_set_freq();
585         if (ret < 0)
586                 goto fail_all;
587
588         ret = check_power_freq_down();
589         if (ret < 0)
590                 goto fail_all;
591
592         ret = check_power_freq_up();
593         if (ret < 0)
594                 goto fail_all;
595
596         ret = check_power_freq_max();
597         if (ret < 0)
598                 goto fail_all;
599
600         ret = check_power_freq_min();
601         if (ret < 0)
602                 goto fail_all;
603
604         ret = check_power_turbo();
605         if (ret < 0)
606                 goto fail_all;
607
608         ret = rte_power_exit(TEST_POWER_LCORE_ID);
609         if (ret < 0) {
610                 printf("Cannot exit power management for lcore %u\n",
611                                                 TEST_POWER_LCORE_ID);
612                 rte_power_unset_env();
613                 return -1;
614         }
615
616         /**
617          * test of exiting power management for the lcore which has been exited
618          */
619         ret = rte_power_exit(TEST_POWER_LCORE_ID);
620         if (ret == 0) {
621                 printf("Unexpectedly exit successfully power management twice "
622                                         "on lcore %u\n", TEST_POWER_LCORE_ID);
623                 rte_power_unset_env();
624                 return -1;
625         }
626
627         /* test of exit power management for an invalid lcore */
628         ret = rte_power_exit(TEST_POWER_LCORE_INVALID);
629         if (ret == 0) {
630                 printf("Unpectedly exit power management successfully for "
631                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
632                 rte_power_unset_env();
633                 return -1;
634         }
635         rte_power_unset_env();
636         return 0;
637
638 fail_all:
639         rte_power_exit(TEST_POWER_LCORE_ID);
640         rte_power_unset_env();
641         return -1;
642 }
643
644 static int
645 test_power_caps(void)
646 {
647         struct rte_power_core_capabilities caps;
648         int ret;
649
650         ret = rte_power_init(TEST_POWER_LCORE_ID);
651         if (ret < 0) {
652                 printf("Cannot initialise power management for lcore %u, this "
653                         "may occur if environment is not configured "
654                         "correctly(APCI cpufreq) or operating in another valid "
655                         "Power management environment\n", TEST_POWER_LCORE_ID);
656                 rte_power_unset_env();
657                 return -1;
658         }
659
660         ret = rte_power_get_capabilities(TEST_POWER_LCORE_ID, &caps);
661         if (ret) {
662                 printf("POWER: Error getting capabilities\n");
663                 return -1;
664         }
665
666         printf("POWER: Capabilities %"PRIx64"\n", caps.capabilities);
667
668         rte_power_unset_env();
669         return 0;
670 }
671
672 #endif
673
674 REGISTER_TEST_COMMAND(power_cpufreq_autotest, test_power_cpufreq);
675 REGISTER_TEST_COMMAND(power_caps_autotest, test_power_caps);