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