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