power: support cppc_cpufreq driver
[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                         (env != PM_ENV_CPPC_CPUFREQ)) {
501                 printf("Unexpectedly got an environment other than ACPI/PSTATE\n");
502                 goto fail_all;
503         }
504
505         /* verify that function pointers are not NULL */
506         if (rte_power_freqs == NULL) {
507                 printf("rte_power_freqs should not be NULL, environment has not been "
508                                 "initialised\n");
509                 goto fail_all;
510         }
511         if (rte_power_get_freq == NULL) {
512                 printf("rte_power_get_freq should not be NULL, environment has not "
513                                 "been initialised\n");
514                 goto fail_all;
515         }
516         if (rte_power_set_freq == NULL) {
517                 printf("rte_power_set_freq should not be NULL, environment has not "
518                                 "been initialised\n");
519                 goto fail_all;
520         }
521         if (rte_power_freq_up == NULL) {
522                 printf("rte_power_freq_up should not be NULL, environment has not "
523                                 "been initialised\n");
524                 goto fail_all;
525         }
526         if (rte_power_freq_down == NULL) {
527                 printf("rte_power_freq_down should not be NULL, environment has not "
528                                 "been initialised\n");
529                 goto fail_all;
530         }
531         if (rte_power_freq_max == NULL) {
532                 printf("rte_power_freq_max should not be NULL, environment has not "
533                                 "been initialised\n");
534                 goto fail_all;
535         }
536         if (rte_power_freq_min == NULL) {
537                 printf("rte_power_freq_min should not be NULL, environment has not "
538                                 "been initialised\n");
539                 goto fail_all;
540         }
541         if (rte_power_turbo_status == NULL) {
542                 printf("rte_power_turbo_status should not be NULL, environment has not "
543                                 "been initialised\n");
544                 goto fail_all;
545         }
546         if (rte_power_freq_enable_turbo == NULL) {
547                 printf("rte_power_freq_enable_turbo should not be NULL, environment has not "
548                                 "been initialised\n");
549                 goto fail_all;
550         }
551         if (rte_power_freq_disable_turbo == NULL) {
552                 printf("rte_power_freq_disable_turbo should not be NULL, environment has not "
553                                 "been initialised\n");
554                 goto fail_all;
555         }
556
557         ret = rte_power_exit(TEST_POWER_LCORE_ID);
558         if (ret < 0) {
559                 printf("Cannot exit power management for lcore %u\n",
560                                                 TEST_POWER_LCORE_ID);
561                 rte_power_unset_env();
562                 return -1;
563         }
564
565         /* test of init power management for an invalid lcore */
566         ret = rte_power_init(TEST_POWER_LCORE_INVALID);
567         if (ret == 0) {
568                 printf("Unexpectedly initialise power management successfully "
569                                 "for lcore %u\n", TEST_POWER_LCORE_INVALID);
570                 rte_power_unset_env();
571                 return -1;
572         }
573
574         /* Test initialisation of a valid lcore */
575         ret = rte_power_init(TEST_POWER_LCORE_ID);
576         if (ret < 0) {
577                 printf("Cannot initialise power management for lcore %u, this "
578                                 "may occur if environment is not configured "
579                                 "correctly(APCI cpufreq) or operating in another valid "
580                                 "Power management environment\n", TEST_POWER_LCORE_ID);
581                 rte_power_unset_env();
582                 return TEST_SKIPPED;
583         }
584
585         /**
586          * test of initialising power management for the lcore which has
587          * been initialised
588          */
589         ret = rte_power_init(TEST_POWER_LCORE_ID);
590         if (ret == 0) {
591                 printf("Unexpectedly init successfully power twice on "
592                                         "lcore %u\n", TEST_POWER_LCORE_ID);
593                 goto fail_all;
594         }
595
596         ret = check_power_freqs();
597         if (ret < 0)
598                 goto fail_all;
599
600         if (total_freq_num < 2) {
601                 rte_power_exit(TEST_POWER_LCORE_ID);
602                 printf("Frequency can not be changed due to CPU itself\n");
603                 rte_power_unset_env();
604                 return 0;
605         }
606
607         ret = check_power_get_freq();
608         if (ret < 0)
609                 goto fail_all;
610
611         ret = check_power_set_freq();
612         if (ret < 0)
613                 goto fail_all;
614
615         ret = check_power_freq_down();
616         if (ret < 0)
617                 goto fail_all;
618
619         ret = check_power_freq_up();
620         if (ret < 0)
621                 goto fail_all;
622
623         ret = check_power_freq_max();
624         if (ret < 0)
625                 goto fail_all;
626
627         ret = check_power_freq_min();
628         if (ret < 0)
629                 goto fail_all;
630
631         ret = check_power_turbo();
632         if (ret < 0)
633                 goto fail_all;
634
635         ret = rte_power_exit(TEST_POWER_LCORE_ID);
636         if (ret < 0) {
637                 printf("Cannot exit power management for lcore %u\n",
638                                                 TEST_POWER_LCORE_ID);
639                 rte_power_unset_env();
640                 return -1;
641         }
642
643         /**
644          * test of exiting power management for the lcore which has been exited
645          */
646         ret = rte_power_exit(TEST_POWER_LCORE_ID);
647         if (ret == 0) {
648                 printf("Unexpectedly exit successfully power management twice "
649                                         "on lcore %u\n", TEST_POWER_LCORE_ID);
650                 rte_power_unset_env();
651                 return -1;
652         }
653
654         /* test of exit power management for an invalid lcore */
655         ret = rte_power_exit(TEST_POWER_LCORE_INVALID);
656         if (ret == 0) {
657                 printf("Unpectedly exit power management successfully for "
658                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
659                 rte_power_unset_env();
660                 return -1;
661         }
662         rte_power_unset_env();
663         return 0;
664
665 fail_all:
666         rte_power_exit(TEST_POWER_LCORE_ID);
667         rte_power_unset_env();
668         return -1;
669 }
670
671 static int
672 test_power_caps(void)
673 {
674         struct rte_power_core_capabilities caps;
675         int ret;
676
677         ret = rte_power_init(TEST_POWER_LCORE_ID);
678         if (ret < 0) {
679                 printf("Cannot initialise power management for lcore %u, this "
680                         "may occur if environment is not configured "
681                         "correctly(APCI cpufreq) or operating in another valid "
682                         "Power management environment\n", TEST_POWER_LCORE_ID);
683                 rte_power_unset_env();
684                 return -1;
685         }
686
687         ret = rte_power_get_capabilities(TEST_POWER_LCORE_ID, &caps);
688         if (ret) {
689                 printf("POWER: Error getting capabilities\n");
690                 return -1;
691         }
692
693         printf("POWER: Capabilities %"PRIx64"\n", caps.capabilities);
694
695         rte_power_unset_env();
696         return 0;
697 }
698
699 #endif
700
701 REGISTER_TEST_COMMAND(power_cpufreq_autotest, test_power_cpufreq);
702 REGISTER_TEST_COMMAND(power_caps_autotest, test_power_caps);