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