linux/tools/power/x86/intel-speed-select/isst-core.c
<<
>>
Prefs
   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}
1075