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