xref: /dpdk/lib/power/rte_power.c (revision 30a1de10)
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
reset_power_function_ptrs(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
rte_power_check_env_supported(enum power_management_env env)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
rte_power_set_env(enum power_management_env env)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
rte_power_unset_env(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
rte_power_get_env(void)154 rte_power_get_env(void) {
155 	return global_default_env;
156 }
157 
158 int
rte_power_init(unsigned int lcore_id)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
rte_power_exit(unsigned int lcore_id)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