Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Intel Speed Select -- Enumerate and control features
0004  * Copyright (c) 2019 Intel Corporation.
0005  */
0006 
0007 #include "isst.h"
0008 
0009 int isst_write_pm_config(int cpu, int cp_state)
0010 {
0011     unsigned int req, resp;
0012     int ret;
0013 
0014     if (cp_state)
0015         req = BIT(16);
0016     else
0017         req = 0;
0018 
0019     ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
0020                      &resp);
0021     if (ret)
0022         return ret;
0023 
0024     debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp);
0025 
0026     return 0;
0027 }
0028 
0029 int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
0030 {
0031     unsigned int resp;
0032     int ret;
0033 
0034     ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
0035                      &resp);
0036     if (ret)
0037         return ret;
0038 
0039     debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp);
0040 
0041     *cp_state = resp & BIT(16);
0042     *cp_cap = resp & BIT(0) ? 1 : 0;
0043 
0044     return 0;
0045 }
0046 
0047 int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
0048 {
0049     unsigned int resp;
0050     int ret;
0051 
0052     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0053                      CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
0054     if (ret) {
0055         pkg_dev->levels = 0;
0056         pkg_dev->locked = 1;
0057         pkg_dev->current_level = 0;
0058         pkg_dev->version = 0;
0059         pkg_dev->enabled = 0;
0060         return 0;
0061     }
0062 
0063     debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
0064 
0065     pkg_dev->version = resp & 0xff;
0066     pkg_dev->levels = (resp >> 8) & 0xff;
0067     pkg_dev->current_level = (resp >> 16) & 0xff;
0068     pkg_dev->locked = !!(resp & BIT(24));
0069     pkg_dev->enabled = !!(resp & BIT(31));
0070 
0071     return 0;
0072 }
0073 
0074 int isst_get_ctdp_control(int cpu, int config_index,
0075               struct isst_pkg_ctdp_level_info *ctdp_level)
0076 {
0077     int cp_state, cp_cap;
0078     unsigned int resp;
0079     int ret;
0080 
0081     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0082                      CONFIG_TDP_GET_TDP_CONTROL, 0,
0083                      config_index, &resp);
0084     if (ret)
0085         return ret;
0086 
0087     ctdp_level->fact_support = resp & BIT(0);
0088     ctdp_level->pbf_support = !!(resp & BIT(1));
0089     ctdp_level->fact_enabled = !!(resp & BIT(16));
0090     ctdp_level->pbf_enabled = !!(resp & BIT(17));
0091 
0092     ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
0093     if (ret) {
0094         debug_printf("cpu:%d pm_config is not supported \n", cpu);
0095     } else {
0096         debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap);
0097         ctdp_level->sst_cp_support = cp_cap;
0098         ctdp_level->sst_cp_enabled = cp_state;
0099     }
0100 
0101     debug_printf(
0102         "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
0103         cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
0104         ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
0105 
0106     return 0;
0107 }
0108 
0109 int isst_get_tdp_info(int cpu, int config_index,
0110               struct isst_pkg_ctdp_level_info *ctdp_level)
0111 {
0112     unsigned int resp;
0113     int ret;
0114 
0115     ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
0116                      0, config_index, &resp);
0117     if (ret) {
0118         isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
0119         return ret;
0120     }
0121 
0122     ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
0123     ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
0124 
0125     debug_printf(
0126         "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
0127         cpu, config_index, resp, ctdp_level->tdp_ratio,
0128         ctdp_level->pkg_tdp);
0129     return 0;
0130 }
0131 
0132 int isst_get_pwr_info(int cpu, int config_index,
0133               struct isst_pkg_ctdp_level_info *ctdp_level)
0134 {
0135     unsigned int resp;
0136     int ret;
0137 
0138     ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
0139                      0, config_index, &resp);
0140     if (ret)
0141         return ret;
0142 
0143     ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
0144     ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
0145 
0146     debug_printf(
0147         "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
0148         cpu, config_index, resp, ctdp_level->pkg_max_power,
0149         ctdp_level->pkg_min_power);
0150 
0151     return 0;
0152 }
0153 
0154 void isst_get_uncore_p0_p1_info(int cpu, int config_index,
0155                 struct isst_pkg_ctdp_level_info *ctdp_level)
0156 {
0157     unsigned int resp;
0158     int ret;
0159     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0160                      CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
0161                      config_index, &resp);
0162     if (ret) {
0163         ctdp_level->uncore_p0 = 0;
0164         ctdp_level->uncore_p1 = 0;
0165         return;
0166     }
0167 
0168     ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
0169     ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
0170     debug_printf(
0171         "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
0172         cpu, config_index, resp, ctdp_level->uncore_p0,
0173         ctdp_level->uncore_p1);
0174 }
0175 
0176 void isst_get_p1_info(int cpu, int config_index,
0177               struct isst_pkg_ctdp_level_info *ctdp_level)
0178 {
0179     unsigned int resp;
0180     int ret;
0181     ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
0182                      config_index, &resp);
0183     if (ret) {
0184         ctdp_level->sse_p1 = 0;
0185         ctdp_level->avx2_p1 = 0;
0186         ctdp_level->avx512_p1 = 0;
0187         return;
0188     }
0189 
0190     ctdp_level->sse_p1 = resp & GENMASK(7, 0);
0191     ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
0192     ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
0193     debug_printf(
0194         "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
0195         cpu, config_index, resp, ctdp_level->sse_p1,
0196         ctdp_level->avx2_p1, ctdp_level->avx512_p1);
0197 }
0198 
0199 void isst_get_uncore_mem_freq(int cpu, int config_index,
0200                   struct isst_pkg_ctdp_level_info *ctdp_level)
0201 {
0202     unsigned int resp;
0203     int ret;
0204 
0205     ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
0206                      0, config_index, &resp);
0207     if (ret) {
0208         ctdp_level->mem_freq = 0;
0209         return;
0210     }
0211 
0212     ctdp_level->mem_freq = resp & GENMASK(7, 0);
0213     if (is_spr_platform()) {
0214         ctdp_level->mem_freq *= 200;
0215     } else if (is_icx_platform()) {
0216         if (ctdp_level->mem_freq < 7) {
0217             ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
0218             ctdp_level->mem_freq /= 10;
0219             if (ctdp_level->mem_freq % 10 > 5)
0220                 ctdp_level->mem_freq++;
0221         } else {
0222             ctdp_level->mem_freq = 0;
0223         }
0224     } else {
0225         ctdp_level->mem_freq = 0;
0226     }
0227     debug_printf(
0228         "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
0229         cpu, config_index, resp, ctdp_level->mem_freq);
0230 }
0231 
0232 int isst_get_tjmax_info(int cpu, int config_index,
0233             struct isst_pkg_ctdp_level_info *ctdp_level)
0234 {
0235     unsigned int resp;
0236     int ret;
0237 
0238     ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
0239                      0, config_index, &resp);
0240     if (ret)
0241         return ret;
0242 
0243     ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
0244 
0245     debug_printf(
0246         "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
0247         cpu, config_index, resp, ctdp_level->t_proc_hot);
0248 
0249     return 0;
0250 }
0251 
0252 int isst_get_coremask_info(int cpu, int config_index,
0253                struct isst_pkg_ctdp_level_info *ctdp_level)
0254 {
0255     unsigned int resp;
0256     int i, ret;
0257 
0258     ctdp_level->cpu_count = 0;
0259     for (i = 0; i < 2; ++i) {
0260         unsigned long long mask;
0261         int cpu_count = 0;
0262 
0263         ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0264                          CONFIG_TDP_GET_CORE_MASK, 0,
0265                          (i << 8) | config_index, &resp);
0266         if (ret)
0267             return ret;
0268 
0269         debug_printf(
0270             "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
0271             cpu, config_index, i, resp);
0272 
0273         mask = (unsigned long long)resp << (32 * i);
0274         set_cpu_mask_from_punit_coremask(cpu, mask,
0275                          ctdp_level->core_cpumask_size,
0276                          ctdp_level->core_cpumask,
0277                          &cpu_count);
0278         ctdp_level->cpu_count += cpu_count;
0279         debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu,
0280                  config_index, i, ctdp_level->cpu_count);
0281     }
0282 
0283     return 0;
0284 }
0285 
0286 int isst_get_get_trl_from_msr(int cpu, int *trl)
0287 {
0288     unsigned long long msr_trl;
0289     int ret;
0290 
0291     ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
0292     if (ret)
0293         return ret;
0294 
0295     trl[0] = msr_trl & GENMASK(7, 0);
0296     trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
0297     trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
0298     trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
0299     trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
0300     trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
0301     trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
0302     trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
0303 
0304     return 0;
0305 }
0306 
0307 int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
0308 {
0309     unsigned int req, resp;
0310     int ret;
0311 
0312     req = level | (avx_level << 16);
0313     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0314                      CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
0315                      &resp);
0316     if (ret)
0317         return ret;
0318 
0319     debug_printf(
0320         "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
0321         cpu, req, resp);
0322 
0323     trl[0] = resp & GENMASK(7, 0);
0324     trl[1] = (resp & GENMASK(15, 8)) >> 8;
0325     trl[2] = (resp & GENMASK(23, 16)) >> 16;
0326     trl[3] = (resp & GENMASK(31, 24)) >> 24;
0327 
0328     req = level | BIT(8) | (avx_level << 16);
0329     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0330                      CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
0331                      &resp);
0332     if (ret)
0333         return ret;
0334 
0335     debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu,
0336              req, resp);
0337 
0338     trl[4] = resp & GENMASK(7, 0);
0339     trl[5] = (resp & GENMASK(15, 8)) >> 8;
0340     trl[6] = (resp & GENMASK(23, 16)) >> 16;
0341     trl[7] = (resp & GENMASK(31, 24)) >> 24;
0342 
0343     return 0;
0344 }
0345 
0346 int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
0347 {
0348     int ret;
0349 
0350     debug_printf("cpu:%d bucket info via MSR\n", cpu);
0351 
0352     *buckets_info = 0;
0353 
0354     ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
0355     if (ret)
0356         return ret;
0357 
0358     debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu,
0359              *buckets_info);
0360 
0361     return 0;
0362 }
0363 
0364 int isst_set_tdp_level_msr(int cpu, int tdp_level)
0365 {
0366     unsigned long long level = tdp_level;
0367     int ret;
0368 
0369     debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
0370 
0371     if (isst_get_config_tdp_lock_status(cpu)) {
0372         isst_display_error_info_message(1, "tdp_locked", 0, 0);
0373         return -1;
0374     }
0375 
0376     if (tdp_level > 2)
0377         return -1; /* invalid value */
0378 
0379     ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
0380     if (ret)
0381         return ret;
0382 
0383     debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level);
0384 
0385     return 0;
0386 }
0387 
0388 int isst_set_tdp_level(int cpu, int tdp_level)
0389 {
0390     unsigned int resp;
0391     int ret;
0392 
0393 
0394     if (isst_get_config_tdp_lock_status(cpu)) {
0395         isst_display_error_info_message(1, "TDP is locked", 0, 0);
0396         return -1;
0397 
0398     }
0399 
0400     ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
0401                      tdp_level, &resp);
0402     if (ret) {
0403         isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
0404         return ret;
0405     }
0406 
0407     return 0;
0408 }
0409 
0410 int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
0411 {
0412     struct isst_pkg_ctdp_level_info ctdp_level;
0413     struct isst_pkg_ctdp pkg_dev;
0414     int i, ret, max_punit_core, max_mask_index;
0415     unsigned int req, resp;
0416 
0417     ret = isst_get_ctdp_levels(cpu, &pkg_dev);
0418     if (ret) {
0419         isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
0420         return ret;
0421     }
0422 
0423     if (level > pkg_dev.levels) {
0424         isst_display_error_info_message(1, "Invalid level", 1, level);
0425         return -1;
0426     }
0427 
0428     ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
0429     if (ret)
0430         return ret;
0431 
0432     if (!ctdp_level.pbf_support) {
0433         isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level);
0434         return -1;
0435     }
0436 
0437     pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
0438 
0439     max_punit_core = get_max_punit_core_id(get_physical_package_id(cpu), get_physical_die_id(cpu));
0440     max_mask_index = max_punit_core > 32 ? 2 : 1;
0441 
0442     for (i = 0; i < max_mask_index; ++i) {
0443         unsigned long long mask;
0444         int count;
0445 
0446         ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0447                          CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
0448                          0, (i << 8) | level, &resp);
0449         if (ret)
0450             break;
0451 
0452         debug_printf(
0453             "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
0454             cpu, resp);
0455 
0456         mask = (unsigned long long)resp << (32 * i);
0457         set_cpu_mask_from_punit_coremask(cpu, mask,
0458                          pbf_info->core_cpumask_size,
0459                          pbf_info->core_cpumask,
0460                          &count);
0461     }
0462 
0463     req = level;
0464     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0465                      CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
0466                      &resp);
0467     if (ret)
0468         return ret;
0469 
0470     debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu,
0471              resp);
0472 
0473     pbf_info->p1_low = resp & 0xff;
0474     pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
0475 
0476     req = level;
0477     ret = isst_send_mbox_command(
0478         cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
0479     if (ret)
0480         return ret;
0481 
0482     debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu, resp);
0483 
0484     pbf_info->tdp = resp & 0xffff;
0485 
0486     req = level;
0487     ret = isst_send_mbox_command(
0488         cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
0489     if (ret)
0490         return ret;
0491 
0492     debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu,
0493              resp);
0494     pbf_info->t_control = (resp >> 8) & 0xff;
0495     pbf_info->t_prochot = resp & 0xff;
0496 
0497     return 0;
0498 }
0499 
0500 void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
0501 {
0502     free_cpu_set(pbf_info->core_cpumask);
0503 }
0504 
0505 int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
0506 {
0507     struct isst_pkg_ctdp pkg_dev;
0508     struct isst_pkg_ctdp_level_info ctdp_level;
0509     int current_level;
0510     unsigned int req = 0, resp;
0511     int ret;
0512 
0513     ret = isst_get_ctdp_levels(cpu, &pkg_dev);
0514     if (ret)
0515         debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
0516 
0517     current_level = pkg_dev.current_level;
0518 
0519     ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level);
0520     if (ret)
0521         return ret;
0522 
0523     if (pbf) {
0524         if (ctdp_level.fact_enabled)
0525             req = BIT(16);
0526 
0527         if (enable)
0528             req |= BIT(17);
0529         else
0530             req &= ~BIT(17);
0531     } else {
0532 
0533         if (enable && !ctdp_level.sst_cp_enabled)
0534             isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
0535 
0536         if (ctdp_level.pbf_enabled)
0537             req = BIT(17);
0538 
0539         if (enable)
0540             req |= BIT(16);
0541         else
0542             req &= ~BIT(16);
0543     }
0544 
0545     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0546                      CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
0547     if (ret)
0548         return ret;
0549 
0550     debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
0551              cpu, pbf, req);
0552 
0553     return 0;
0554 }
0555 
0556 int isst_get_fact_bucket_info(int cpu, int level,
0557                   struct isst_fact_bucket_info *bucket_info)
0558 {
0559     unsigned int resp;
0560     int i, k, ret;
0561 
0562     for (i = 0; i < 2; ++i) {
0563         int j;
0564 
0565         ret = isst_send_mbox_command(
0566             cpu, CONFIG_TDP,
0567             CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
0568             (i << 8) | level, &resp);
0569         if (ret)
0570             return ret;
0571 
0572         debug_printf(
0573             "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
0574             cpu, i, level, resp);
0575 
0576         for (j = 0; j < 4; ++j) {
0577             bucket_info[j + (i * 4)].high_priority_cores_count =
0578                 (resp >> (j * 8)) & 0xff;
0579         }
0580     }
0581 
0582     for (k = 0; k < 3; ++k) {
0583         for (i = 0; i < 2; ++i) {
0584             int j;
0585 
0586             ret = isst_send_mbox_command(
0587                 cpu, CONFIG_TDP,
0588                 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
0589                 (k << 16) | (i << 8) | level, &resp);
0590             if (ret)
0591                 return ret;
0592 
0593             debug_printf(
0594                 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
0595                 cpu, i, level, k, resp);
0596 
0597             for (j = 0; j < 4; ++j) {
0598                 switch (k) {
0599                 case 0:
0600                     bucket_info[j + (i * 4)].sse_trl =
0601                         (resp >> (j * 8)) & 0xff;
0602                     break;
0603                 case 1:
0604                     bucket_info[j + (i * 4)].avx_trl =
0605                         (resp >> (j * 8)) & 0xff;
0606                     break;
0607                 case 2:
0608                     bucket_info[j + (i * 4)].avx512_trl =
0609                         (resp >> (j * 8)) & 0xff;
0610                     break;
0611                 default:
0612                     break;
0613                 }
0614             }
0615         }
0616     }
0617 
0618     return 0;
0619 }
0620 
0621 int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info)
0622 {
0623     struct isst_pkg_ctdp_level_info ctdp_level;
0624     struct isst_pkg_ctdp pkg_dev;
0625     unsigned int resp;
0626     int j, ret, print;
0627 
0628     ret = isst_get_ctdp_levels(cpu, &pkg_dev);
0629     if (ret) {
0630         isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
0631         return ret;
0632     }
0633 
0634     if (level > pkg_dev.levels) {
0635         isst_display_error_info_message(1, "Invalid level", 1, level);
0636         return -1;
0637     }
0638 
0639     ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
0640     if (ret)
0641         return ret;
0642 
0643     if (!ctdp_level.fact_support) {
0644         isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
0645         return -1;
0646     }
0647 
0648     ret = isst_send_mbox_command(cpu, CONFIG_TDP,
0649                      CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
0650                      level, &resp);
0651     if (ret)
0652         return ret;
0653 
0654     debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
0655              cpu, resp);
0656 
0657     fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
0658     fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
0659     fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
0660 
0661     ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
0662     if (ret)
0663         return ret;
0664 
0665     print = 0;
0666     for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
0667         if (fact_bucket != 0xff && fact_bucket != j)
0668             continue;
0669 
0670         if (!fact_info->bucket_info[j].high_priority_cores_count)
0671             break;
0672 
0673         print = 1;
0674     }
0675     if (!print) {
0676         isst_display_error_info_message(1, "Invalid bucket", 0, 0);
0677         return -1;
0678     }
0679 
0680     return 0;
0681 }
0682 
0683 int isst_get_trl(int cpu, unsigned long long *trl)
0684 {
0685     int ret;
0686 
0687     ret = isst_send_msr_command(cpu, 0x1AD, 0, trl);
0688     if (ret)
0689         return ret;
0690 
0691     return 0;
0692 }
0693 
0694 int isst_set_trl(int cpu, unsigned long long trl)
0695 {
0696     int ret;
0697 
0698     if (!trl)
0699         trl = 0xFFFFFFFFFFFFFFFFULL;
0700 
0701     ret = isst_send_msr_command(cpu, 0x1AD, 1, &trl);
0702     if (ret)
0703         return ret;
0704 
0705     return 0;
0706 }
0707 
0708 int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
0709 {
0710     unsigned long long msr_trl;
0711     int ret;
0712 
0713     if (trl) {
0714         msr_trl = trl;
0715     } else {
0716         struct isst_pkg_ctdp pkg_dev;
0717         int trl[8];
0718         int i;
0719 
0720         ret = isst_get_ctdp_levels(cpu, &pkg_dev);
0721         if (ret)
0722             return ret;
0723 
0724         ret = isst_get_get_trl(cpu, pkg_dev.current_level, 0, trl);
0725         if (ret)
0726             return ret;
0727 
0728         msr_trl = 0;
0729         for (i = 0; i < 8; ++i) {
0730             unsigned long long _trl = trl[i];
0731 
0732             msr_trl |= (_trl << (i * 8));
0733         }
0734     }
0735     ret = isst_send_msr_command(cpu, 0x1AD, 1, &msr_trl);
0736     if (ret)
0737         return ret;
0738 
0739     return 0;
0740 }
0741 
0742 /* Return 1 if locked */
0743 int isst_get_config_tdp_lock_status(int cpu)
0744 {
0745     unsigned long long tdp_control = 0;
0746     int ret;
0747 
0748     ret = isst_send_msr_command(cpu, 0x64b, 0, &tdp_control);
0749     if (ret)
0750         return ret;
0751 
0752     ret = !!(tdp_control & BIT(31));
0753 
0754     return ret;
0755 }
0756 
0757 void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev)
0758 {
0759     int i;
0760 
0761     if (!pkg_dev->processed)
0762         return;
0763 
0764     for (i = 0; i < pkg_dev->levels; ++i) {
0765         struct isst_pkg_ctdp_level_info *ctdp_level;
0766 
0767         ctdp_level = &pkg_dev->ctdp_level[i];
0768         if (ctdp_level->pbf_support)
0769             free_cpu_set(ctdp_level->pbf_info.core_cpumask);
0770         free_cpu_set(ctdp_level->core_cpumask);
0771     }
0772 }
0773 
0774 int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
0775 {
0776     int i, ret, valid = 0;
0777 
0778     if (pkg_dev->processed)
0779         return 0;
0780 
0781     ret = isst_get_ctdp_levels(cpu, pkg_dev);
0782     if (ret)
0783         return ret;
0784 
0785     debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
0786              cpu, pkg_dev->enabled, pkg_dev->current_level,
0787              pkg_dev->levels);
0788 
0789     if (tdp_level != 0xff && tdp_level > pkg_dev->levels) {
0790         isst_display_error_info_message(1, "Invalid level", 0, 0);
0791         return -1;
0792     }
0793 
0794     if (!pkg_dev->enabled)
0795         isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0);
0796 
0797     for (i = 0; i <= pkg_dev->levels; ++i) {
0798         struct isst_pkg_ctdp_level_info *ctdp_level;
0799 
0800         if (tdp_level != 0xff && i != tdp_level)
0801             continue;
0802 
0803         debug_printf("cpu:%d Get Information for TDP level:%d\n", cpu,
0804                  i);
0805         ctdp_level = &pkg_dev->ctdp_level[i];
0806 
0807         ctdp_level->level = i;
0808         ctdp_level->control_cpu = cpu;
0809         ctdp_level->pkg_id = get_physical_package_id(cpu);
0810         ctdp_level->die_id = get_physical_die_id(cpu);
0811 
0812         ret = isst_get_ctdp_control(cpu, i, ctdp_level);
0813         if (ret)
0814             continue;
0815 
0816         valid = 1;
0817         pkg_dev->processed = 1;
0818         ctdp_level->processed = 1;
0819 
0820         if (ctdp_level->pbf_support) {
0821             ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
0822             if (!ret)
0823                 ctdp_level->pbf_found = 1;
0824         }
0825 
0826         if (ctdp_level->fact_support) {
0827             ret = isst_get_fact_info(cpu, i, 0xff,
0828                          &ctdp_level->fact_info);
0829             if (ret)
0830                 return ret;
0831         }
0832 
0833         if (!pkg_dev->enabled && is_skx_based_platform()) {
0834             int freq;
0835 
0836             freq = get_cpufreq_base_freq(cpu);
0837             if (freq > 0) {
0838                 ctdp_level->sse_p1 = freq / 100000;
0839                 ctdp_level->tdp_ratio = ctdp_level->sse_p1;
0840             }
0841 
0842             isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores);
0843             isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
0844             continue;
0845         }
0846 
0847         ret = isst_get_tdp_info(cpu, i, ctdp_level);
0848         if (ret)
0849             return ret;
0850 
0851         ret = isst_get_pwr_info(cpu, i, ctdp_level);
0852         if (ret)
0853             return ret;
0854 
0855         ret = isst_get_tjmax_info(cpu, i, ctdp_level);
0856         if (ret)
0857             return ret;
0858 
0859         ctdp_level->core_cpumask_size =
0860             alloc_cpu_set(&ctdp_level->core_cpumask);
0861         ret = isst_get_coremask_info(cpu, i, ctdp_level);
0862         if (ret)
0863             return ret;
0864 
0865         ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
0866         if (ret)
0867             return ret;
0868 
0869         ret = isst_get_get_trl(cpu, i, 0,
0870                        ctdp_level->trl_sse_active_cores);
0871         if (ret)
0872             return ret;
0873 
0874         ret = isst_get_get_trl(cpu, i, 1,
0875                        ctdp_level->trl_avx_active_cores);
0876         if (ret)
0877             return ret;
0878 
0879         ret = isst_get_get_trl(cpu, i, 2,
0880                        ctdp_level->trl_avx_512_active_cores);
0881         if (ret)
0882             return ret;
0883 
0884         isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
0885         isst_get_p1_info(cpu, i, ctdp_level);
0886         isst_get_uncore_mem_freq(cpu, i, ctdp_level);
0887     }
0888 
0889     if (!valid)
0890         isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, cpu);
0891 
0892     return 0;
0893 }
0894 
0895 int isst_clos_get_clos_information(int cpu, int *enable, int *type)
0896 {
0897     unsigned int resp;
0898     int ret;
0899 
0900     ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
0901                      &resp);
0902     if (ret)
0903         return ret;
0904 
0905     debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
0906 
0907     if (resp & BIT(1))
0908         *enable = 1;
0909     else
0910         *enable = 0;
0911 
0912     if (resp & BIT(2))
0913         *type = 1;
0914     else
0915         *type = 0;
0916 
0917     return 0;
0918 }
0919 
0920 int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
0921 {
0922     unsigned int req, resp;
0923     int ret;
0924 
0925     if (!enable_clos) {
0926         struct isst_pkg_ctdp pkg_dev;
0927         struct isst_pkg_ctdp_level_info ctdp_level;
0928 
0929         ret = isst_get_ctdp_levels(cpu, &pkg_dev);
0930         if (ret) {
0931             debug_printf("isst_get_ctdp_levels\n");
0932             return ret;
0933         }
0934 
0935         ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
0936                         &ctdp_level);
0937         if (ret)
0938             return ret;
0939 
0940         if (ctdp_level.fact_enabled) {
0941             isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
0942             return -EINVAL;
0943         }
0944         ret = isst_write_pm_config(cpu, 0);
0945         if (ret)
0946             isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
0947     } else {
0948         ret = isst_write_pm_config(cpu, 1);
0949         if (ret)
0950             isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
0951     }
0952 
0953     ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
0954                      &resp);
0955     if (ret) {
0956         isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
0957         return ret;
0958     }
0959 
0960     debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
0961 
0962     req = resp;
0963 
0964     if (enable_clos)
0965         req = req | BIT(1);
0966     else
0967         req = req & ~BIT(1);
0968 
0969     if (priority_type > 1)
0970         isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
0971 
0972     if (priority_type)
0973         req = req | BIT(2);
0974     else
0975         req = req & ~BIT(2);
0976 
0977     ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
0978                      BIT(MBOX_CMD_WRITE_BIT), req, &resp);
0979     if (ret)
0980         return ret;
0981 
0982     debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu,
0983              priority_type, req);
0984 
0985     return 0;
0986 }
0987 
0988 int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config)
0989 {
0990     unsigned int resp;
0991     int ret;
0992 
0993     ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
0994                      &resp);
0995     if (ret)
0996         return ret;
0997 
0998     clos_config->pkg_id = get_physical_package_id(cpu);
0999     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 
1010 int 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 
1034 int 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 
1055 int 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 }