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