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