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