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