1*6f987b59SSivaprasad Tummala /* SPDX-License-Identifier: BSD-3-Clause 2*6f987b59SSivaprasad Tummala * Copyright(c) 2010-2021 Intel Corporation 3*6f987b59SSivaprasad Tummala * Copyright(c) 2021 Arm Limited 4*6f987b59SSivaprasad Tummala * Copyright(c) 2024 Advanced Micro Devices, Inc. 5*6f987b59SSivaprasad Tummala */ 6*6f987b59SSivaprasad Tummala 7*6f987b59SSivaprasad Tummala #include <stdlib.h> 8*6f987b59SSivaprasad Tummala 9*6f987b59SSivaprasad Tummala #include <rte_memcpy.h> 10*6f987b59SSivaprasad Tummala #include <rte_stdatomic.h> 11*6f987b59SSivaprasad Tummala 12*6f987b59SSivaprasad Tummala #include "amd_pstate_cpufreq.h" 13*6f987b59SSivaprasad Tummala #include "power_common.h" 14*6f987b59SSivaprasad Tummala 15*6f987b59SSivaprasad Tummala /* macros used for rounding frequency to nearest 1000 */ 16*6f987b59SSivaprasad Tummala #define FREQ_ROUNDING_DELTA 500 17*6f987b59SSivaprasad Tummala #define ROUND_FREQ_TO_N_1000 1000 18*6f987b59SSivaprasad Tummala 19*6f987b59SSivaprasad Tummala #define POWER_CONVERT_TO_DECIMAL 10 20*6f987b59SSivaprasad Tummala 21*6f987b59SSivaprasad Tummala #define POWER_GOVERNOR_USERSPACE "userspace" 22*6f987b59SSivaprasad Tummala #define POWER_SYSFILE_SETSPEED \ 23*6f987b59SSivaprasad Tummala "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_setspeed" 24*6f987b59SSivaprasad Tummala #define POWER_SYSFILE_SCALING_MAX_FREQ \ 25*6f987b59SSivaprasad Tummala "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_max_freq" 26*6f987b59SSivaprasad Tummala #define POWER_SYSFILE_SCALING_MIN_FREQ \ 27*6f987b59SSivaprasad Tummala "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_min_freq" 28*6f987b59SSivaprasad Tummala #define POWER_SYSFILE_HIGHEST_PERF \ 29*6f987b59SSivaprasad Tummala "/sys/devices/system/cpu/cpu%u/acpi_cppc/highest_perf" 30*6f987b59SSivaprasad Tummala #define POWER_SYSFILE_NOMINAL_PERF \ 31*6f987b59SSivaprasad Tummala "/sys/devices/system/cpu/cpu%u/acpi_cppc/nominal_perf" 32*6f987b59SSivaprasad Tummala #define POWER_SYSFILE_NOMINAL_FREQ \ 33*6f987b59SSivaprasad Tummala "/sys/devices/system/cpu/cpu%u/acpi_cppc/nominal_freq" 34*6f987b59SSivaprasad Tummala 35*6f987b59SSivaprasad Tummala #define POWER_AMD_PSTATE_DRIVER "amd-pstate" 36*6f987b59SSivaprasad Tummala #define BUS_FREQ 1000 /* khz */ 37*6f987b59SSivaprasad Tummala 38*6f987b59SSivaprasad Tummala enum power_state { 39*6f987b59SSivaprasad Tummala POWER_IDLE = 0, 40*6f987b59SSivaprasad Tummala POWER_ONGOING, 41*6f987b59SSivaprasad Tummala POWER_USED, 42*6f987b59SSivaprasad Tummala POWER_UNKNOWN 43*6f987b59SSivaprasad Tummala }; 44*6f987b59SSivaprasad Tummala 45*6f987b59SSivaprasad Tummala /** 46*6f987b59SSivaprasad Tummala * Power info per lcore. 47*6f987b59SSivaprasad Tummala */ 48*6f987b59SSivaprasad Tummala struct __rte_cache_aligned amd_pstate_power_info { 49*6f987b59SSivaprasad Tummala uint32_t lcore_id; /**< Logical core id */ 50*6f987b59SSivaprasad Tummala RTE_ATOMIC(uint32_t) state; /**< Power in use state */ 51*6f987b59SSivaprasad Tummala FILE *f; /**< FD of scaling_setspeed */ 52*6f987b59SSivaprasad Tummala char governor_ori[28]; /**< Original governor name */ 53*6f987b59SSivaprasad Tummala uint32_t curr_idx; /**< Freq index in freqs array */ 54*6f987b59SSivaprasad Tummala uint32_t nom_idx; /**< Nominal index in freqs array */ 55*6f987b59SSivaprasad Tummala uint32_t highest_perf; /**< system wide max freq */ 56*6f987b59SSivaprasad Tummala uint32_t nominal_perf; /**< system wide nominal freq */ 57*6f987b59SSivaprasad Tummala uint16_t turbo_available; /**< Turbo Boost available */ 58*6f987b59SSivaprasad Tummala uint16_t turbo_enable; /**< Turbo Boost enable/disable */ 59*6f987b59SSivaprasad Tummala uint32_t nb_freqs; /**< number of available freqs */ 60*6f987b59SSivaprasad Tummala uint32_t freqs[RTE_MAX_LCORE_FREQS]; /**< Frequency array */ 61*6f987b59SSivaprasad Tummala }; 62*6f987b59SSivaprasad Tummala 63*6f987b59SSivaprasad Tummala static struct amd_pstate_power_info lcore_power_info[RTE_MAX_LCORE]; 64*6f987b59SSivaprasad Tummala 65*6f987b59SSivaprasad Tummala /** 66*6f987b59SSivaprasad Tummala * It is to set specific freq for specific logical core, according to the index 67*6f987b59SSivaprasad Tummala * of supported frequencies. 68*6f987b59SSivaprasad Tummala */ 69*6f987b59SSivaprasad Tummala static int 70*6f987b59SSivaprasad Tummala set_freq_internal(struct amd_pstate_power_info *pi, uint32_t idx) 71*6f987b59SSivaprasad Tummala { 72*6f987b59SSivaprasad Tummala if (idx >= RTE_MAX_LCORE_FREQS || idx >= pi->nb_freqs) { 73*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid frequency index %u, which " 74*6f987b59SSivaprasad Tummala "should be less than %u", idx, pi->nb_freqs); 75*6f987b59SSivaprasad Tummala return -1; 76*6f987b59SSivaprasad Tummala } 77*6f987b59SSivaprasad Tummala 78*6f987b59SSivaprasad Tummala /* Check if it is the same as current */ 79*6f987b59SSivaprasad Tummala if (idx == pi->curr_idx) 80*6f987b59SSivaprasad Tummala return 0; 81*6f987b59SSivaprasad Tummala 82*6f987b59SSivaprasad Tummala POWER_DEBUG_LOG("Frequency[%u] %u to be set for lcore %u", 83*6f987b59SSivaprasad Tummala idx, pi->freqs[idx], pi->lcore_id); 84*6f987b59SSivaprasad Tummala if (fseek(pi->f, 0, SEEK_SET) < 0) { 85*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Fail to set file position indicator to 0 " 86*6f987b59SSivaprasad Tummala "for setting frequency for lcore %u", pi->lcore_id); 87*6f987b59SSivaprasad Tummala return -1; 88*6f987b59SSivaprasad Tummala } 89*6f987b59SSivaprasad Tummala if (fprintf(pi->f, "%u", pi->freqs[idx]) < 0) { 90*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Fail to write new frequency for " 91*6f987b59SSivaprasad Tummala "lcore %u", pi->lcore_id); 92*6f987b59SSivaprasad Tummala return -1; 93*6f987b59SSivaprasad Tummala } 94*6f987b59SSivaprasad Tummala fflush(pi->f); 95*6f987b59SSivaprasad Tummala pi->curr_idx = idx; 96*6f987b59SSivaprasad Tummala 97*6f987b59SSivaprasad Tummala return 1; 98*6f987b59SSivaprasad Tummala } 99*6f987b59SSivaprasad Tummala 100*6f987b59SSivaprasad Tummala /** 101*6f987b59SSivaprasad Tummala * It is to check the current scaling governor by reading sys file, and then 102*6f987b59SSivaprasad Tummala * set it into 'userspace' if it is not by writing the sys file. The original 103*6f987b59SSivaprasad Tummala * governor will be saved for rolling back. 104*6f987b59SSivaprasad Tummala */ 105*6f987b59SSivaprasad Tummala static int 106*6f987b59SSivaprasad Tummala power_set_governor_userspace(struct amd_pstate_power_info *pi) 107*6f987b59SSivaprasad Tummala { 108*6f987b59SSivaprasad Tummala return power_set_governor(pi->lcore_id, POWER_GOVERNOR_USERSPACE, 109*6f987b59SSivaprasad Tummala pi->governor_ori, sizeof(pi->governor_ori)); 110*6f987b59SSivaprasad Tummala } 111*6f987b59SSivaprasad Tummala 112*6f987b59SSivaprasad Tummala static int 113*6f987b59SSivaprasad Tummala power_check_turbo(struct amd_pstate_power_info *pi) 114*6f987b59SSivaprasad Tummala { 115*6f987b59SSivaprasad Tummala FILE *f_nom = NULL, *f_max = NULL; 116*6f987b59SSivaprasad Tummala int ret = -1; 117*6f987b59SSivaprasad Tummala uint32_t nominal_perf = 0, highest_perf = 0; 118*6f987b59SSivaprasad Tummala 119*6f987b59SSivaprasad Tummala open_core_sysfs_file(&f_max, "r", POWER_SYSFILE_HIGHEST_PERF, 120*6f987b59SSivaprasad Tummala pi->lcore_id); 121*6f987b59SSivaprasad Tummala if (f_max == NULL) { 122*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "failed to open %s", 123*6f987b59SSivaprasad Tummala POWER_SYSFILE_HIGHEST_PERF); 124*6f987b59SSivaprasad Tummala goto err; 125*6f987b59SSivaprasad Tummala } 126*6f987b59SSivaprasad Tummala 127*6f987b59SSivaprasad Tummala open_core_sysfs_file(&f_nom, "r", POWER_SYSFILE_NOMINAL_PERF, 128*6f987b59SSivaprasad Tummala pi->lcore_id); 129*6f987b59SSivaprasad Tummala if (f_nom == NULL) { 130*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "failed to open %s", 131*6f987b59SSivaprasad Tummala POWER_SYSFILE_NOMINAL_PERF); 132*6f987b59SSivaprasad Tummala goto err; 133*6f987b59SSivaprasad Tummala } 134*6f987b59SSivaprasad Tummala 135*6f987b59SSivaprasad Tummala ret = read_core_sysfs_u32(f_max, &highest_perf); 136*6f987b59SSivaprasad Tummala if (ret < 0) { 137*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Failed to read %s", 138*6f987b59SSivaprasad Tummala POWER_SYSFILE_HIGHEST_PERF); 139*6f987b59SSivaprasad Tummala goto err; 140*6f987b59SSivaprasad Tummala } 141*6f987b59SSivaprasad Tummala 142*6f987b59SSivaprasad Tummala ret = read_core_sysfs_u32(f_nom, &nominal_perf); 143*6f987b59SSivaprasad Tummala if (ret < 0) { 144*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Failed to read %s", 145*6f987b59SSivaprasad Tummala POWER_SYSFILE_NOMINAL_PERF); 146*6f987b59SSivaprasad Tummala goto err; 147*6f987b59SSivaprasad Tummala } 148*6f987b59SSivaprasad Tummala 149*6f987b59SSivaprasad Tummala pi->highest_perf = highest_perf; 150*6f987b59SSivaprasad Tummala pi->nominal_perf = nominal_perf; 151*6f987b59SSivaprasad Tummala 152*6f987b59SSivaprasad Tummala if (highest_perf > nominal_perf) { 153*6f987b59SSivaprasad Tummala pi->turbo_available = 1; 154*6f987b59SSivaprasad Tummala pi->turbo_enable = 1; 155*6f987b59SSivaprasad Tummala ret = 0; 156*6f987b59SSivaprasad Tummala POWER_DEBUG_LOG("Lcore %u can do Turbo Boost! highest perf %u, " 157*6f987b59SSivaprasad Tummala "nominal perf %u", 158*6f987b59SSivaprasad Tummala pi->lcore_id, highest_perf, nominal_perf); 159*6f987b59SSivaprasad Tummala } else { 160*6f987b59SSivaprasad Tummala pi->turbo_available = 0; 161*6f987b59SSivaprasad Tummala pi->turbo_enable = 0; 162*6f987b59SSivaprasad Tummala POWER_DEBUG_LOG("Lcore %u Turbo not available! highest perf %u, " 163*6f987b59SSivaprasad Tummala "nominal perf %u", 164*6f987b59SSivaprasad Tummala pi->lcore_id, highest_perf, nominal_perf); 165*6f987b59SSivaprasad Tummala } 166*6f987b59SSivaprasad Tummala 167*6f987b59SSivaprasad Tummala err: 168*6f987b59SSivaprasad Tummala if (f_max != NULL) 169*6f987b59SSivaprasad Tummala fclose(f_max); 170*6f987b59SSivaprasad Tummala if (f_nom != NULL) 171*6f987b59SSivaprasad Tummala fclose(f_nom); 172*6f987b59SSivaprasad Tummala 173*6f987b59SSivaprasad Tummala return ret; 174*6f987b59SSivaprasad Tummala } 175*6f987b59SSivaprasad Tummala 176*6f987b59SSivaprasad Tummala /** 177*6f987b59SSivaprasad Tummala * It is to get the available frequencies of the specific lcore by reading the 178*6f987b59SSivaprasad Tummala * sys file. 179*6f987b59SSivaprasad Tummala */ 180*6f987b59SSivaprasad Tummala static int 181*6f987b59SSivaprasad Tummala power_get_available_freqs(struct amd_pstate_power_info *pi) 182*6f987b59SSivaprasad Tummala { 183*6f987b59SSivaprasad Tummala FILE *f_min = NULL, *f_max = NULL, *f_nom = NULL; 184*6f987b59SSivaprasad Tummala int ret = -1, nominal_idx = -1; 185*6f987b59SSivaprasad Tummala uint32_t scaling_min_freq = 0, scaling_max_freq = 0; 186*6f987b59SSivaprasad Tummala uint32_t i, num_freqs = RTE_MAX_LCORE_FREQS; 187*6f987b59SSivaprasad Tummala uint32_t nominal_freq = 0, scaling_freq = 0; 188*6f987b59SSivaprasad Tummala uint32_t freq_calc = 0; 189*6f987b59SSivaprasad Tummala 190*6f987b59SSivaprasad Tummala open_core_sysfs_file(&f_max, "r", POWER_SYSFILE_SCALING_MAX_FREQ, 191*6f987b59SSivaprasad Tummala pi->lcore_id); 192*6f987b59SSivaprasad Tummala if (f_max == NULL) { 193*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "failed to open %s", 194*6f987b59SSivaprasad Tummala POWER_SYSFILE_SCALING_MAX_FREQ); 195*6f987b59SSivaprasad Tummala goto out; 196*6f987b59SSivaprasad Tummala } 197*6f987b59SSivaprasad Tummala 198*6f987b59SSivaprasad Tummala open_core_sysfs_file(&f_min, "r", POWER_SYSFILE_SCALING_MIN_FREQ, 199*6f987b59SSivaprasad Tummala pi->lcore_id); 200*6f987b59SSivaprasad Tummala if (f_min == NULL) { 201*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "failed to open %s", 202*6f987b59SSivaprasad Tummala POWER_SYSFILE_SCALING_MIN_FREQ); 203*6f987b59SSivaprasad Tummala goto out; 204*6f987b59SSivaprasad Tummala } 205*6f987b59SSivaprasad Tummala 206*6f987b59SSivaprasad Tummala open_core_sysfs_file(&f_nom, "r", POWER_SYSFILE_NOMINAL_FREQ, 207*6f987b59SSivaprasad Tummala pi->lcore_id); 208*6f987b59SSivaprasad Tummala if (f_nom == NULL) { 209*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "failed to open %s", 210*6f987b59SSivaprasad Tummala POWER_SYSFILE_NOMINAL_FREQ); 211*6f987b59SSivaprasad Tummala goto out; 212*6f987b59SSivaprasad Tummala } 213*6f987b59SSivaprasad Tummala 214*6f987b59SSivaprasad Tummala ret = read_core_sysfs_u32(f_max, &scaling_max_freq); 215*6f987b59SSivaprasad Tummala if (ret < 0) { 216*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Failed to read %s", 217*6f987b59SSivaprasad Tummala POWER_SYSFILE_SCALING_MAX_FREQ); 218*6f987b59SSivaprasad Tummala goto out; 219*6f987b59SSivaprasad Tummala } 220*6f987b59SSivaprasad Tummala 221*6f987b59SSivaprasad Tummala ret = read_core_sysfs_u32(f_min, &scaling_min_freq); 222*6f987b59SSivaprasad Tummala if (ret < 0) { 223*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Failed to read %s", 224*6f987b59SSivaprasad Tummala POWER_SYSFILE_SCALING_MIN_FREQ); 225*6f987b59SSivaprasad Tummala goto out; 226*6f987b59SSivaprasad Tummala } 227*6f987b59SSivaprasad Tummala 228*6f987b59SSivaprasad Tummala ret = read_core_sysfs_u32(f_nom, &nominal_freq); 229*6f987b59SSivaprasad Tummala if (ret < 0) { 230*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Failed to read %s", 231*6f987b59SSivaprasad Tummala POWER_SYSFILE_NOMINAL_FREQ); 232*6f987b59SSivaprasad Tummala goto out; 233*6f987b59SSivaprasad Tummala } 234*6f987b59SSivaprasad Tummala 235*6f987b59SSivaprasad Tummala power_check_turbo(pi); 236*6f987b59SSivaprasad Tummala 237*6f987b59SSivaprasad Tummala if (scaling_max_freq < scaling_min_freq) { 238*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "scaling min freq exceeds max freq, " 239*6f987b59SSivaprasad Tummala "not expected! Check system power policy"); 240*6f987b59SSivaprasad Tummala goto out; 241*6f987b59SSivaprasad Tummala } else if (scaling_max_freq == scaling_min_freq) { 242*6f987b59SSivaprasad Tummala num_freqs = 1; 243*6f987b59SSivaprasad Tummala } 244*6f987b59SSivaprasad Tummala 245*6f987b59SSivaprasad Tummala if (num_freqs > 1) { 246*6f987b59SSivaprasad Tummala scaling_freq = (scaling_max_freq - scaling_min_freq); 247*6f987b59SSivaprasad Tummala scaling_freq <<= 10; 248*6f987b59SSivaprasad Tummala scaling_freq /= (num_freqs - 1); 249*6f987b59SSivaprasad Tummala scaling_freq >>= 10; 250*6f987b59SSivaprasad Tummala } else { 251*6f987b59SSivaprasad Tummala scaling_freq = 0; 252*6f987b59SSivaprasad Tummala } 253*6f987b59SSivaprasad Tummala 254*6f987b59SSivaprasad Tummala /* Generate the freq bucket array. */ 255*6f987b59SSivaprasad Tummala for (i = 0, pi->nb_freqs = 0; i < num_freqs; i++) { 256*6f987b59SSivaprasad Tummala freq_calc = scaling_max_freq - (i * scaling_freq); 257*6f987b59SSivaprasad Tummala /* convert the frequency to nearest 1000 value 258*6f987b59SSivaprasad Tummala * Ex: if freq=1396789 then freq_conv=1397000 259*6f987b59SSivaprasad Tummala * Ex: if freq=800030 then freq_conv=800000 260*6f987b59SSivaprasad Tummala */ 261*6f987b59SSivaprasad Tummala freq_calc = (freq_calc + FREQ_ROUNDING_DELTA) 262*6f987b59SSivaprasad Tummala / ROUND_FREQ_TO_N_1000; 263*6f987b59SSivaprasad Tummala freq_calc = freq_calc * ROUND_FREQ_TO_N_1000; 264*6f987b59SSivaprasad Tummala 265*6f987b59SSivaprasad Tummala /* update the frequency table only if required */ 266*6f987b59SSivaprasad Tummala if ((pi->nb_freqs == 0) || 267*6f987b59SSivaprasad Tummala pi->freqs[pi->nb_freqs-1] != freq_calc) { 268*6f987b59SSivaprasad Tummala pi->freqs[pi->nb_freqs++] = freq_calc; 269*6f987b59SSivaprasad Tummala } 270*6f987b59SSivaprasad Tummala if (nominal_idx == -1) { 271*6f987b59SSivaprasad Tummala if ((nominal_freq * BUS_FREQ) >= freq_calc) { 272*6f987b59SSivaprasad Tummala pi->nom_idx = pi->nb_freqs - 1; 273*6f987b59SSivaprasad Tummala nominal_idx = pi->nom_idx; 274*6f987b59SSivaprasad Tummala } 275*6f987b59SSivaprasad Tummala } 276*6f987b59SSivaprasad Tummala } 277*6f987b59SSivaprasad Tummala 278*6f987b59SSivaprasad Tummala ret = 0; 279*6f987b59SSivaprasad Tummala 280*6f987b59SSivaprasad Tummala POWER_DEBUG_LOG("%d frequency(s) of lcore %u are available", 281*6f987b59SSivaprasad Tummala num_freqs, pi->lcore_id); 282*6f987b59SSivaprasad Tummala 283*6f987b59SSivaprasad Tummala out: 284*6f987b59SSivaprasad Tummala if (f_min != NULL) 285*6f987b59SSivaprasad Tummala fclose(f_min); 286*6f987b59SSivaprasad Tummala if (f_max != NULL) 287*6f987b59SSivaprasad Tummala fclose(f_max); 288*6f987b59SSivaprasad Tummala if (f_nom != NULL) 289*6f987b59SSivaprasad Tummala fclose(f_nom); 290*6f987b59SSivaprasad Tummala 291*6f987b59SSivaprasad Tummala return ret; 292*6f987b59SSivaprasad Tummala } 293*6f987b59SSivaprasad Tummala 294*6f987b59SSivaprasad Tummala /** 295*6f987b59SSivaprasad Tummala * It is to fopen the sys file for the future setting the lcore frequency. 296*6f987b59SSivaprasad Tummala */ 297*6f987b59SSivaprasad Tummala static int 298*6f987b59SSivaprasad Tummala power_init_for_setting_freq(struct amd_pstate_power_info *pi) 299*6f987b59SSivaprasad Tummala { 300*6f987b59SSivaprasad Tummala FILE *f = NULL; 301*6f987b59SSivaprasad Tummala char buf[BUFSIZ]; 302*6f987b59SSivaprasad Tummala uint32_t i, freq; 303*6f987b59SSivaprasad Tummala int ret; 304*6f987b59SSivaprasad Tummala 305*6f987b59SSivaprasad Tummala open_core_sysfs_file(&f, "rw+", POWER_SYSFILE_SETSPEED, pi->lcore_id); 306*6f987b59SSivaprasad Tummala if (f == NULL) { 307*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "failed to open %s", 308*6f987b59SSivaprasad Tummala POWER_SYSFILE_SETSPEED); 309*6f987b59SSivaprasad Tummala goto err; 310*6f987b59SSivaprasad Tummala } 311*6f987b59SSivaprasad Tummala 312*6f987b59SSivaprasad Tummala ret = read_core_sysfs_s(f, buf, sizeof(buf)); 313*6f987b59SSivaprasad Tummala if (ret < 0) { 314*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Failed to read %s", 315*6f987b59SSivaprasad Tummala POWER_SYSFILE_SETSPEED); 316*6f987b59SSivaprasad Tummala goto err; 317*6f987b59SSivaprasad Tummala } 318*6f987b59SSivaprasad Tummala 319*6f987b59SSivaprasad Tummala freq = strtoul(buf, NULL, POWER_CONVERT_TO_DECIMAL); 320*6f987b59SSivaprasad Tummala 321*6f987b59SSivaprasad Tummala /* convert the frequency to nearest 1000 value 322*6f987b59SSivaprasad Tummala * Ex: if freq=1396789 then freq_conv=1397000 323*6f987b59SSivaprasad Tummala * Ex: if freq=800030 then freq_conv=800000 324*6f987b59SSivaprasad Tummala */ 325*6f987b59SSivaprasad Tummala unsigned int freq_conv = 0; 326*6f987b59SSivaprasad Tummala freq_conv = (freq + FREQ_ROUNDING_DELTA) 327*6f987b59SSivaprasad Tummala / ROUND_FREQ_TO_N_1000; 328*6f987b59SSivaprasad Tummala freq_conv = freq_conv * ROUND_FREQ_TO_N_1000; 329*6f987b59SSivaprasad Tummala 330*6f987b59SSivaprasad Tummala for (i = 0; i < pi->nb_freqs; i++) { 331*6f987b59SSivaprasad Tummala if (freq_conv == pi->freqs[i]) { 332*6f987b59SSivaprasad Tummala pi->curr_idx = i; 333*6f987b59SSivaprasad Tummala pi->f = f; 334*6f987b59SSivaprasad Tummala return 0; 335*6f987b59SSivaprasad Tummala } 336*6f987b59SSivaprasad Tummala } 337*6f987b59SSivaprasad Tummala 338*6f987b59SSivaprasad Tummala err: 339*6f987b59SSivaprasad Tummala if (f != NULL) 340*6f987b59SSivaprasad Tummala fclose(f); 341*6f987b59SSivaprasad Tummala 342*6f987b59SSivaprasad Tummala return -1; 343*6f987b59SSivaprasad Tummala } 344*6f987b59SSivaprasad Tummala 345*6f987b59SSivaprasad Tummala int 346*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_check_supported(void) 347*6f987b59SSivaprasad Tummala { 348*6f987b59SSivaprasad Tummala return cpufreq_check_scaling_driver(POWER_AMD_PSTATE_DRIVER); 349*6f987b59SSivaprasad Tummala } 350*6f987b59SSivaprasad Tummala 351*6f987b59SSivaprasad Tummala int 352*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_init(unsigned int lcore_id) 353*6f987b59SSivaprasad Tummala { 354*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 355*6f987b59SSivaprasad Tummala uint32_t exp_state; 356*6f987b59SSivaprasad Tummala 357*6f987b59SSivaprasad Tummala if (!power_amd_pstate_cpufreq_check_supported()) { 358*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "%s driver is not supported", 359*6f987b59SSivaprasad Tummala POWER_AMD_PSTATE_DRIVER); 360*6f987b59SSivaprasad Tummala return -1; 361*6f987b59SSivaprasad Tummala } 362*6f987b59SSivaprasad Tummala 363*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 364*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Lcore id %u can not exceeds %u", 365*6f987b59SSivaprasad Tummala lcore_id, RTE_MAX_LCORE - 1U); 366*6f987b59SSivaprasad Tummala return -1; 367*6f987b59SSivaprasad Tummala } 368*6f987b59SSivaprasad Tummala 369*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 370*6f987b59SSivaprasad Tummala exp_state = POWER_IDLE; 371*6f987b59SSivaprasad Tummala /* The power in use state works as a guard variable between 372*6f987b59SSivaprasad Tummala * the CPU frequency control initialization and exit process. 373*6f987b59SSivaprasad Tummala * The ACQUIRE memory ordering here pairs with the RELEASE 374*6f987b59SSivaprasad Tummala * ordering below as lock to make sure the frequency operations 375*6f987b59SSivaprasad Tummala * in the critical section are done under the correct state. 376*6f987b59SSivaprasad Tummala */ 377*6f987b59SSivaprasad Tummala if (!rte_atomic_compare_exchange_strong_explicit(&(pi->state), 378*6f987b59SSivaprasad Tummala &exp_state, POWER_ONGOING, 379*6f987b59SSivaprasad Tummala rte_memory_order_acquire, rte_memory_order_relaxed)) { 380*6f987b59SSivaprasad Tummala POWER_LOG(INFO, "Power management of lcore %u is " 381*6f987b59SSivaprasad Tummala "in use", lcore_id); 382*6f987b59SSivaprasad Tummala return -1; 383*6f987b59SSivaprasad Tummala } 384*6f987b59SSivaprasad Tummala 385*6f987b59SSivaprasad Tummala if (power_get_lcore_mapped_cpu_id(lcore_id, &pi->lcore_id) < 0) { 386*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Cannot get CPU ID mapped for lcore %u", lcore_id); 387*6f987b59SSivaprasad Tummala return -1; 388*6f987b59SSivaprasad Tummala } 389*6f987b59SSivaprasad Tummala 390*6f987b59SSivaprasad Tummala /* Check and set the governor */ 391*6f987b59SSivaprasad Tummala if (power_set_governor_userspace(pi) < 0) { 392*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Cannot set governor of lcore %u to " 393*6f987b59SSivaprasad Tummala "userspace", lcore_id); 394*6f987b59SSivaprasad Tummala goto fail; 395*6f987b59SSivaprasad Tummala } 396*6f987b59SSivaprasad Tummala 397*6f987b59SSivaprasad Tummala /* Get the available frequencies */ 398*6f987b59SSivaprasad Tummala if (power_get_available_freqs(pi) < 0) { 399*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Cannot get available frequencies of " 400*6f987b59SSivaprasad Tummala "lcore %u", lcore_id); 401*6f987b59SSivaprasad Tummala goto fail; 402*6f987b59SSivaprasad Tummala } 403*6f987b59SSivaprasad Tummala 404*6f987b59SSivaprasad Tummala /* Init for setting lcore frequency */ 405*6f987b59SSivaprasad Tummala if (power_init_for_setting_freq(pi) < 0) { 406*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Cannot init for setting frequency for " 407*6f987b59SSivaprasad Tummala "lcore %u", lcore_id); 408*6f987b59SSivaprasad Tummala goto fail; 409*6f987b59SSivaprasad Tummala } 410*6f987b59SSivaprasad Tummala 411*6f987b59SSivaprasad Tummala /* Set freq to max by default */ 412*6f987b59SSivaprasad Tummala if (power_amd_pstate_cpufreq_freq_max(lcore_id) < 0) { 413*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Cannot set frequency of lcore %u " 414*6f987b59SSivaprasad Tummala "to max", lcore_id); 415*6f987b59SSivaprasad Tummala goto fail; 416*6f987b59SSivaprasad Tummala } 417*6f987b59SSivaprasad Tummala 418*6f987b59SSivaprasad Tummala POWER_LOG(INFO, "Initialized successfully for lcore %u " 419*6f987b59SSivaprasad Tummala "power management", lcore_id); 420*6f987b59SSivaprasad Tummala 421*6f987b59SSivaprasad Tummala rte_atomic_store_explicit(&(pi->state), POWER_USED, rte_memory_order_release); 422*6f987b59SSivaprasad Tummala 423*6f987b59SSivaprasad Tummala return 0; 424*6f987b59SSivaprasad Tummala 425*6f987b59SSivaprasad Tummala fail: 426*6f987b59SSivaprasad Tummala rte_atomic_store_explicit(&(pi->state), POWER_UNKNOWN, rte_memory_order_release); 427*6f987b59SSivaprasad Tummala return -1; 428*6f987b59SSivaprasad Tummala } 429*6f987b59SSivaprasad Tummala 430*6f987b59SSivaprasad Tummala /** 431*6f987b59SSivaprasad Tummala * It is to check the governor and then set the original governor back if 432*6f987b59SSivaprasad Tummala * needed by writing the sys file. 433*6f987b59SSivaprasad Tummala */ 434*6f987b59SSivaprasad Tummala static int 435*6f987b59SSivaprasad Tummala power_set_governor_original(struct amd_pstate_power_info *pi) 436*6f987b59SSivaprasad Tummala { 437*6f987b59SSivaprasad Tummala return power_set_governor(pi->lcore_id, pi->governor_ori, NULL, 0); 438*6f987b59SSivaprasad Tummala } 439*6f987b59SSivaprasad Tummala 440*6f987b59SSivaprasad Tummala int 441*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_exit(unsigned int lcore_id) 442*6f987b59SSivaprasad Tummala { 443*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 444*6f987b59SSivaprasad Tummala uint32_t exp_state; 445*6f987b59SSivaprasad Tummala 446*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 447*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Lcore id %u can not exceeds %u", 448*6f987b59SSivaprasad Tummala lcore_id, RTE_MAX_LCORE - 1U); 449*6f987b59SSivaprasad Tummala return -1; 450*6f987b59SSivaprasad Tummala } 451*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 452*6f987b59SSivaprasad Tummala exp_state = POWER_USED; 453*6f987b59SSivaprasad Tummala /* The power in use state works as a guard variable between 454*6f987b59SSivaprasad Tummala * the CPU frequency control initialization and exit process. 455*6f987b59SSivaprasad Tummala * The ACQUIRE memory ordering here pairs with the RELEASE 456*6f987b59SSivaprasad Tummala * ordering below as lock to make sure the frequency operations 457*6f987b59SSivaprasad Tummala * in the critical section are done under the correct state. 458*6f987b59SSivaprasad Tummala */ 459*6f987b59SSivaprasad Tummala if (!rte_atomic_compare_exchange_strong_explicit(&(pi->state), 460*6f987b59SSivaprasad Tummala &exp_state, POWER_ONGOING, 461*6f987b59SSivaprasad Tummala rte_memory_order_acquire, rte_memory_order_relaxed)) { 462*6f987b59SSivaprasad Tummala POWER_LOG(INFO, "Power management of lcore %u is " 463*6f987b59SSivaprasad Tummala "not used", lcore_id); 464*6f987b59SSivaprasad Tummala return -1; 465*6f987b59SSivaprasad Tummala } 466*6f987b59SSivaprasad Tummala 467*6f987b59SSivaprasad Tummala /* Close FD of setting freq */ 468*6f987b59SSivaprasad Tummala fclose(pi->f); 469*6f987b59SSivaprasad Tummala pi->f = NULL; 470*6f987b59SSivaprasad Tummala 471*6f987b59SSivaprasad Tummala /* Set the governor back to the original */ 472*6f987b59SSivaprasad Tummala if (power_set_governor_original(pi) < 0) { 473*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Cannot set the governor of %u back " 474*6f987b59SSivaprasad Tummala "to the original", lcore_id); 475*6f987b59SSivaprasad Tummala goto fail; 476*6f987b59SSivaprasad Tummala } 477*6f987b59SSivaprasad Tummala 478*6f987b59SSivaprasad Tummala POWER_LOG(INFO, "Power management of lcore %u has exited from " 479*6f987b59SSivaprasad Tummala "'userspace' mode and been set back to the " 480*6f987b59SSivaprasad Tummala "original", lcore_id); 481*6f987b59SSivaprasad Tummala rte_atomic_store_explicit(&(pi->state), POWER_IDLE, rte_memory_order_release); 482*6f987b59SSivaprasad Tummala 483*6f987b59SSivaprasad Tummala return 0; 484*6f987b59SSivaprasad Tummala 485*6f987b59SSivaprasad Tummala fail: 486*6f987b59SSivaprasad Tummala rte_atomic_store_explicit(&(pi->state), POWER_UNKNOWN, rte_memory_order_release); 487*6f987b59SSivaprasad Tummala 488*6f987b59SSivaprasad Tummala return -1; 489*6f987b59SSivaprasad Tummala } 490*6f987b59SSivaprasad Tummala 491*6f987b59SSivaprasad Tummala uint32_t 492*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_freqs(unsigned int lcore_id, uint32_t *freqs, uint32_t num) 493*6f987b59SSivaprasad Tummala { 494*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 495*6f987b59SSivaprasad Tummala 496*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 497*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 498*6f987b59SSivaprasad Tummala return 0; 499*6f987b59SSivaprasad Tummala } 500*6f987b59SSivaprasad Tummala 501*6f987b59SSivaprasad Tummala if (freqs == NULL) { 502*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "NULL buffer supplied"); 503*6f987b59SSivaprasad Tummala return 0; 504*6f987b59SSivaprasad Tummala } 505*6f987b59SSivaprasad Tummala 506*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 507*6f987b59SSivaprasad Tummala if (num < pi->nb_freqs) { 508*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Buffer size is not enough"); 509*6f987b59SSivaprasad Tummala return 0; 510*6f987b59SSivaprasad Tummala } 511*6f987b59SSivaprasad Tummala rte_memcpy(freqs, pi->freqs, pi->nb_freqs * sizeof(uint32_t)); 512*6f987b59SSivaprasad Tummala 513*6f987b59SSivaprasad Tummala return pi->nb_freqs; 514*6f987b59SSivaprasad Tummala } 515*6f987b59SSivaprasad Tummala 516*6f987b59SSivaprasad Tummala uint32_t 517*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_get_freq(unsigned int lcore_id) 518*6f987b59SSivaprasad Tummala { 519*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 520*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 521*6f987b59SSivaprasad Tummala return RTE_POWER_INVALID_FREQ_INDEX; 522*6f987b59SSivaprasad Tummala } 523*6f987b59SSivaprasad Tummala 524*6f987b59SSivaprasad Tummala return lcore_power_info[lcore_id].curr_idx; 525*6f987b59SSivaprasad Tummala } 526*6f987b59SSivaprasad Tummala 527*6f987b59SSivaprasad Tummala int 528*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_set_freq(unsigned int lcore_id, uint32_t index) 529*6f987b59SSivaprasad Tummala { 530*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 531*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 532*6f987b59SSivaprasad Tummala return -1; 533*6f987b59SSivaprasad Tummala } 534*6f987b59SSivaprasad Tummala 535*6f987b59SSivaprasad Tummala return set_freq_internal(&(lcore_power_info[lcore_id]), index); 536*6f987b59SSivaprasad Tummala } 537*6f987b59SSivaprasad Tummala 538*6f987b59SSivaprasad Tummala int 539*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_freq_down(unsigned int lcore_id) 540*6f987b59SSivaprasad Tummala { 541*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 542*6f987b59SSivaprasad Tummala 543*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 544*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 545*6f987b59SSivaprasad Tummala return -1; 546*6f987b59SSivaprasad Tummala } 547*6f987b59SSivaprasad Tummala 548*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 549*6f987b59SSivaprasad Tummala if (pi->curr_idx + 1 == pi->nb_freqs) 550*6f987b59SSivaprasad Tummala return 0; 551*6f987b59SSivaprasad Tummala 552*6f987b59SSivaprasad Tummala /* Frequencies in the array are from high to low. */ 553*6f987b59SSivaprasad Tummala return set_freq_internal(pi, pi->curr_idx + 1); 554*6f987b59SSivaprasad Tummala } 555*6f987b59SSivaprasad Tummala 556*6f987b59SSivaprasad Tummala int 557*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_freq_up(unsigned int lcore_id) 558*6f987b59SSivaprasad Tummala { 559*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 560*6f987b59SSivaprasad Tummala 561*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 562*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 563*6f987b59SSivaprasad Tummala return -1; 564*6f987b59SSivaprasad Tummala } 565*6f987b59SSivaprasad Tummala 566*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 567*6f987b59SSivaprasad Tummala if (pi->curr_idx == 0 || (pi->curr_idx == pi->nom_idx && 568*6f987b59SSivaprasad Tummala pi->turbo_available && !pi->turbo_enable)) 569*6f987b59SSivaprasad Tummala return 0; 570*6f987b59SSivaprasad Tummala 571*6f987b59SSivaprasad Tummala /* Frequencies in the array are from high to low. */ 572*6f987b59SSivaprasad Tummala return set_freq_internal(pi, pi->curr_idx - 1); 573*6f987b59SSivaprasad Tummala } 574*6f987b59SSivaprasad Tummala 575*6f987b59SSivaprasad Tummala int 576*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_freq_max(unsigned int lcore_id) 577*6f987b59SSivaprasad Tummala { 578*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 579*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 580*6f987b59SSivaprasad Tummala return -1; 581*6f987b59SSivaprasad Tummala } 582*6f987b59SSivaprasad Tummala 583*6f987b59SSivaprasad Tummala /* Frequencies in the array are from high to low. */ 584*6f987b59SSivaprasad Tummala if (lcore_power_info[lcore_id].turbo_available) { 585*6f987b59SSivaprasad Tummala if (lcore_power_info[lcore_id].turbo_enable) 586*6f987b59SSivaprasad Tummala /* Set to Turbo */ 587*6f987b59SSivaprasad Tummala return set_freq_internal( 588*6f987b59SSivaprasad Tummala &lcore_power_info[lcore_id], 0); 589*6f987b59SSivaprasad Tummala else 590*6f987b59SSivaprasad Tummala /* Set to max non-turbo */ 591*6f987b59SSivaprasad Tummala return set_freq_internal( 592*6f987b59SSivaprasad Tummala &lcore_power_info[lcore_id], 593*6f987b59SSivaprasad Tummala lcore_power_info[lcore_id].nom_idx); 594*6f987b59SSivaprasad Tummala } else 595*6f987b59SSivaprasad Tummala return set_freq_internal(&lcore_power_info[lcore_id], 0); 596*6f987b59SSivaprasad Tummala } 597*6f987b59SSivaprasad Tummala 598*6f987b59SSivaprasad Tummala int 599*6f987b59SSivaprasad Tummala power_amd_pstate_cpufreq_freq_min(unsigned int lcore_id) 600*6f987b59SSivaprasad Tummala { 601*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 602*6f987b59SSivaprasad Tummala 603*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 604*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 605*6f987b59SSivaprasad Tummala return -1; 606*6f987b59SSivaprasad Tummala } 607*6f987b59SSivaprasad Tummala 608*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 609*6f987b59SSivaprasad Tummala 610*6f987b59SSivaprasad Tummala /* Frequencies in the array are from high to low. */ 611*6f987b59SSivaprasad Tummala return set_freq_internal(pi, pi->nb_freqs - 1); 612*6f987b59SSivaprasad Tummala } 613*6f987b59SSivaprasad Tummala 614*6f987b59SSivaprasad Tummala int 615*6f987b59SSivaprasad Tummala power_amd_pstate_turbo_status(unsigned int lcore_id) 616*6f987b59SSivaprasad Tummala { 617*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 618*6f987b59SSivaprasad Tummala 619*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 620*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 621*6f987b59SSivaprasad Tummala return -1; 622*6f987b59SSivaprasad Tummala } 623*6f987b59SSivaprasad Tummala 624*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 625*6f987b59SSivaprasad Tummala 626*6f987b59SSivaprasad Tummala return pi->turbo_enable; 627*6f987b59SSivaprasad Tummala } 628*6f987b59SSivaprasad Tummala 629*6f987b59SSivaprasad Tummala int 630*6f987b59SSivaprasad Tummala power_amd_pstate_enable_turbo(unsigned int lcore_id) 631*6f987b59SSivaprasad Tummala { 632*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 633*6f987b59SSivaprasad Tummala 634*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 635*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 636*6f987b59SSivaprasad Tummala return -1; 637*6f987b59SSivaprasad Tummala } 638*6f987b59SSivaprasad Tummala 639*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 640*6f987b59SSivaprasad Tummala 641*6f987b59SSivaprasad Tummala if (pi->turbo_available) 642*6f987b59SSivaprasad Tummala pi->turbo_enable = 1; 643*6f987b59SSivaprasad Tummala else { 644*6f987b59SSivaprasad Tummala pi->turbo_enable = 0; 645*6f987b59SSivaprasad Tummala POWER_LOG(ERR, 646*6f987b59SSivaprasad Tummala "Failed to enable turbo on lcore %u", 647*6f987b59SSivaprasad Tummala lcore_id); 648*6f987b59SSivaprasad Tummala return -1; 649*6f987b59SSivaprasad Tummala } 650*6f987b59SSivaprasad Tummala 651*6f987b59SSivaprasad Tummala /* TODO: must set to max once enabling Turbo? Considering add condition: 652*6f987b59SSivaprasad Tummala * if ((pi->turbo_available) && (pi->curr_idx <= 1)) 653*6f987b59SSivaprasad Tummala */ 654*6f987b59SSivaprasad Tummala /* Max may have changed, so call to max function */ 655*6f987b59SSivaprasad Tummala if (power_amd_pstate_cpufreq_freq_max(lcore_id) < 0) { 656*6f987b59SSivaprasad Tummala POWER_LOG(ERR, 657*6f987b59SSivaprasad Tummala "Failed to set frequency of lcore %u to max", 658*6f987b59SSivaprasad Tummala lcore_id); 659*6f987b59SSivaprasad Tummala return -1; 660*6f987b59SSivaprasad Tummala } 661*6f987b59SSivaprasad Tummala 662*6f987b59SSivaprasad Tummala return 0; 663*6f987b59SSivaprasad Tummala } 664*6f987b59SSivaprasad Tummala 665*6f987b59SSivaprasad Tummala int 666*6f987b59SSivaprasad Tummala power_amd_pstate_disable_turbo(unsigned int lcore_id) 667*6f987b59SSivaprasad Tummala { 668*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 669*6f987b59SSivaprasad Tummala 670*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 671*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 672*6f987b59SSivaprasad Tummala return -1; 673*6f987b59SSivaprasad Tummala } 674*6f987b59SSivaprasad Tummala 675*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 676*6f987b59SSivaprasad Tummala 677*6f987b59SSivaprasad Tummala pi->turbo_enable = 0; 678*6f987b59SSivaprasad Tummala 679*6f987b59SSivaprasad Tummala if ((pi->turbo_available) && (pi->curr_idx <= pi->nom_idx)) { 680*6f987b59SSivaprasad Tummala /* Try to set freq to max by default coming out of turbo */ 681*6f987b59SSivaprasad Tummala if (power_amd_pstate_cpufreq_freq_max(lcore_id) < 0) { 682*6f987b59SSivaprasad Tummala POWER_LOG(ERR, 683*6f987b59SSivaprasad Tummala "Failed to set frequency of lcore %u to max", 684*6f987b59SSivaprasad Tummala lcore_id); 685*6f987b59SSivaprasad Tummala return -1; 686*6f987b59SSivaprasad Tummala } 687*6f987b59SSivaprasad Tummala } 688*6f987b59SSivaprasad Tummala 689*6f987b59SSivaprasad Tummala return 0; 690*6f987b59SSivaprasad Tummala } 691*6f987b59SSivaprasad Tummala 692*6f987b59SSivaprasad Tummala int 693*6f987b59SSivaprasad Tummala power_amd_pstate_get_capabilities(unsigned int lcore_id, 694*6f987b59SSivaprasad Tummala struct rte_power_core_capabilities *caps) 695*6f987b59SSivaprasad Tummala { 696*6f987b59SSivaprasad Tummala struct amd_pstate_power_info *pi; 697*6f987b59SSivaprasad Tummala 698*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 699*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid lcore ID"); 700*6f987b59SSivaprasad Tummala return -1; 701*6f987b59SSivaprasad Tummala } 702*6f987b59SSivaprasad Tummala if (caps == NULL) { 703*6f987b59SSivaprasad Tummala POWER_LOG(ERR, "Invalid argument"); 704*6f987b59SSivaprasad Tummala return -1; 705*6f987b59SSivaprasad Tummala } 706*6f987b59SSivaprasad Tummala 707*6f987b59SSivaprasad Tummala pi = &lcore_power_info[lcore_id]; 708*6f987b59SSivaprasad Tummala caps->capabilities = 0; 709*6f987b59SSivaprasad Tummala caps->turbo = !!(pi->turbo_available); 710*6f987b59SSivaprasad Tummala 711*6f987b59SSivaprasad Tummala return 0; 712*6f987b59SSivaprasad Tummala } 713*6f987b59SSivaprasad Tummala 714*6f987b59SSivaprasad Tummala static struct rte_power_cpufreq_ops amd_pstate_ops = { 715*6f987b59SSivaprasad Tummala .name = "amd-pstate", 716*6f987b59SSivaprasad Tummala .init = power_amd_pstate_cpufreq_init, 717*6f987b59SSivaprasad Tummala .exit = power_amd_pstate_cpufreq_exit, 718*6f987b59SSivaprasad Tummala .check_env_support = power_amd_pstate_cpufreq_check_supported, 719*6f987b59SSivaprasad Tummala .get_avail_freqs = power_amd_pstate_cpufreq_freqs, 720*6f987b59SSivaprasad Tummala .get_freq = power_amd_pstate_cpufreq_get_freq, 721*6f987b59SSivaprasad Tummala .set_freq = power_amd_pstate_cpufreq_set_freq, 722*6f987b59SSivaprasad Tummala .freq_down = power_amd_pstate_cpufreq_freq_down, 723*6f987b59SSivaprasad Tummala .freq_up = power_amd_pstate_cpufreq_freq_up, 724*6f987b59SSivaprasad Tummala .freq_max = power_amd_pstate_cpufreq_freq_max, 725*6f987b59SSivaprasad Tummala .freq_min = power_amd_pstate_cpufreq_freq_min, 726*6f987b59SSivaprasad Tummala .turbo_status = power_amd_pstate_turbo_status, 727*6f987b59SSivaprasad Tummala .enable_turbo = power_amd_pstate_enable_turbo, 728*6f987b59SSivaprasad Tummala .disable_turbo = power_amd_pstate_disable_turbo, 729*6f987b59SSivaprasad Tummala .get_caps = power_amd_pstate_get_capabilities 730*6f987b59SSivaprasad Tummala }; 731*6f987b59SSivaprasad Tummala 732*6f987b59SSivaprasad Tummala RTE_POWER_REGISTER_CPUFREQ_OPS(amd_pstate_ops); 733