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