1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <rte_errno.h> 6 #include <rte_spinlock.h> 7 8 #include "rte_power.h" 9 #include "power_acpi_cpufreq.h" 10 #include "power_cppc_cpufreq.h" 11 #include "power_kvm_vm.h" 12 #include "power_pstate_cpufreq.h" 13 #include "power_common.h" 14 15 enum power_management_env global_default_env = PM_ENV_NOT_SET; 16 17 static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER; 18 19 /* function pointers */ 20 rte_power_freqs_t rte_power_freqs = NULL; 21 rte_power_get_freq_t rte_power_get_freq = NULL; 22 rte_power_set_freq_t rte_power_set_freq = NULL; 23 rte_power_freq_change_t rte_power_freq_up = NULL; 24 rte_power_freq_change_t rte_power_freq_down = NULL; 25 rte_power_freq_change_t rte_power_freq_max = NULL; 26 rte_power_freq_change_t rte_power_freq_min = NULL; 27 rte_power_freq_change_t rte_power_turbo_status; 28 rte_power_freq_change_t rte_power_freq_enable_turbo; 29 rte_power_freq_change_t rte_power_freq_disable_turbo; 30 rte_power_get_capabilities_t rte_power_get_capabilities; 31 32 static void 33 reset_power_function_ptrs(void) 34 { 35 rte_power_freqs = NULL; 36 rte_power_get_freq = NULL; 37 rte_power_set_freq = NULL; 38 rte_power_freq_up = NULL; 39 rte_power_freq_down = NULL; 40 rte_power_freq_max = NULL; 41 rte_power_freq_min = NULL; 42 rte_power_turbo_status = NULL; 43 rte_power_freq_enable_turbo = NULL; 44 rte_power_freq_disable_turbo = NULL; 45 rte_power_get_capabilities = NULL; 46 } 47 48 int 49 rte_power_check_env_supported(enum power_management_env env) 50 { 51 switch (env) { 52 case PM_ENV_ACPI_CPUFREQ: 53 return power_acpi_cpufreq_check_supported(); 54 case PM_ENV_PSTATE_CPUFREQ: 55 return power_pstate_cpufreq_check_supported(); 56 case PM_ENV_KVM_VM: 57 return power_kvm_vm_check_supported(); 58 case PM_ENV_CPPC_CPUFREQ: 59 return power_cppc_cpufreq_check_supported(); 60 default: 61 rte_errno = EINVAL; 62 return -1; 63 } 64 } 65 66 int 67 rte_power_set_env(enum power_management_env env) 68 { 69 rte_spinlock_lock(&global_env_cfg_lock); 70 71 if (global_default_env != PM_ENV_NOT_SET) { 72 RTE_LOG(ERR, POWER, "Power Management Environment already set.\n"); 73 rte_spinlock_unlock(&global_env_cfg_lock); 74 return -1; 75 } 76 77 int ret = 0; 78 79 if (env == PM_ENV_ACPI_CPUFREQ) { 80 rte_power_freqs = power_acpi_cpufreq_freqs; 81 rte_power_get_freq = power_acpi_cpufreq_get_freq; 82 rte_power_set_freq = power_acpi_cpufreq_set_freq; 83 rte_power_freq_up = power_acpi_cpufreq_freq_up; 84 rte_power_freq_down = power_acpi_cpufreq_freq_down; 85 rte_power_freq_min = power_acpi_cpufreq_freq_min; 86 rte_power_freq_max = power_acpi_cpufreq_freq_max; 87 rte_power_turbo_status = power_acpi_turbo_status; 88 rte_power_freq_enable_turbo = power_acpi_enable_turbo; 89 rte_power_freq_disable_turbo = power_acpi_disable_turbo; 90 rte_power_get_capabilities = power_acpi_get_capabilities; 91 } else if (env == PM_ENV_KVM_VM) { 92 rte_power_freqs = power_kvm_vm_freqs; 93 rte_power_get_freq = power_kvm_vm_get_freq; 94 rte_power_set_freq = power_kvm_vm_set_freq; 95 rte_power_freq_up = power_kvm_vm_freq_up; 96 rte_power_freq_down = power_kvm_vm_freq_down; 97 rte_power_freq_min = power_kvm_vm_freq_min; 98 rte_power_freq_max = power_kvm_vm_freq_max; 99 rte_power_turbo_status = power_kvm_vm_turbo_status; 100 rte_power_freq_enable_turbo = power_kvm_vm_enable_turbo; 101 rte_power_freq_disable_turbo = power_kvm_vm_disable_turbo; 102 rte_power_get_capabilities = power_kvm_vm_get_capabilities; 103 } else if (env == PM_ENV_PSTATE_CPUFREQ) { 104 rte_power_freqs = power_pstate_cpufreq_freqs; 105 rte_power_get_freq = power_pstate_cpufreq_get_freq; 106 rte_power_set_freq = power_pstate_cpufreq_set_freq; 107 rte_power_freq_up = power_pstate_cpufreq_freq_up; 108 rte_power_freq_down = power_pstate_cpufreq_freq_down; 109 rte_power_freq_min = power_pstate_cpufreq_freq_min; 110 rte_power_freq_max = power_pstate_cpufreq_freq_max; 111 rte_power_turbo_status = power_pstate_turbo_status; 112 rte_power_freq_enable_turbo = power_pstate_enable_turbo; 113 rte_power_freq_disable_turbo = power_pstate_disable_turbo; 114 rte_power_get_capabilities = power_pstate_get_capabilities; 115 116 } else if (env == PM_ENV_CPPC_CPUFREQ) { 117 rte_power_freqs = power_cppc_cpufreq_freqs; 118 rte_power_get_freq = power_cppc_cpufreq_get_freq; 119 rte_power_set_freq = power_cppc_cpufreq_set_freq; 120 rte_power_freq_up = power_cppc_cpufreq_freq_up; 121 rte_power_freq_down = power_cppc_cpufreq_freq_down; 122 rte_power_freq_min = power_cppc_cpufreq_freq_min; 123 rte_power_freq_max = power_cppc_cpufreq_freq_max; 124 rte_power_turbo_status = power_cppc_turbo_status; 125 rte_power_freq_enable_turbo = power_cppc_enable_turbo; 126 rte_power_freq_disable_turbo = power_cppc_disable_turbo; 127 rte_power_get_capabilities = power_cppc_get_capabilities; 128 } else { 129 RTE_LOG(ERR, POWER, "Invalid Power Management Environment(%d) set\n", 130 env); 131 ret = -1; 132 } 133 134 if (ret == 0) 135 global_default_env = env; 136 else { 137 global_default_env = PM_ENV_NOT_SET; 138 reset_power_function_ptrs(); 139 } 140 141 rte_spinlock_unlock(&global_env_cfg_lock); 142 return ret; 143 } 144 145 void 146 rte_power_unset_env(void) 147 { 148 rte_spinlock_lock(&global_env_cfg_lock); 149 global_default_env = PM_ENV_NOT_SET; 150 reset_power_function_ptrs(); 151 rte_spinlock_unlock(&global_env_cfg_lock); 152 } 153 154 enum power_management_env 155 rte_power_get_env(void) { 156 return global_default_env; 157 } 158 159 int 160 rte_power_init(unsigned int lcore_id) 161 { 162 int ret = -1; 163 164 switch (global_default_env) { 165 case PM_ENV_ACPI_CPUFREQ: 166 return power_acpi_cpufreq_init(lcore_id); 167 case PM_ENV_KVM_VM: 168 return power_kvm_vm_init(lcore_id); 169 case PM_ENV_PSTATE_CPUFREQ: 170 return power_pstate_cpufreq_init(lcore_id); 171 case PM_ENV_CPPC_CPUFREQ: 172 return power_cppc_cpufreq_init(lcore_id); 173 default: 174 RTE_LOG(INFO, POWER, "Env isn't set yet!\n"); 175 } 176 177 /* Auto detect Environment */ 178 RTE_LOG(INFO, POWER, "Attempting to initialise ACPI cpufreq power management...\n"); 179 ret = power_acpi_cpufreq_init(lcore_id); 180 if (ret == 0) { 181 rte_power_set_env(PM_ENV_ACPI_CPUFREQ); 182 goto out; 183 } 184 185 RTE_LOG(INFO, POWER, "Attempting to initialise PSTAT power management...\n"); 186 ret = power_pstate_cpufreq_init(lcore_id); 187 if (ret == 0) { 188 rte_power_set_env(PM_ENV_PSTATE_CPUFREQ); 189 goto out; 190 } 191 192 RTE_LOG(INFO, POWER, "Attempting to initialise CPPC power management...\n"); 193 ret = power_cppc_cpufreq_init(lcore_id); 194 if (ret == 0) { 195 rte_power_set_env(PM_ENV_CPPC_CPUFREQ); 196 goto out; 197 } 198 199 RTE_LOG(INFO, POWER, "Attempting to initialise VM power management...\n"); 200 ret = power_kvm_vm_init(lcore_id); 201 if (ret == 0) { 202 rte_power_set_env(PM_ENV_KVM_VM); 203 goto out; 204 } 205 RTE_LOG(ERR, POWER, "Unable to set Power Management Environment for lcore " 206 "%u\n", lcore_id); 207 out: 208 return ret; 209 } 210 211 int 212 rte_power_exit(unsigned int lcore_id) 213 { 214 switch (global_default_env) { 215 case PM_ENV_ACPI_CPUFREQ: 216 return power_acpi_cpufreq_exit(lcore_id); 217 case PM_ENV_KVM_VM: 218 return power_kvm_vm_exit(lcore_id); 219 case PM_ENV_PSTATE_CPUFREQ: 220 return power_pstate_cpufreq_exit(lcore_id); 221 case PM_ENV_CPPC_CPUFREQ: 222 return power_cppc_cpufreq_exit(lcore_id); 223 default: 224 RTE_LOG(ERR, POWER, "Environment has not been set, unable to exit gracefully\n"); 225 226 } 227 return -1; 228 229 } 230