xref: /dpdk/app/test/test_power_cpufreq.c (revision 089e5ed727a15da2729cfee9b63533dd120bd04c)
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 
12 #include "test.h"
13 
14 #ifndef RTE_LIBRTE_POWER
15 
16 static int
17 test_power_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_caps(void)
25 {
26 	printf("Power management library not supported, skipping test\n");
27 	return TEST_SKIPPED;
28 }
29 
30 #else
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 \
38 	"/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_cur_freq"
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 /* Check rte_power_turbo() */
370 static int
371 check_power_turbo(void)
372 {
373 	int ret;
374 
375 	if (rte_power_turbo_status(TEST_POWER_LCORE_ID) == 0) {
376 		printf("Turbo not available on lcore %u, skipping test\n",
377 				TEST_POWER_LCORE_ID);
378 		return 0;
379 	}
380 
381 	/* test with an invalid lcore id */
382 	ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_INVALID);
383 	if (ret >= 0) {
384 		printf("Unexpectedly enable turbo successfully on lcore %u\n",
385 				TEST_POWER_LCORE_INVALID);
386 		return -1;
387 	}
388 	ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_ID);
389 	if (ret < 0) {
390 		printf("Fail to enable turbo on lcore %u\n",
391 				TEST_POWER_LCORE_ID);
392 		return -1;
393 	}
394 
395 	/* Check the current frequency */
396 	ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
397 	if (ret < 0)
398 		return -1;
399 
400 	/* test with an invalid lcore id */
401 	ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_INVALID);
402 	if (ret >= 0) {
403 		printf("Unexpectedly disable turbo successfully on lcore %u\n",
404 				TEST_POWER_LCORE_INVALID);
405 		return -1;
406 	}
407 	ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_ID);
408 	if (ret < 0) {
409 		printf("Fail to disable turbo on lcore %u\n",
410 				TEST_POWER_LCORE_ID);
411 		return -1;
412 	}
413 
414 	/* Check the current frequency */
415 	ret = check_cur_freq(TEST_POWER_LCORE_ID, 1);
416 	if (ret < 0)
417 		return -1;
418 
419 	return 0;
420 }
421 
422 static int
423 test_power_cpufreq(void)
424 {
425 	int ret = -1;
426 	enum power_management_env env;
427 
428 	/* Test initialisation of a valid lcore */
429 	ret = rte_power_init(TEST_POWER_LCORE_ID);
430 	if (ret < 0) {
431 		printf("Cannot initialise power management for lcore %u, this "
432 				"may occur if environment is not configured "
433 				"correctly(APCI cpufreq) or operating in another valid "
434 				"Power management environment\n",
435 				TEST_POWER_LCORE_ID);
436 		rte_power_unset_env();
437 		return TEST_SKIPPED;
438 	}
439 
440 	/* Test environment configuration */
441 	env = rte_power_get_env();
442 	if ((env != PM_ENV_ACPI_CPUFREQ) && (env != PM_ENV_PSTATE_CPUFREQ)) {
443 		printf("Unexpectedly got an environment other than ACPI/PSTATE\n");
444 		goto fail_all;
445 	}
446 
447 	/* verify that function pointers are not NULL */
448 	if (rte_power_freqs == NULL) {
449 		printf("rte_power_freqs should not be NULL, environment has not been "
450 				"initialised\n");
451 		goto fail_all;
452 	}
453 	if (rte_power_get_freq == NULL) {
454 		printf("rte_power_get_freq should not be NULL, environment has not "
455 				"been initialised\n");
456 		goto fail_all;
457 	}
458 	if (rte_power_set_freq == NULL) {
459 		printf("rte_power_set_freq should not be NULL, environment has not "
460 				"been initialised\n");
461 		goto fail_all;
462 	}
463 	if (rte_power_freq_up == NULL) {
464 		printf("rte_power_freq_up should not be NULL, environment has not "
465 				"been initialised\n");
466 		goto fail_all;
467 	}
468 	if (rte_power_freq_down == NULL) {
469 		printf("rte_power_freq_down should not be NULL, environment has not "
470 				"been initialised\n");
471 		goto fail_all;
472 	}
473 	if (rte_power_freq_max == NULL) {
474 		printf("rte_power_freq_max should not be NULL, environment has not "
475 				"been initialised\n");
476 		goto fail_all;
477 	}
478 	if (rte_power_freq_min == NULL) {
479 		printf("rte_power_freq_min should not be NULL, environment has not "
480 				"been initialised\n");
481 		goto fail_all;
482 	}
483 	if (rte_power_turbo_status == NULL) {
484 		printf("rte_power_turbo_status should not be NULL, environment has not "
485 				"been initialised\n");
486 		goto fail_all;
487 	}
488 	if (rte_power_freq_enable_turbo == NULL) {
489 		printf("rte_power_freq_enable_turbo should not be NULL, environment has not "
490 				"been initialised\n");
491 		goto fail_all;
492 	}
493 	if (rte_power_freq_disable_turbo == NULL) {
494 		printf("rte_power_freq_disable_turbo should not be NULL, environment has not "
495 				"been initialised\n");
496 		goto fail_all;
497 	}
498 
499 	ret = rte_power_exit(TEST_POWER_LCORE_ID);
500 	if (ret < 0) {
501 		printf("Cannot exit power management for lcore %u\n",
502 						TEST_POWER_LCORE_ID);
503 		rte_power_unset_env();
504 		return -1;
505 	}
506 
507 	/* test of init power management for an invalid lcore */
508 	ret = rte_power_init(TEST_POWER_LCORE_INVALID);
509 	if (ret == 0) {
510 		printf("Unexpectedly initialise power management successfully "
511 				"for lcore %u\n", TEST_POWER_LCORE_INVALID);
512 		rte_power_unset_env();
513 		return -1;
514 	}
515 
516 	/* Test initialisation of a valid lcore */
517 	ret = rte_power_init(TEST_POWER_LCORE_ID);
518 	if (ret < 0) {
519 		printf("Cannot initialise power management for lcore %u, this "
520 				"may occur if environment is not configured "
521 				"correctly(APCI cpufreq) or operating in another valid "
522 				"Power management environment\n", TEST_POWER_LCORE_ID);
523 		rte_power_unset_env();
524 		return TEST_SKIPPED;
525 	}
526 
527 	/**
528 	 * test of initialising power management for the lcore which has
529 	 * been initialised
530 	 */
531 	ret = rte_power_init(TEST_POWER_LCORE_ID);
532 	if (ret == 0) {
533 		printf("Unexpectedly init successfully power twice on "
534 					"lcore %u\n", TEST_POWER_LCORE_ID);
535 		goto fail_all;
536 	}
537 
538 	ret = check_power_freqs();
539 	if (ret < 0)
540 		goto fail_all;
541 
542 	if (total_freq_num < 2) {
543 		rte_power_exit(TEST_POWER_LCORE_ID);
544 		printf("Frequency can not be changed due to CPU itself\n");
545 		rte_power_unset_env();
546 		return 0;
547 	}
548 
549 	ret = check_power_get_freq();
550 	if (ret < 0)
551 		goto fail_all;
552 
553 	ret = check_power_set_freq();
554 	if (ret < 0)
555 		goto fail_all;
556 
557 	ret = check_power_freq_down();
558 	if (ret < 0)
559 		goto fail_all;
560 
561 	ret = check_power_freq_up();
562 	if (ret < 0)
563 		goto fail_all;
564 
565 	ret = check_power_freq_max();
566 	if (ret < 0)
567 		goto fail_all;
568 
569 	ret = check_power_freq_min();
570 	if (ret < 0)
571 		goto fail_all;
572 
573 	ret = check_power_turbo();
574 	if (ret < 0)
575 		goto fail_all;
576 
577 	ret = rte_power_exit(TEST_POWER_LCORE_ID);
578 	if (ret < 0) {
579 		printf("Cannot exit power management for lcore %u\n",
580 						TEST_POWER_LCORE_ID);
581 		rte_power_unset_env();
582 		return -1;
583 	}
584 
585 	/**
586 	 * test of exiting power management for the lcore which has been exited
587 	 */
588 	ret = rte_power_exit(TEST_POWER_LCORE_ID);
589 	if (ret == 0) {
590 		printf("Unexpectedly exit successfully power management twice "
591 					"on lcore %u\n", TEST_POWER_LCORE_ID);
592 		rte_power_unset_env();
593 		return -1;
594 	}
595 
596 	/* test of exit power management for an invalid lcore */
597 	ret = rte_power_exit(TEST_POWER_LCORE_INVALID);
598 	if (ret == 0) {
599 		printf("Unpectedly exit power management successfully for "
600 				"lcore %u\n", TEST_POWER_LCORE_INVALID);
601 		rte_power_unset_env();
602 		return -1;
603 	}
604 	rte_power_unset_env();
605 	return 0;
606 
607 fail_all:
608 	rte_power_exit(TEST_POWER_LCORE_ID);
609 	rte_power_unset_env();
610 	return -1;
611 }
612 
613 static int
614 test_power_caps(void)
615 {
616 	struct rte_power_core_capabilities caps;
617 	int ret;
618 
619 	ret = rte_power_init(TEST_POWER_LCORE_ID);
620 	if (ret < 0) {
621 		printf("Cannot initialise power management for lcore %u, this "
622 			"may occur if environment is not configured "
623 			"correctly(APCI cpufreq) or operating in another valid "
624 			"Power management environment\n", TEST_POWER_LCORE_ID);
625 		rte_power_unset_env();
626 		return -1;
627 	}
628 
629 	ret = rte_power_get_capabilities(TEST_POWER_LCORE_ID, &caps);
630 	if (ret) {
631 		printf("POWER: Error getting capabilities\n");
632 		return -1;
633 	}
634 
635 	printf("POWER: Capabilities %"PRIx64"\n", caps.capabilities);
636 
637 	rte_power_unset_env();
638 	return 0;
639 }
640 
641 #endif
642 
643 REGISTER_TEST_COMMAND(power_cpufreq_autotest, test_power_cpufreq);
644 REGISTER_TEST_COMMAND(power_caps_autotest, test_power_caps);
645