1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel Speed Select -- Enumerate and control features 4 * Copyright (c) 2019 Intel Corporation. 5 */ 6 7 #include "isst.h" 8 9 int isst_write_pm_config(int cpu, int cp_state) 10 { 11 unsigned int req, resp; 12 int ret; 13 14 if (cp_state) 15 req = BIT(16); 16 else 17 req = 0; 18 19 ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req, 20 &resp); 21 if (ret) 22 return ret; 23 24 debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp); 25 26 return 0; 27 } 28 29 int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap) 30 { 31 unsigned int resp; 32 int ret; 33 34 ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0, 35 &resp); 36 if (ret) 37 return ret; 38 39 debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp); 40 41 *cp_state = resp & BIT(16); 42 *cp_cap = resp & BIT(0) ? 1 : 0; 43 44 return 0; 45 } 46 47 int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev) 48 { 49 unsigned int resp; 50 int ret; 51 52 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 53 CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp); 54 if (ret) { 55 pkg_dev->levels = 0; 56 pkg_dev->locked = 1; 57 pkg_dev->current_level = 0; 58 pkg_dev->version = 0; 59 pkg_dev->enabled = 0; 60 return 0; 61 } 62 63 debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp); 64 65 pkg_dev->version = resp & 0xff; 66 pkg_dev->levels = (resp >> 8) & 0xff; 67 pkg_dev->current_level = (resp >> 16) & 0xff; 68 pkg_dev->locked = !!(resp & BIT(24)); 69 pkg_dev->enabled = !!(resp & BIT(31)); 70 71 return 0; 72 } 73 74 int isst_get_ctdp_control(int cpu, int config_index, 75 struct isst_pkg_ctdp_level_info *ctdp_level) 76 { 77 int cp_state, cp_cap; 78 unsigned int resp; 79 int ret; 80 81 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 82 CONFIG_TDP_GET_TDP_CONTROL, 0, 83 config_index, &resp); 84 if (ret) 85 return ret; 86 87 ctdp_level->fact_support = resp & BIT(0); 88 ctdp_level->pbf_support = !!(resp & BIT(1)); 89 ctdp_level->fact_enabled = !!(resp & BIT(16)); 90 ctdp_level->pbf_enabled = !!(resp & BIT(17)); 91 92 ret = isst_read_pm_config(cpu, &cp_state, &cp_cap); 93 if (ret) { 94 debug_printf("cpu:%d pm_config is not supported \n", cpu); 95 } else { 96 debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap); 97 ctdp_level->sst_cp_support = cp_cap; 98 ctdp_level->sst_cp_enabled = cp_state; 99 } 100 101 debug_printf( 102 "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n", 103 cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support, 104 ctdp_level->fact_enabled, ctdp_level->pbf_enabled); 105 106 return 0; 107 } 108 109 int isst_get_tdp_info(int cpu, int config_index, 110 struct isst_pkg_ctdp_level_info *ctdp_level) 111 { 112 unsigned int resp; 113 int ret; 114 115 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO, 116 0, config_index, &resp); 117 if (ret) { 118 isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index); 119 return ret; 120 } 121 122 ctdp_level->pkg_tdp = resp & GENMASK(14, 0); 123 ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16; 124 125 debug_printf( 126 "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n", 127 cpu, config_index, resp, ctdp_level->tdp_ratio, 128 ctdp_level->pkg_tdp); 129 return 0; 130 } 131 132 int isst_get_pwr_info(int cpu, int config_index, 133 struct isst_pkg_ctdp_level_info *ctdp_level) 134 { 135 unsigned int resp; 136 int ret; 137 138 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO, 139 0, config_index, &resp); 140 if (ret) 141 return ret; 142 143 ctdp_level->pkg_max_power = resp & GENMASK(14, 0); 144 ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16; 145 146 debug_printf( 147 "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n", 148 cpu, config_index, resp, ctdp_level->pkg_max_power, 149 ctdp_level->pkg_min_power); 150 151 return 0; 152 } 153 154 void isst_get_uncore_p0_p1_info(int cpu, int config_index, 155 struct isst_pkg_ctdp_level_info *ctdp_level) 156 { 157 unsigned int resp; 158 int ret; 159 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 160 CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0, 161 config_index, &resp); 162 if (ret) { 163 ctdp_level->uncore_p0 = 0; 164 ctdp_level->uncore_p1 = 0; 165 return; 166 } 167 168 ctdp_level->uncore_p0 = resp & GENMASK(7, 0); 169 ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8; 170 debug_printf( 171 "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n", 172 cpu, config_index, resp, ctdp_level->uncore_p0, 173 ctdp_level->uncore_p1); 174 } 175 176 void isst_get_p1_info(int cpu, int config_index, 177 struct isst_pkg_ctdp_level_info *ctdp_level) 178 { 179 unsigned int resp; 180 int ret; 181 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0, 182 config_index, &resp); 183 if (ret) { 184 ctdp_level->sse_p1 = 0; 185 ctdp_level->avx2_p1 = 0; 186 ctdp_level->avx512_p1 = 0; 187 return; 188 } 189 190 ctdp_level->sse_p1 = resp & GENMASK(7, 0); 191 ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8; 192 ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16; 193 debug_printf( 194 "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n", 195 cpu, config_index, resp, ctdp_level->sse_p1, 196 ctdp_level->avx2_p1, ctdp_level->avx512_p1); 197 } 198 199 void isst_get_uncore_mem_freq(int cpu, int config_index, 200 struct isst_pkg_ctdp_level_info *ctdp_level) 201 { 202 unsigned int resp; 203 int ret; 204 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ, 205 0, config_index, &resp); 206 if (ret) { 207 ctdp_level->mem_freq = 0; 208 return; 209 } 210 211 ctdp_level->mem_freq = resp & GENMASK(7, 0); 212 debug_printf( 213 "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n", 214 cpu, config_index, resp, ctdp_level->mem_freq); 215 } 216 217 int isst_get_tjmax_info(int cpu, int config_index, 218 struct isst_pkg_ctdp_level_info *ctdp_level) 219 { 220 unsigned int resp; 221 int ret; 222 223 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO, 224 0, config_index, &resp); 225 if (ret) 226 return ret; 227 228 ctdp_level->t_proc_hot = resp & GENMASK(7, 0); 229 230 debug_printf( 231 "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n", 232 cpu, config_index, resp, ctdp_level->t_proc_hot); 233 234 return 0; 235 } 236 237 int isst_get_coremask_info(int cpu, int config_index, 238 struct isst_pkg_ctdp_level_info *ctdp_level) 239 { 240 unsigned int resp; 241 int i, ret; 242 243 ctdp_level->cpu_count = 0; 244 for (i = 0; i < 2; ++i) { 245 unsigned long long mask; 246 int cpu_count = 0; 247 248 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 249 CONFIG_TDP_GET_CORE_MASK, 0, 250 (i << 8) | config_index, &resp); 251 if (ret) 252 return ret; 253 254 debug_printf( 255 "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n", 256 cpu, config_index, i, resp); 257 258 mask = (unsigned long long)resp << (32 * i); 259 set_cpu_mask_from_punit_coremask(cpu, mask, 260 ctdp_level->core_cpumask_size, 261 ctdp_level->core_cpumask, 262 &cpu_count); 263 ctdp_level->cpu_count += cpu_count; 264 debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu, 265 config_index, i, ctdp_level->cpu_count); 266 } 267 268 return 0; 269 } 270 271 int isst_get_get_trl_from_msr(int cpu, int *trl) 272 { 273 unsigned long long msr_trl; 274 int ret; 275 276 ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl); 277 if (ret) 278 return ret; 279 280 trl[0] = msr_trl & GENMASK(7, 0); 281 trl[1] = (msr_trl & GENMASK(15, 8)) >> 8; 282 trl[2] = (msr_trl & GENMASK(23, 16)) >> 16; 283 trl[3] = (msr_trl & GENMASK(31, 24)) >> 24; 284 trl[4] = (msr_trl & GENMASK(39, 32)) >> 32; 285 trl[5] = (msr_trl & GENMASK(47, 40)) >> 40; 286 trl[6] = (msr_trl & GENMASK(55, 48)) >> 48; 287 trl[7] = (msr_trl & GENMASK(63, 56)) >> 56; 288 289 return 0; 290 } 291 292 int isst_get_get_trl(int cpu, int level, int avx_level, int *trl) 293 { 294 unsigned int req, resp; 295 int ret; 296 297 req = level | (avx_level << 16); 298 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 299 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req, 300 &resp); 301 if (ret) 302 return ret; 303 304 debug_printf( 305 "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n", 306 cpu, req, resp); 307 308 trl[0] = resp & GENMASK(7, 0); 309 trl[1] = (resp & GENMASK(15, 8)) >> 8; 310 trl[2] = (resp & GENMASK(23, 16)) >> 16; 311 trl[3] = (resp & GENMASK(31, 24)) >> 24; 312 313 req = level | BIT(8) | (avx_level << 16); 314 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 315 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req, 316 &resp); 317 if (ret) 318 return ret; 319 320 debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu, 321 req, resp); 322 323 trl[4] = resp & GENMASK(7, 0); 324 trl[5] = (resp & GENMASK(15, 8)) >> 8; 325 trl[6] = (resp & GENMASK(23, 16)) >> 16; 326 trl[7] = (resp & GENMASK(31, 24)) >> 24; 327 328 return 0; 329 } 330 331 int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info) 332 { 333 int ret; 334 335 debug_printf("cpu:%d bucket info via MSR\n", cpu); 336 337 *buckets_info = 0; 338 339 ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info); 340 if (ret) 341 return ret; 342 343 debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu, 344 *buckets_info); 345 346 return 0; 347 } 348 349 int isst_set_tdp_level_msr(int cpu, int tdp_level) 350 { 351 unsigned long long level = tdp_level; 352 int ret; 353 354 debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level); 355 356 if (isst_get_config_tdp_lock_status(cpu)) { 357 isst_display_error_info_message(1, "tdp_locked", 0, 0); 358 return -1; 359 } 360 361 if (tdp_level > 2) 362 return -1; /* invalid value */ 363 364 ret = isst_send_msr_command(cpu, 0x64b, 1, &level); 365 if (ret) 366 return ret; 367 368 debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level); 369 370 return 0; 371 } 372 373 int isst_set_tdp_level(int cpu, int tdp_level) 374 { 375 unsigned int resp; 376 int ret; 377 378 379 if (isst_get_config_tdp_lock_status(cpu)) { 380 isst_display_error_info_message(1, "TDP is locked", 0, 0); 381 return -1; 382 383 } 384 385 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0, 386 tdp_level, &resp); 387 if (ret) { 388 isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level); 389 return ret; 390 } 391 392 return 0; 393 } 394 395 int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info) 396 { 397 struct isst_pkg_ctdp_level_info ctdp_level; 398 struct isst_pkg_ctdp pkg_dev; 399 int i, ret, core_cnt, max; 400 unsigned int req, resp; 401 402 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 403 if (ret) { 404 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 405 return ret; 406 } 407 408 if (level > pkg_dev.levels) { 409 isst_display_error_info_message(1, "Invalid level", 1, level); 410 return -1; 411 } 412 413 ret = isst_get_ctdp_control(cpu, level, &ctdp_level); 414 if (ret) 415 return ret; 416 417 if (!ctdp_level.pbf_support) { 418 isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level); 419 return -1; 420 } 421 422 pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask); 423 424 core_cnt = get_core_count(get_physical_package_id(cpu), get_physical_die_id(cpu)); 425 max = core_cnt > 32 ? 2 : 1; 426 427 for (i = 0; i < max; ++i) { 428 unsigned long long mask; 429 int count; 430 431 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 432 CONFIG_TDP_PBF_GET_CORE_MASK_INFO, 433 0, (i << 8) | level, &resp); 434 if (ret) 435 break; 436 437 debug_printf( 438 "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n", 439 cpu, resp); 440 441 mask = (unsigned long long)resp << (32 * i); 442 set_cpu_mask_from_punit_coremask(cpu, mask, 443 pbf_info->core_cpumask_size, 444 pbf_info->core_cpumask, 445 &count); 446 } 447 448 req = level; 449 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 450 CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req, 451 &resp); 452 if (ret) 453 return ret; 454 455 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu, 456 resp); 457 458 pbf_info->p1_low = resp & 0xff; 459 pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8; 460 461 req = level; 462 ret = isst_send_mbox_command( 463 cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp); 464 if (ret) 465 return ret; 466 467 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu, resp); 468 469 pbf_info->tdp = resp & 0xffff; 470 471 req = level; 472 ret = isst_send_mbox_command( 473 cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp); 474 if (ret) 475 return ret; 476 477 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu, 478 resp); 479 pbf_info->t_control = (resp >> 8) & 0xff; 480 pbf_info->t_prochot = resp & 0xff; 481 482 return 0; 483 } 484 485 void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info) 486 { 487 free_cpu_set(pbf_info->core_cpumask); 488 } 489 490 int isst_set_pbf_fact_status(int cpu, int pbf, int enable) 491 { 492 struct isst_pkg_ctdp pkg_dev; 493 struct isst_pkg_ctdp_level_info ctdp_level; 494 int current_level; 495 unsigned int req = 0, resp; 496 int ret; 497 498 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 499 if (ret) 500 debug_printf("cpu:%d No support for dynamic ISST\n", cpu); 501 502 current_level = pkg_dev.current_level; 503 504 ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level); 505 if (ret) 506 return ret; 507 508 if (pbf) { 509 if (ctdp_level.fact_enabled) 510 req = BIT(16); 511 512 if (enable) 513 req |= BIT(17); 514 else 515 req &= ~BIT(17); 516 } else { 517 518 if (enable && !ctdp_level.sst_cp_enabled) 519 isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0); 520 521 if (ctdp_level.pbf_enabled) 522 req = BIT(17); 523 524 if (enable) 525 req |= BIT(16); 526 else 527 req &= ~BIT(16); 528 } 529 530 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 531 CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp); 532 if (ret) 533 return ret; 534 535 debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n", 536 cpu, pbf, req); 537 538 return 0; 539 } 540 541 int isst_get_fact_bucket_info(int cpu, int level, 542 struct isst_fact_bucket_info *bucket_info) 543 { 544 unsigned int resp; 545 int i, k, ret; 546 547 for (i = 0; i < 2; ++i) { 548 int j; 549 550 ret = isst_send_mbox_command( 551 cpu, CONFIG_TDP, 552 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0, 553 (i << 8) | level, &resp); 554 if (ret) 555 return ret; 556 557 debug_printf( 558 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n", 559 cpu, i, level, resp); 560 561 for (j = 0; j < 4; ++j) { 562 bucket_info[j + (i * 4)].high_priority_cores_count = 563 (resp >> (j * 8)) & 0xff; 564 } 565 } 566 567 for (k = 0; k < 3; ++k) { 568 for (i = 0; i < 2; ++i) { 569 int j; 570 571 ret = isst_send_mbox_command( 572 cpu, CONFIG_TDP, 573 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0, 574 (k << 16) | (i << 8) | level, &resp); 575 if (ret) 576 return ret; 577 578 debug_printf( 579 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n", 580 cpu, i, level, k, resp); 581 582 for (j = 0; j < 4; ++j) { 583 switch (k) { 584 case 0: 585 bucket_info[j + (i * 4)].sse_trl = 586 (resp >> (j * 8)) & 0xff; 587 break; 588 case 1: 589 bucket_info[j + (i * 4)].avx_trl = 590 (resp >> (j * 8)) & 0xff; 591 break; 592 case 2: 593 bucket_info[j + (i * 4)].avx512_trl = 594 (resp >> (j * 8)) & 0xff; 595 break; 596 default: 597 break; 598 } 599 } 600 } 601 } 602 603 return 0; 604 } 605 606 int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info) 607 { 608 struct isst_pkg_ctdp_level_info ctdp_level; 609 struct isst_pkg_ctdp pkg_dev; 610 unsigned int resp; 611 int j, ret, print; 612 613 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 614 if (ret) { 615 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 616 return ret; 617 } 618 619 if (level > pkg_dev.levels) { 620 isst_display_error_info_message(1, "Invalid level", 1, level); 621 return -1; 622 } 623 624 ret = isst_get_ctdp_control(cpu, level, &ctdp_level); 625 if (ret) 626 return ret; 627 628 if (!ctdp_level.fact_support) { 629 isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level); 630 return -1; 631 } 632 633 ret = isst_send_mbox_command(cpu, CONFIG_TDP, 634 CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0, 635 level, &resp); 636 if (ret) 637 return ret; 638 639 debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n", 640 cpu, resp); 641 642 fact_info->lp_clipping_ratio_license_sse = resp & 0xff; 643 fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff; 644 fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff; 645 646 ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info); 647 if (ret) 648 return ret; 649 650 print = 0; 651 for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) { 652 if (fact_bucket != 0xff && fact_bucket != j) 653 continue; 654 655 if (!fact_info->bucket_info[j].high_priority_cores_count) 656 break; 657 658 print = 1; 659 } 660 if (!print) { 661 isst_display_error_info_message(1, "Invalid bucket", 0, 0); 662 return -1; 663 } 664 665 return 0; 666 } 667 668 int isst_set_trl(int cpu, unsigned long long trl) 669 { 670 int ret; 671 672 if (!trl) 673 trl = 0xFFFFFFFFFFFFFFFFULL; 674 675 ret = isst_send_msr_command(cpu, 0x1AD, 1, &trl); 676 if (ret) 677 return ret; 678 679 return 0; 680 } 681 682 int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl) 683 { 684 unsigned long long msr_trl; 685 int ret; 686 687 if (trl) { 688 msr_trl = trl; 689 } else { 690 struct isst_pkg_ctdp pkg_dev; 691 int trl[8]; 692 int i; 693 694 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 695 if (ret) 696 return ret; 697 698 ret = isst_get_get_trl(cpu, pkg_dev.current_level, 0, trl); 699 if (ret) 700 return ret; 701 702 msr_trl = 0; 703 for (i = 0; i < 8; ++i) { 704 unsigned long long _trl = trl[i]; 705 706 msr_trl |= (_trl << (i * 8)); 707 } 708 } 709 ret = isst_send_msr_command(cpu, 0x1AD, 1, &msr_trl); 710 if (ret) 711 return ret; 712 713 return 0; 714 } 715 716 /* Return 1 if locked */ 717 int isst_get_config_tdp_lock_status(int cpu) 718 { 719 unsigned long long tdp_control = 0; 720 int ret; 721 722 ret = isst_send_msr_command(cpu, 0x64b, 0, &tdp_control); 723 if (ret) 724 return ret; 725 726 ret = !!(tdp_control & BIT(31)); 727 728 return ret; 729 } 730 731 void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev) 732 { 733 int i; 734 735 if (!pkg_dev->processed) 736 return; 737 738 for (i = 0; i < pkg_dev->levels; ++i) { 739 struct isst_pkg_ctdp_level_info *ctdp_level; 740 741 ctdp_level = &pkg_dev->ctdp_level[i]; 742 if (ctdp_level->pbf_support) 743 free_cpu_set(ctdp_level->pbf_info.core_cpumask); 744 free_cpu_set(ctdp_level->core_cpumask); 745 } 746 } 747 748 int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) 749 { 750 int i, ret, valid = 0; 751 752 if (pkg_dev->processed) 753 return 0; 754 755 ret = isst_get_ctdp_levels(cpu, pkg_dev); 756 if (ret) 757 return ret; 758 759 debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n", 760 cpu, pkg_dev->enabled, pkg_dev->current_level, 761 pkg_dev->levels); 762 763 if (tdp_level != 0xff && tdp_level > pkg_dev->levels) { 764 isst_display_error_info_message(1, "Invalid level", 0, 0); 765 return -1; 766 } 767 768 if (!pkg_dev->enabled) 769 isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0); 770 771 for (i = 0; i <= pkg_dev->levels; ++i) { 772 struct isst_pkg_ctdp_level_info *ctdp_level; 773 774 if (tdp_level != 0xff && i != tdp_level) 775 continue; 776 777 debug_printf("cpu:%d Get Information for TDP level:%d\n", cpu, 778 i); 779 ctdp_level = &pkg_dev->ctdp_level[i]; 780 781 ctdp_level->level = i; 782 ctdp_level->control_cpu = cpu; 783 ctdp_level->pkg_id = get_physical_package_id(cpu); 784 ctdp_level->die_id = get_physical_die_id(cpu); 785 786 ret = isst_get_ctdp_control(cpu, i, ctdp_level); 787 if (ret) 788 continue; 789 790 valid = 1; 791 pkg_dev->processed = 1; 792 ctdp_level->processed = 1; 793 794 if (ctdp_level->pbf_support) { 795 ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info); 796 if (!ret) 797 ctdp_level->pbf_found = 1; 798 } 799 800 if (ctdp_level->fact_support) { 801 ret = isst_get_fact_info(cpu, i, 0xff, 802 &ctdp_level->fact_info); 803 if (ret) 804 return ret; 805 } 806 807 if (!pkg_dev->enabled) { 808 int freq; 809 810 freq = get_cpufreq_base_freq(cpu); 811 if (freq > 0) { 812 ctdp_level->sse_p1 = freq / 100000; 813 ctdp_level->tdp_ratio = ctdp_level->sse_p1; 814 } 815 816 isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores); 817 isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info); 818 continue; 819 } 820 821 ret = isst_get_tdp_info(cpu, i, ctdp_level); 822 if (ret) 823 return ret; 824 825 ret = isst_get_pwr_info(cpu, i, ctdp_level); 826 if (ret) 827 return ret; 828 829 ret = isst_get_tjmax_info(cpu, i, ctdp_level); 830 if (ret) 831 return ret; 832 833 ctdp_level->core_cpumask_size = 834 alloc_cpu_set(&ctdp_level->core_cpumask); 835 ret = isst_get_coremask_info(cpu, i, ctdp_level); 836 if (ret) 837 return ret; 838 839 ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info); 840 if (ret) 841 return ret; 842 843 ret = isst_get_get_trl(cpu, i, 0, 844 ctdp_level->trl_sse_active_cores); 845 if (ret) 846 return ret; 847 848 ret = isst_get_get_trl(cpu, i, 1, 849 ctdp_level->trl_avx_active_cores); 850 if (ret) 851 return ret; 852 853 ret = isst_get_get_trl(cpu, i, 2, 854 ctdp_level->trl_avx_512_active_cores); 855 if (ret) 856 return ret; 857 858 isst_get_uncore_p0_p1_info(cpu, i, ctdp_level); 859 isst_get_p1_info(cpu, i, ctdp_level); 860 isst_get_uncore_mem_freq(cpu, i, ctdp_level); 861 } 862 863 if (!valid) 864 isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, cpu); 865 866 return 0; 867 } 868 869 int isst_clos_get_clos_information(int cpu, int *enable, int *type) 870 { 871 unsigned int resp; 872 int ret; 873 874 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, 875 &resp); 876 if (ret) 877 return ret; 878 879 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp); 880 881 if (resp & BIT(1)) 882 *enable = 1; 883 else 884 *enable = 0; 885 886 if (resp & BIT(2)) 887 *type = 1; 888 else 889 *type = 0; 890 891 return 0; 892 } 893 894 int isst_pm_qos_config(int cpu, int enable_clos, int priority_type) 895 { 896 unsigned int req, resp; 897 int ret; 898 899 if (!enable_clos) { 900 struct isst_pkg_ctdp pkg_dev; 901 struct isst_pkg_ctdp_level_info ctdp_level; 902 903 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 904 if (ret) { 905 debug_printf("isst_get_ctdp_levels\n"); 906 return ret; 907 } 908 909 ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, 910 &ctdp_level); 911 if (ret) 912 return ret; 913 914 if (ctdp_level.fact_enabled) { 915 debug_printf("Turbo-freq feature must be disabled first\n"); 916 return -EINVAL; 917 } 918 ret = isst_write_pm_config(cpu, 0); 919 if (ret) 920 isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error\n", 0, 0); 921 } else { 922 ret = isst_write_pm_config(cpu, 1); 923 if (ret) 924 isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error\n", 0, 0); 925 } 926 927 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, 928 &resp); 929 if (ret) { 930 isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0); 931 return ret; 932 } 933 934 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp); 935 936 req = resp; 937 938 if (enable_clos) 939 req = req | BIT(1); 940 else 941 req = req & ~BIT(1); 942 943 if (priority_type > 1) 944 isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0); 945 946 if (priority_type) 947 req = req | BIT(2); 948 else 949 req = req & ~BIT(2); 950 951 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 952 BIT(MBOX_CMD_WRITE_BIT), req, &resp); 953 if (ret) 954 return ret; 955 956 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu, 957 priority_type, req); 958 959 return 0; 960 } 961 962 int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config) 963 { 964 unsigned int resp; 965 int ret; 966 967 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0, 968 &resp); 969 if (ret) 970 return ret; 971 972 clos_config->pkg_id = get_physical_package_id(cpu); 973 clos_config->die_id = get_physical_die_id(cpu); 974 975 clos_config->epp = resp & 0x0f; 976 clos_config->clos_prop_prio = (resp >> 4) & 0x0f; 977 clos_config->clos_min = (resp >> 8) & 0xff; 978 clos_config->clos_max = (resp >> 16) & 0xff; 979 clos_config->clos_desired = (resp >> 24) & 0xff; 980 981 return 0; 982 } 983 984 int isst_set_clos(int cpu, int clos, struct isst_clos_config *clos_config) 985 { 986 unsigned int req, resp; 987 unsigned int param; 988 int ret; 989 990 req = clos_config->epp & 0x0f; 991 req |= (clos_config->clos_prop_prio & 0x0f) << 4; 992 req |= (clos_config->clos_min & 0xff) << 8; 993 req |= (clos_config->clos_max & 0xff) << 16; 994 req |= (clos_config->clos_desired & 0xff) << 24; 995 996 param = BIT(MBOX_CMD_WRITE_BIT) | clos; 997 998 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req, 999 &resp); 1000 if (ret) 1001 return ret; 1002 1003 debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", cpu, param, req); 1004 1005 return 0; 1006 } 1007 1008 int isst_clos_get_assoc_status(int cpu, int *clos_id) 1009 { 1010 unsigned int resp; 1011 unsigned int param; 1012 int core_id, ret; 1013 1014 core_id = find_phy_core_num(cpu); 1015 param = core_id; 1016 1017 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0, 1018 &resp); 1019 if (ret) 1020 return ret; 1021 1022 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", cpu, param, 1023 resp); 1024 *clos_id = (resp >> 16) & 0x03; 1025 1026 return 0; 1027 } 1028 1029 int isst_clos_associate(int cpu, int clos_id) 1030 { 1031 unsigned int req, resp; 1032 unsigned int param; 1033 int core_id, ret; 1034 1035 req = (clos_id & 0x03) << 16; 1036 core_id = find_phy_core_num(cpu); 1037 param = BIT(MBOX_CMD_WRITE_BIT) | core_id; 1038 1039 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 1040 req, &resp); 1041 if (ret) 1042 return ret; 1043 1044 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", cpu, param, 1045 req); 1046 1047 return 0; 1048 } 1049