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