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