test/power: add unit test for get capabilities API
[dpdk.git] / test / test / test_power_acpi_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
11 #include "test.h"
12
13 #ifndef RTE_LIBRTE_POWER
14
15 static int
16 test_power_acpi_cpufreq(void)
17 {
18         printf("Power management library not supported, skipping test\n");
19         return TEST_SKIPPED;
20 }
21
22 static int
23 test_power_acpi_caps(void)
24 {
25         printf("Power management library not supported, skipping test\n");
26         return TEST_SKIPPED;
27 }
28
29 #else
30 #include <rte_power.h>
31
32 #define TEST_POWER_LCORE_ID      2U
33 #define TEST_POWER_LCORE_INVALID ((unsigned)RTE_MAX_LCORE)
34 #define TEST_POWER_FREQS_NUM_MAX ((unsigned)RTE_MAX_LCORE_FREQS)
35
36 #define TEST_POWER_SYSFILE_CUR_FREQ \
37         "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_cur_freq"
38
39 static uint32_t total_freq_num;
40 static uint32_t freqs[TEST_POWER_FREQS_NUM_MAX];
41
42 static int
43 check_cur_freq(unsigned lcore_id, uint32_t idx)
44 {
45 #define TEST_POWER_CONVERT_TO_DECIMAL 10
46         FILE *f;
47         char fullpath[PATH_MAX];
48         char buf[BUFSIZ];
49         uint32_t cur_freq;
50         int ret = -1;
51
52         if (snprintf(fullpath, sizeof(fullpath),
53                 TEST_POWER_SYSFILE_CUR_FREQ, lcore_id) < 0) {
54                 return 0;
55         }
56         f = fopen(fullpath, "r");
57         if (f == NULL) {
58                 return 0;
59         }
60         if (fgets(buf, sizeof(buf), f) == NULL) {
61                 goto fail_get_cur_freq;
62         }
63         cur_freq = strtoul(buf, NULL, TEST_POWER_CONVERT_TO_DECIMAL);
64         ret = (freqs[idx] == cur_freq ? 0 : -1);
65
66 fail_get_cur_freq:
67         fclose(f);
68
69         return ret;
70 }
71
72 /* Check rte_power_freqs() */
73 static int
74 check_power_freqs(void)
75 {
76         uint32_t ret;
77
78         total_freq_num = 0;
79         memset(freqs, 0, sizeof(freqs));
80
81         /* test with an invalid lcore id */
82         ret = rte_power_freqs(TEST_POWER_LCORE_INVALID, freqs,
83                                         TEST_POWER_FREQS_NUM_MAX);
84         if (ret > 0) {
85                 printf("Unexpectedly get available freqs successfully on "
86                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
87                 return -1;
88         }
89
90         /* test with NULL buffer to save available freqs */
91         ret = rte_power_freqs(TEST_POWER_LCORE_ID, NULL,
92                                 TEST_POWER_FREQS_NUM_MAX);
93         if (ret > 0) {
94                 printf("Unexpectedly get available freqs successfully with "
95                         "NULL buffer on lcore %u\n", TEST_POWER_LCORE_ID);
96                 return -1;
97         }
98
99         /* test of getting zero number of freqs */
100         ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs, 0);
101         if (ret > 0) {
102                 printf("Unexpectedly get available freqs successfully with "
103                         "zero buffer size on lcore %u\n", TEST_POWER_LCORE_ID);
104                 return -1;
105         }
106
107         /* test with all valid input parameters */
108         ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs,
109                                 TEST_POWER_FREQS_NUM_MAX);
110         if (ret == 0 || ret > TEST_POWER_FREQS_NUM_MAX) {
111                 printf("Fail to get available freqs on lcore %u\n",
112                                                 TEST_POWER_LCORE_ID);
113                 return -1;
114         }
115
116         /* Save the total number of available freqs */
117         total_freq_num = ret;
118
119         return 0;
120 }
121
122 /* Check rte_power_get_freq() */
123 static int
124 check_power_get_freq(void)
125 {
126         int ret;
127         uint32_t count;
128
129         /* test with an invalid lcore id */
130         count = rte_power_get_freq(TEST_POWER_LCORE_INVALID);
131         if (count < TEST_POWER_FREQS_NUM_MAX) {
132                 printf("Unexpectedly get freq index successfully on "
133                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
134                 return -1;
135         }
136
137         count = rte_power_get_freq(TEST_POWER_LCORE_ID);
138         if (count >= TEST_POWER_FREQS_NUM_MAX) {
139                 printf("Fail to get the freq index on lcore %u\n",
140                                                 TEST_POWER_LCORE_ID);
141                 return -1;
142         }
143
144         /* Check the current frequency */
145         ret = check_cur_freq(TEST_POWER_LCORE_ID, count);
146         if (ret < 0)
147                 return -1;
148
149         return 0;
150 }
151
152 /* Check rte_power_set_freq() */
153 static int
154 check_power_set_freq(void)
155 {
156         int ret;
157
158         /* test with an invalid lcore id */
159         ret = rte_power_set_freq(TEST_POWER_LCORE_INVALID, 0);
160         if (ret >= 0) {
161                 printf("Unexpectedly set freq index successfully on "
162                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
163                 return -1;
164         }
165
166         /* test with an invalid freq index */
167         ret = rte_power_set_freq(TEST_POWER_LCORE_ID,
168                                 TEST_POWER_FREQS_NUM_MAX);
169         if (ret >= 0) {
170                 printf("Unexpectedly set an invalid freq index (%u)"
171                         "successfully on lcore %u\n", TEST_POWER_FREQS_NUM_MAX,
172                                                         TEST_POWER_LCORE_ID);
173                 return -1;
174         }
175
176         /**
177          * test with an invalid freq index which is right one bigger than
178          * total number of freqs
179          */
180         ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num);
181         if (ret >= 0) {
182                 printf("Unexpectedly set an invalid freq index (%u)"
183                         "successfully on lcore %u\n", total_freq_num,
184                                                 TEST_POWER_LCORE_ID);
185                 return -1;
186         }
187         ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
188         if (ret < 0) {
189                 printf("Fail to set freq index on lcore %u\n",
190                                         TEST_POWER_LCORE_ID);
191                 return -1;
192         }
193
194         /* Check the current frequency */
195         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
196         if (ret < 0)
197                 return -1;
198
199         return 0;
200 }
201
202 /* Check rte_power_freq_down() */
203 static int
204 check_power_freq_down(void)
205 {
206         int ret;
207
208         /* test with an invalid lcore id */
209         ret = rte_power_freq_down(TEST_POWER_LCORE_INVALID);
210         if (ret >= 0) {
211                 printf("Unexpectedly scale down successfully the freq on "
212                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
213                 return -1;
214         }
215
216         /* Scale down to min and then scale down one step */
217         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
218         if (ret < 0) {
219                 printf("Fail to scale down the freq to min on lcore %u\n",
220                                                         TEST_POWER_LCORE_ID);
221                 return -1;
222         }
223         ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
224         if (ret < 0) {
225                 printf("Fail to scale down the freq on lcore %u\n",
226                                                 TEST_POWER_LCORE_ID);
227                 return -1;
228         }
229
230         /* Check the current frequency */
231         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
232         if (ret < 0)
233                 return -1;
234
235         /* Scale up to max and then scale down one step */
236         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
237         if (ret < 0) {
238                 printf("Fail to scale up the freq to max on lcore %u\n",
239                                                         TEST_POWER_LCORE_ID);
240                 return -1;
241         }
242         ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
243         if (ret < 0) {
244                 printf("Fail to scale down the freq on lcore %u\n",
245                                                 TEST_POWER_LCORE_ID);
246                 return -1;
247         }
248
249         /* Check the current frequency */
250         ret = check_cur_freq(TEST_POWER_LCORE_ID, 1);
251         if (ret < 0)
252                 return -1;
253
254         return 0;
255 }
256
257 /* Check rte_power_freq_up() */
258 static int
259 check_power_freq_up(void)
260 {
261         int ret;
262
263         /* test with an invalid lcore id */
264         ret = rte_power_freq_up(TEST_POWER_LCORE_INVALID);
265         if (ret >= 0) {
266                 printf("Unexpectedly scale up successfully the freq on %u\n",
267                                                 TEST_POWER_LCORE_INVALID);
268                 return -1;
269         }
270
271         /* Scale down to min and then scale up one step */
272         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
273         if (ret < 0) {
274                 printf("Fail to scale down the freq to min on lcore %u\n",
275                                                         TEST_POWER_LCORE_ID);
276                 return -1;
277         }
278         ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
279         if (ret < 0) {
280                 printf("Fail to scale up the freq on lcore %u\n",
281                                                 TEST_POWER_LCORE_ID);
282                 return -1;
283         }
284
285         /* Check the current frequency */
286         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 2);
287         if (ret < 0)
288                 return -1;
289
290         /* Scale up to max and then scale up one step */
291         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
292         if (ret < 0) {
293                 printf("Fail to scale up the freq to max on lcore %u\n",
294                                                 TEST_POWER_LCORE_ID);
295                 return -1;
296         }
297         ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
298         if (ret < 0) {
299                 printf("Fail to scale up the freq on lcore %u\n",
300                                                 TEST_POWER_LCORE_ID);
301                 return -1;
302         }
303
304         /* Check the current frequency */
305         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
306         if (ret < 0)
307                 return -1;
308
309         return 0;
310 }
311
312 /* Check rte_power_freq_max() */
313 static int
314 check_power_freq_max(void)
315 {
316         int ret;
317
318         /* test with an invalid lcore id */
319         ret = rte_power_freq_max(TEST_POWER_LCORE_INVALID);
320         if (ret >= 0) {
321                 printf("Unexpectedly scale up successfully the freq to max on "
322                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
323                 return -1;
324         }
325         ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
326         if (ret < 0) {
327                 printf("Fail to scale up the freq to max on lcore %u\n",
328                                                 TEST_POWER_LCORE_ID);
329                 return -1;
330         }
331
332         /* Check the current frequency */
333         ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
334         if (ret < 0)
335                 return -1;
336
337         return 0;
338 }
339
340 /* Check rte_power_freq_min() */
341 static int
342 check_power_freq_min(void)
343 {
344         int ret;
345
346         /* test with an invalid lcore id */
347         ret = rte_power_freq_min(TEST_POWER_LCORE_INVALID);
348         if (ret >= 0) {
349                 printf("Unexpectedly scale down successfully the freq to min "
350                                 "on lcore %u\n", TEST_POWER_LCORE_INVALID);
351                 return -1;
352         }
353         ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
354         if (ret < 0) {
355                 printf("Fail to scale down the freq to min on lcore %u\n",
356                                                         TEST_POWER_LCORE_ID);
357                 return -1;
358         }
359
360         /* Check the current frequency */
361         ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
362         if (ret < 0)
363                 return -1;
364
365         return 0;
366 }
367
368 static int
369 test_power_acpi_cpufreq(void)
370 {
371         int ret = -1;
372         enum power_management_env env;
373
374         ret = rte_power_set_env(PM_ENV_ACPI_CPUFREQ);
375         if (ret != 0) {
376                 printf("Failed on setting environment to PM_ENV_ACPI_CPUFREQ, this "
377                                 "may occur if environment is not configured correctly or "
378                                 " operating in another valid Power management environment\n");
379                 return -1;
380         }
381
382         /* Test environment configuration */
383         env = rte_power_get_env();
384         if (env != PM_ENV_ACPI_CPUFREQ) {
385                 printf("Unexpectedly got an environment other than ACPI cpufreq\n");
386                 goto fail_all;
387         }
388
389         /* verify that function pointers are not NULL */
390         if (rte_power_freqs == NULL) {
391                 printf("rte_power_freqs should not be NULL, environment has not been "
392                                 "initialised\n");
393                 goto fail_all;
394         }
395         if (rte_power_get_freq == NULL) {
396                 printf("rte_power_get_freq should not be NULL, environment has not "
397                                 "been initialised\n");
398                 goto fail_all;
399         }
400         if (rte_power_set_freq == NULL) {
401                 printf("rte_power_set_freq should not be NULL, environment has not "
402                                 "been initialised\n");
403                 goto fail_all;
404         }
405         if (rte_power_freq_up == NULL) {
406                 printf("rte_power_freq_up should not be NULL, environment has not "
407                                 "been initialised\n");
408                 goto fail_all;
409         }
410         if (rte_power_freq_down == NULL) {
411                 printf("rte_power_freq_down should not be NULL, environment has not "
412                                 "been initialised\n");
413                 goto fail_all;
414         }
415         if (rte_power_freq_max == NULL) {
416                 printf("rte_power_freq_max should not be NULL, environment has not "
417                                 "been initialised\n");
418                 goto fail_all;
419         }
420         if (rte_power_freq_min == NULL) {
421                 printf("rte_power_freq_min should not be NULL, environment has not "
422                                 "been initialised\n");
423                 goto fail_all;
424         }
425
426         /* test of init power management for an invalid lcore */
427         ret = rte_power_init(TEST_POWER_LCORE_INVALID);
428         if (ret == 0) {
429                 printf("Unexpectedly initialise power management successfully "
430                                 "for lcore %u\n", TEST_POWER_LCORE_INVALID);
431                 rte_power_unset_env();
432                 return -1;
433         }
434
435         /* Test initialisation of a valid lcore */
436         ret = rte_power_init(TEST_POWER_LCORE_ID);
437         if (ret < 0) {
438                 printf("Cannot initialise power management for lcore %u, this "
439                                 "may occur if environment is not configured "
440                                 "correctly(APCI cpufreq) or operating in another valid "
441                                 "Power management environment\n", TEST_POWER_LCORE_ID);
442                 rte_power_unset_env();
443                 return -1;
444         }
445
446         /**
447          * test of initialising power management for the lcore which has
448          * been initialised
449          */
450         ret = rte_power_init(TEST_POWER_LCORE_ID);
451         if (ret == 0) {
452                 printf("Unexpectedly init successfully power twice on "
453                                         "lcore %u\n", TEST_POWER_LCORE_ID);
454                 goto fail_all;
455         }
456
457         ret = check_power_freqs();
458         if (ret < 0)
459                 goto fail_all;
460
461         if (total_freq_num < 2) {
462                 rte_power_exit(TEST_POWER_LCORE_ID);
463                 printf("Frequency can not be changed due to CPU itself\n");
464                 rte_power_unset_env();
465                 return 0;
466         }
467
468         ret = check_power_get_freq();
469         if (ret < 0)
470                 goto fail_all;
471
472         ret = check_power_set_freq();
473         if (ret < 0)
474                 goto fail_all;
475
476         ret = check_power_freq_down();
477         if (ret < 0)
478                 goto fail_all;
479
480         ret = check_power_freq_up();
481         if (ret < 0)
482                 goto fail_all;
483
484         ret = check_power_freq_max();
485         if (ret < 0)
486                 goto fail_all;
487
488         ret = check_power_freq_min();
489         if (ret < 0)
490                 goto fail_all;
491
492         ret = rte_power_exit(TEST_POWER_LCORE_ID);
493         if (ret < 0) {
494                 printf("Cannot exit power management for lcore %u\n",
495                                                 TEST_POWER_LCORE_ID);
496                 rte_power_unset_env();
497                 return -1;
498         }
499
500         /**
501          * test of exiting power management for the lcore which has been exited
502          */
503         ret = rte_power_exit(TEST_POWER_LCORE_ID);
504         if (ret == 0) {
505                 printf("Unexpectedly exit successfully power management twice "
506                                         "on lcore %u\n", TEST_POWER_LCORE_ID);
507                 rte_power_unset_env();
508                 return -1;
509         }
510
511         /* test of exit power management for an invalid lcore */
512         ret = rte_power_exit(TEST_POWER_LCORE_INVALID);
513         if (ret == 0) {
514                 printf("Unpectedly exit power management successfully for "
515                                 "lcore %u\n", TEST_POWER_LCORE_INVALID);
516                 rte_power_unset_env();
517                 return -1;
518         }
519         rte_power_unset_env();
520         return 0;
521
522 fail_all:
523         rte_power_exit(TEST_POWER_LCORE_ID);
524         rte_power_unset_env();
525         return -1;
526 }
527
528 static int
529 test_power_acpi_caps(void)
530 {
531         struct rte_power_core_capabilities caps;
532         int ret;
533
534         ret = rte_power_set_env(PM_ENV_ACPI_CPUFREQ);
535         if (ret) {
536                 printf("Error setting ACPI environment\n");
537                 return -1;
538         }
539
540         ret = rte_power_init(TEST_POWER_LCORE_ID);
541         if (ret < 0) {
542                 printf("Cannot initialise power management for lcore %u, this "
543                         "may occur if environment is not configured "
544                         "correctly(APCI cpufreq) or operating in another valid "
545                         "Power management environment\n", TEST_POWER_LCORE_ID);
546                 rte_power_unset_env();
547                 return -1;
548         }
549
550         ret = rte_power_get_capabilities(TEST_POWER_LCORE_ID, &caps);
551         if (ret) {
552                 printf("ACPI: Error getting capabilities\n");
553                 return -1;
554         }
555
556         printf("ACPI: Capabilities %lx\n", caps.capabilities);
557
558         rte_power_unset_env();
559         return 0;
560 }
561
562 #endif
563
564 REGISTER_TEST_COMMAND(power_acpi_cpufreq_autotest, test_power_acpi_cpufreq);
565 REGISTER_TEST_COMMAND(power_acpi_caps_autotest, test_power_acpi_caps);