doc: fix build on Windows with Meson 0.58
[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         rte_power_freq_enable_turbo(TEST_POWER_LCORE_ID);
253
254         /* test with an invalid lcore id */
255         ret = rte_power_freq_down(TEST_POWER_LCORE_INVALID);
256         if (ret >= 0) {
257                 printf("Unexpectedly scale down successfully the freq on "
258                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
259                 return -1;
260         }
261
262         /* Scale down to min and then scale down one step */
263         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
264         if (ret < 0) {
265                 printf("Fail to scale down the freq to min on lcore %u\n",
266                                                         TEST_POWER_LCORE_ID);
267                 return -1;
268         }
269         ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
270         if (ret < 0) {
271                 printf("Fail to scale down the freq on lcore %u\n",
272                                                 TEST_POWER_LCORE_ID);
273                 return -1;
274         }
275
276         /* Check the current frequency */
277         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1, false);
278         if (ret < 0)
279                 return -1;
280
281         /* Scale up to max and then scale down one step */
282         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
283         if (ret < 0) {
284                 printf("Fail to scale up the freq to max on lcore %u\n",
285                                                         TEST_POWER_LCORE_ID);
286                 return -1;
287         }
288         ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
289         if (ret < 0) {
290                 printf("Fail to scale down the freq on lcore %u\n",
291                                                 TEST_POWER_LCORE_ID);
292                 return -1;
293         }
294
295         /* Check the current frequency */
296         ret = check_cur_freq(TEST_POWER_LCORE_ID, 1, false);
297         if (ret < 0)
298                 return -1;
299
300         return 0;
301 }
302
303 /* Check rte_power_freq_up() */
304 static int
305 check_power_freq_up(void)
306 {
307         int ret;
308
309         /* test with an invalid lcore id */
310         ret = rte_power_freq_up(TEST_POWER_LCORE_INVALID);
311         if (ret >= 0) {
312                 printf("Unexpectedly scale up successfully the freq on %u\n",
313                                                 TEST_POWER_LCORE_INVALID);
314                 return -1;
315         }
316
317         /* Scale down to min and then scale up one step */
318         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
319         if (ret < 0) {
320                 printf("Fail to scale down the freq to min on lcore %u\n",
321                                                         TEST_POWER_LCORE_ID);
322                 return -1;
323         }
324         ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
325         if (ret < 0) {
326                 printf("Fail to scale up the freq on lcore %u\n",
327                                                 TEST_POWER_LCORE_ID);
328                 return -1;
329         }
330
331         /* Check the current frequency */
332         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 2, false);
333         if (ret < 0)
334                 return -1;
335
336         /* Scale up to max and then scale up one step */
337         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
338         if (ret < 0) {
339                 printf("Fail to scale up the freq to max on lcore %u\n",
340                                                 TEST_POWER_LCORE_ID);
341                 return -1;
342         }
343         ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
344         if (ret < 0) {
345                 printf("Fail to scale up the freq on lcore %u\n",
346                                                 TEST_POWER_LCORE_ID);
347                 return -1;
348         }
349
350         /* Check the current frequency */
351         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0, true);
352         if (ret < 0)
353                 return -1;
354
355         return 0;
356 }
357
358 /* Check rte_power_freq_max() */
359 static int
360 check_power_freq_max(void)
361 {
362         int ret;
363
364         /* test with an invalid lcore id */
365         ret = rte_power_freq_max(TEST_POWER_LCORE_INVALID);
366         if (ret >= 0) {
367                 printf("Unexpectedly scale up successfully the freq to max on "
368                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
369                 return -1;
370         }
371         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
372         if (ret < 0) {
373                 printf("Fail to scale up the freq to max on lcore %u\n",
374                                                 TEST_POWER_LCORE_ID);
375                 return -1;
376         }
377
378         /* Check the current frequency */
379         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0, true);
380         if (ret < 0)
381                 return -1;
382
383         return 0;
384 }
385
386 /* Check rte_power_freq_min() */
387 static int
388 check_power_freq_min(void)
389 {
390         int ret;
391
392         /* test with an invalid lcore id */
393         ret = rte_power_freq_min(TEST_POWER_LCORE_INVALID);
394         if (ret >= 0) {
395                 printf("Unexpectedly scale down successfully the freq to min "
396                                 "on lcore %u\n", TEST_POWER_LCORE_INVALID);
397                 return -1;
398         }
399         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
400         if (ret < 0) {
401                 printf("Fail to scale down the freq to min on lcore %u\n",
402                                                         TEST_POWER_LCORE_ID);
403                 return -1;
404         }
405
406         /* Check the current frequency */
407         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1, false);
408         if (ret < 0)
409                 return -1;
410
411         return 0;
412 }
413
414 /* Check rte_power_turbo() */
415 static int
416 check_power_turbo(void)
417 {
418         int ret;
419
420         if (rte_power_turbo_status(TEST_POWER_LCORE_ID) == 0) {
421                 printf("Turbo not available on lcore %u, skipping test\n",
422                                 TEST_POWER_LCORE_ID);
423                 return 0;
424         }
425
426         /* test with an invalid lcore id */
427         ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_INVALID);
428         if (ret >= 0) {
429                 printf("Unexpectedly enable turbo successfully on lcore %u\n",
430                                 TEST_POWER_LCORE_INVALID);
431                 return -1;
432         }
433         ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_ID);
434         if (ret < 0) {
435                 printf("Fail to enable turbo on lcore %u\n",
436                                 TEST_POWER_LCORE_ID);
437                 return -1;
438         }
439         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
440         if (ret < 0) {
441                 printf("Fail to scale up the freq to max on lcore %u\n",
442                                                 TEST_POWER_LCORE_ID);
443                 return -1;
444         }
445
446         /* Check the current frequency */
447         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0, true);
448         if (ret < 0)
449                 return -1;
450
451         /* test with an invalid lcore id */
452         ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_INVALID);
453         if (ret >= 0) {
454                 printf("Unexpectedly disable turbo successfully on lcore %u\n",
455                                 TEST_POWER_LCORE_INVALID);
456                 return -1;
457         }
458         ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_ID);
459         if (ret < 0) {
460                 printf("Fail to disable turbo on lcore %u\n",
461                                 TEST_POWER_LCORE_ID);
462                 return -1;
463         }
464         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
465         if (ret < 0) {
466                 printf("Fail to scale up the freq to max on lcore %u\n",
467                                                 TEST_POWER_LCORE_ID);
468                 return -1;
469         }
470
471         /* Check the current frequency */
472         ret = check_cur_freq(TEST_POWER_LCORE_ID, 1, false);
473         if (ret < 0)
474                 return -1;
475
476         return 0;
477 }
478
479 static int
480 test_power_cpufreq(void)
481 {
482         int ret = -1;
483         enum power_management_env env;
484
485         /* Test initialisation of a valid lcore */
486         ret = rte_power_init(TEST_POWER_LCORE_ID);
487         if (ret < 0) {
488                 printf("Cannot initialise power management for lcore %u, this "
489                                 "may occur if environment is not configured "
490                                 "correctly(APCI cpufreq) or operating in another valid "
491                                 "Power management environment\n",
492                                 TEST_POWER_LCORE_ID);
493                 rte_power_unset_env();
494                 return TEST_SKIPPED;
495         }
496
497         /* Test environment configuration */
498         env = rte_power_get_env();
499         if ((env != PM_ENV_ACPI_CPUFREQ) && (env != PM_ENV_PSTATE_CPUFREQ)) {
500                 printf("Unexpectedly got an environment other than ACPI/PSTATE\n");
501                 goto fail_all;
502         }
503
504         /* verify that function pointers are not NULL */
505         if (rte_power_freqs == NULL) {
506                 printf("rte_power_freqs should not be NULL, environment has not been "
507                                 "initialised\n");
508                 goto fail_all;
509         }
510         if (rte_power_get_freq == NULL) {
511                 printf("rte_power_get_freq should not be NULL, environment has not "
512                                 "been initialised\n");
513                 goto fail_all;
514         }
515         if (rte_power_set_freq == NULL) {
516                 printf("rte_power_set_freq should not be NULL, environment has not "
517                                 "been initialised\n");
518                 goto fail_all;
519         }
520         if (rte_power_freq_up == NULL) {
521                 printf("rte_power_freq_up should not be NULL, environment has not "
522                                 "been initialised\n");
523                 goto fail_all;
524         }
525         if (rte_power_freq_down == NULL) {
526                 printf("rte_power_freq_down should not be NULL, environment has not "
527                                 "been initialised\n");
528                 goto fail_all;
529         }
530         if (rte_power_freq_max == NULL) {
531                 printf("rte_power_freq_max should not be NULL, environment has not "
532                                 "been initialised\n");
533                 goto fail_all;
534         }
535         if (rte_power_freq_min == NULL) {
536                 printf("rte_power_freq_min should not be NULL, environment has not "
537                                 "been initialised\n");
538                 goto fail_all;
539         }
540         if (rte_power_turbo_status == NULL) {
541                 printf("rte_power_turbo_status should not be NULL, environment has not "
542                                 "been initialised\n");
543                 goto fail_all;
544         }
545         if (rte_power_freq_enable_turbo == NULL) {
546                 printf("rte_power_freq_enable_turbo should not be NULL, environment has not "
547                                 "been initialised\n");
548                 goto fail_all;
549         }
550         if (rte_power_freq_disable_turbo == NULL) {
551                 printf("rte_power_freq_disable_turbo should not be NULL, environment has not "
552                                 "been initialised\n");
553                 goto fail_all;
554         }
555
556         ret = rte_power_exit(TEST_POWER_LCORE_ID);
557         if (ret < 0) {
558                 printf("Cannot exit power management for lcore %u\n",
559                                                 TEST_POWER_LCORE_ID);
560                 rte_power_unset_env();
561                 return -1;
562         }
563
564         /* test of init power management for an invalid lcore */
565         ret = rte_power_init(TEST_POWER_LCORE_INVALID);
566         if (ret == 0) {
567                 printf("Unexpectedly initialise power management successfully "
568                                 "for lcore %u\n", TEST_POWER_LCORE_INVALID);
569                 rte_power_unset_env();
570                 return -1;
571         }
572
573         /* Test initialisation of a valid lcore */
574         ret = rte_power_init(TEST_POWER_LCORE_ID);
575         if (ret < 0) {
576                 printf("Cannot initialise power management for lcore %u, this "
577                                 "may occur if environment is not configured "
578                                 "correctly(APCI cpufreq) or operating in another valid "
579                                 "Power management environment\n", TEST_POWER_LCORE_ID);
580                 rte_power_unset_env();
581                 return TEST_SKIPPED;
582         }
583
584         /**
585          * test of initialising power management for the lcore which has
586          * been initialised
587          */
588         ret = rte_power_init(TEST_POWER_LCORE_ID);
589         if (ret == 0) {
590                 printf("Unexpectedly init successfully power twice on "
591                                         "lcore %u\n", TEST_POWER_LCORE_ID);
592                 goto fail_all;
593         }
594
595         ret = check_power_freqs();
596         if (ret < 0)
597                 goto fail_all;
598
599         if (total_freq_num < 2) {
600                 rte_power_exit(TEST_POWER_LCORE_ID);
601                 printf("Frequency can not be changed due to CPU itself\n");
602                 rte_power_unset_env();
603                 return 0;
604         }
605
606         ret = check_power_get_freq();
607         if (ret < 0)
608                 goto fail_all;
609
610         ret = check_power_set_freq();
611         if (ret < 0)
612                 goto fail_all;
613
614         ret = check_power_freq_down();
615         if (ret < 0)
616                 goto fail_all;
617
618         ret = check_power_freq_up();
619         if (ret < 0)
620                 goto fail_all;
621
622         ret = check_power_freq_max();
623         if (ret < 0)
624                 goto fail_all;
625
626         ret = check_power_freq_min();
627         if (ret < 0)
628                 goto fail_all;
629
630         ret = check_power_turbo();
631         if (ret < 0)
632                 goto fail_all;
633
634         ret = rte_power_exit(TEST_POWER_LCORE_ID);
635         if (ret < 0) {
636                 printf("Cannot exit power management for lcore %u\n",
637                                                 TEST_POWER_LCORE_ID);
638                 rte_power_unset_env();
639                 return -1;
640         }
641
642         /**
643          * test of exiting power management for the lcore which has been exited
644          */
645         ret = rte_power_exit(TEST_POWER_LCORE_ID);
646         if (ret == 0) {
647                 printf("Unexpectedly exit successfully power management twice "
648                                         "on lcore %u\n", TEST_POWER_LCORE_ID);
649                 rte_power_unset_env();
650                 return -1;
651         }
652
653         /* test of exit power management for an invalid lcore */
654         ret = rte_power_exit(TEST_POWER_LCORE_INVALID);
655         if (ret == 0) {
656                 printf("Unpectedly exit power management successfully for "
657                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
658                 rte_power_unset_env();
659                 return -1;
660         }
661         rte_power_unset_env();
662         return 0;
663
664 fail_all:
665         rte_power_exit(TEST_POWER_LCORE_ID);
666         rte_power_unset_env();
667         return -1;
668 }
669
670 static int
671 test_power_caps(void)
672 {
673         struct rte_power_core_capabilities caps;
674         int ret;
675
676         ret = rte_power_init(TEST_POWER_LCORE_ID);
677         if (ret < 0) {
678                 printf("Cannot initialise power management for lcore %u, this "
679                         "may occur if environment is not configured "
680                         "correctly(APCI cpufreq) or operating in another valid "
681                         "Power management environment\n", TEST_POWER_LCORE_ID);
682                 rte_power_unset_env();
683                 return -1;
684         }
685
686         ret = rte_power_get_capabilities(TEST_POWER_LCORE_ID, &caps);
687         if (ret) {
688                 printf("POWER: Error getting capabilities\n");
689                 return -1;
690         }
691
692         printf("POWER: Capabilities %"PRIx64"\n", caps.capabilities);
693
694         rte_power_unset_env();
695         return 0;
696 }
697
698 #endif
699
700 REGISTER_TEST_COMMAND(power_cpufreq_autotest, test_power_cpufreq);
701 REGISTER_TEST_COMMAND(power_caps_autotest, test_power_caps);