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