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