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