Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <eal_export.h>
6 : : #include <rte_spinlock.h>
7 : : #include <rte_debug.h>
8 : :
9 : : #include "power_common.h"
10 : : #include "power_cpufreq.h"
11 : :
12 : : static enum power_management_env global_default_env = PM_ENV_NOT_SET;
13 : : static struct rte_power_cpufreq_ops *global_cpufreq_ops;
14 : :
15 : : static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER;
16 : : static RTE_TAILQ_HEAD(, rte_power_cpufreq_ops) cpufreq_ops_list =
17 : : TAILQ_HEAD_INITIALIZER(cpufreq_ops_list);
18 : :
19 : : const char *power_env_str[] = {
20 : : "not set",
21 : : "acpi",
22 : : "kvm-vm",
23 : : "intel-pstate",
24 : : "cppc",
25 : : "amd-pstate"
26 : : };
27 : :
28 : : /* register the ops struct in rte_power_cpufreq_ops, return 0 on success. */
29 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_power_register_cpufreq_ops)
30 : : int
31 : 1515 : rte_power_register_cpufreq_ops(struct rte_power_cpufreq_ops *driver_ops)
32 : : {
33 [ + - + - ]: 1515 : if (!driver_ops->init || !driver_ops->exit ||
34 [ + - + - ]: 1515 : !driver_ops->check_env_support || !driver_ops->get_avail_freqs ||
35 [ + - + - ]: 1515 : !driver_ops->get_freq || !driver_ops->set_freq ||
36 [ + - + - ]: 1515 : !driver_ops->freq_up || !driver_ops->freq_down ||
37 [ + - + - ]: 1515 : !driver_ops->freq_max || !driver_ops->freq_min ||
38 [ + - + - ]: 1515 : !driver_ops->turbo_status || !driver_ops->enable_turbo ||
39 [ + - - + ]: 1515 : !driver_ops->disable_turbo || !driver_ops->get_caps) {
40 : 0 : POWER_LOG(ERR, "Missing callbacks while registering cpufreq ops");
41 : 0 : return -1;
42 : : }
43 : :
44 : 1515 : TAILQ_INSERT_TAIL(&cpufreq_ops_list, driver_ops, next);
45 : :
46 : 1515 : return 0;
47 : : }
48 : :
49 : : RTE_EXPORT_SYMBOL(rte_power_check_env_supported)
50 : : int
51 : 0 : rte_power_check_env_supported(enum power_management_env env)
52 : : {
53 : : struct rte_power_cpufreq_ops *ops;
54 : :
55 [ # # ]: 0 : if (env >= RTE_DIM(power_env_str))
56 : : return 0;
57 : :
58 [ # # ]: 0 : RTE_TAILQ_FOREACH(ops, &cpufreq_ops_list, next)
59 [ # # ]: 0 : if (strncmp(ops->name, power_env_str[env],
60 : : RTE_POWER_DRIVER_NAMESZ) == 0)
61 : 0 : return ops->check_env_support();
62 : :
63 : : return 0;
64 : : }
65 : :
66 : : RTE_EXPORT_SYMBOL(rte_power_set_env)
67 : : int
68 : 7 : rte_power_set_env(enum power_management_env env)
69 : : {
70 : : struct rte_power_cpufreq_ops *ops;
71 : : int ret = -1;
72 : :
73 : : rte_spinlock_lock(&global_env_cfg_lock);
74 : :
75 [ - + ]: 7 : if (global_default_env != PM_ENV_NOT_SET) {
76 : 0 : POWER_LOG(ERR, "Power Management Environment already set.");
77 : 0 : goto out;
78 : : }
79 : :
80 [ + + ]: 26 : RTE_TAILQ_FOREACH(ops, &cpufreq_ops_list, next)
81 [ + + ]: 25 : if (strncmp(ops->name, power_env_str[env],
82 : : RTE_POWER_DRIVER_NAMESZ) == 0) {
83 : 6 : global_cpufreq_ops = ops;
84 : 6 : global_default_env = env;
85 : : ret = 0;
86 : 6 : goto out;
87 : : }
88 : :
89 : 1 : POWER_LOG(ERR, "Invalid Power Management Environment(%d) set",
90 : : env);
91 : 7 : out:
92 : : rte_spinlock_unlock(&global_env_cfg_lock);
93 : 7 : return ret;
94 : : }
95 : :
96 : : RTE_EXPORT_SYMBOL(rte_power_unset_env)
97 : : void
98 : 9 : rte_power_unset_env(void)
99 : : {
100 : : rte_spinlock_lock(&global_env_cfg_lock);
101 : 9 : global_default_env = PM_ENV_NOT_SET;
102 : 9 : global_cpufreq_ops = NULL;
103 : : rte_spinlock_unlock(&global_env_cfg_lock);
104 : 9 : }
105 : :
106 : : RTE_EXPORT_SYMBOL(rte_power_get_env)
107 : : enum power_management_env
108 : 7 : rte_power_get_env(void) {
109 : 7 : return global_default_env;
110 : : }
111 : :
112 : : RTE_EXPORT_SYMBOL(rte_power_init)
113 : : int
114 : 4 : rte_power_init(unsigned int lcore_id)
115 : : {
116 : : struct rte_power_cpufreq_ops *ops;
117 : : uint8_t env;
118 : :
119 [ + + + - ]: 4 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
120 [ + - ]: 1 : if (global_default_env != PM_ENV_NOT_SET)
121 : 1 : return global_cpufreq_ops->init(lcore_id);
122 : :
123 : 0 : POWER_LOG(INFO, "Env isn't set yet!");
124 : :
125 : : /* Auto detect Environment */
126 [ # # ]: 0 : RTE_TAILQ_FOREACH(ops, &cpufreq_ops_list, next) {
127 : 0 : POWER_LOG(INFO,
128 : : "Attempting to initialise %s cpufreq power management...",
129 : : ops->name);
130 [ # # ]: 0 : for (env = 0; env < RTE_DIM(power_env_str); env++) {
131 [ # # ]: 0 : if ((strncmp(ops->name, power_env_str[env],
132 [ # # ]: 0 : RTE_POWER_DRIVER_NAMESZ) == 0) &&
133 : 0 : (ops->init(lcore_id) == 0)) {
134 : 0 : rte_power_set_env(env);
135 : 0 : return 0;
136 : : }
137 : : }
138 : : }
139 : :
140 : 0 : POWER_LOG(ERR,
141 : : "Unable to set Power Management Environment for lcore %u",
142 : : lcore_id);
143 : :
144 : 0 : return -1;
145 : : }
146 : :
147 : : RTE_EXPORT_SYMBOL(rte_power_exit)
148 : : int
149 : 0 : rte_power_exit(unsigned int lcore_id)
150 : : {
151 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
152 [ # # ]: 0 : if (global_default_env != PM_ENV_NOT_SET)
153 : 0 : return global_cpufreq_ops->exit(lcore_id);
154 : :
155 : 0 : POWER_LOG(ERR,
156 : : "Environment has not been set, unable to exit gracefully");
157 : :
158 : 0 : return -1;
159 : : }
160 : :
161 : : RTE_EXPORT_SYMBOL(rte_power_freqs)
162 : : uint32_t
163 : 0 : rte_power_freqs(unsigned int lcore_id, uint32_t *freqs, uint32_t n)
164 : : {
165 : : RTE_ASSERT(global_cpufreq_ops != NULL);
166 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, 0);
167 : 0 : return global_cpufreq_ops->get_avail_freqs(lcore_id, freqs, n);
168 : : }
169 : :
170 : : RTE_EXPORT_SYMBOL(rte_power_get_freq)
171 : : uint32_t
172 : 0 : rte_power_get_freq(unsigned int lcore_id)
173 : : {
174 : : RTE_ASSERT(global_cpufreq_ops != NULL);
175 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, RTE_POWER_INVALID_FREQ_INDEX);
176 : 0 : return global_cpufreq_ops->get_freq(lcore_id);
177 : : }
178 : :
179 : : RTE_EXPORT_SYMBOL(rte_power_set_freq)
180 : : uint32_t
181 : 0 : rte_power_set_freq(unsigned int lcore_id, uint32_t index)
182 : : {
183 : : RTE_ASSERT(global_cpufreq_ops != NULL);
184 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
185 : 0 : return global_cpufreq_ops->set_freq(lcore_id, index);
186 : : }
187 : :
188 : : RTE_EXPORT_SYMBOL(rte_power_freq_up)
189 : : int
190 : 0 : rte_power_freq_up(unsigned int lcore_id)
191 : : {
192 : : RTE_ASSERT(global_cpufreq_ops != NULL);
193 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
194 : 0 : return global_cpufreq_ops->freq_up(lcore_id);
195 : : }
196 : :
197 : : RTE_EXPORT_SYMBOL(rte_power_freq_down)
198 : : int
199 : 0 : rte_power_freq_down(unsigned int lcore_id)
200 : : {
201 : : RTE_ASSERT(global_cpufreq_ops != NULL);
202 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
203 : 0 : return global_cpufreq_ops->freq_down(lcore_id);
204 : : }
205 : :
206 : : RTE_EXPORT_SYMBOL(rte_power_freq_max)
207 : : int
208 : 0 : rte_power_freq_max(unsigned int lcore_id)
209 : : {
210 : : RTE_ASSERT(global_cpufreq_ops != NULL);
211 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
212 : 0 : return global_cpufreq_ops->freq_max(lcore_id);
213 : : }
214 : :
215 : : RTE_EXPORT_SYMBOL(rte_power_freq_min)
216 : : int
217 : 0 : rte_power_freq_min(unsigned int lcore_id)
218 : : {
219 : : RTE_ASSERT(global_cpufreq_ops != NULL);
220 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
221 : 0 : return global_cpufreq_ops->freq_min(lcore_id);
222 : : }
223 : :
224 : : RTE_EXPORT_SYMBOL(rte_power_turbo_status)
225 : : int
226 : 0 : rte_power_turbo_status(unsigned int lcore_id)
227 : : {
228 : : RTE_ASSERT(global_cpufreq_ops != NULL);
229 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
230 : 0 : return global_cpufreq_ops->turbo_status(lcore_id);
231 : : }
232 : :
233 : : RTE_EXPORT_SYMBOL(rte_power_freq_enable_turbo)
234 : : int
235 : 0 : rte_power_freq_enable_turbo(unsigned int lcore_id)
236 : : {
237 : : RTE_ASSERT(global_cpufreq_ops != NULL);
238 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
239 : 0 : return global_cpufreq_ops->enable_turbo(lcore_id);
240 : : }
241 : :
242 : : RTE_EXPORT_SYMBOL(rte_power_freq_disable_turbo)
243 : : int
244 : 0 : rte_power_freq_disable_turbo(unsigned int lcore_id)
245 : : {
246 : : RTE_ASSERT(global_cpufreq_ops != NULL);
247 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
248 : 0 : return global_cpufreq_ops->disable_turbo(lcore_id);
249 : : }
250 : :
251 : : RTE_EXPORT_SYMBOL(rte_power_get_capabilities)
252 : : int
253 : 0 : rte_power_get_capabilities(unsigned int lcore_id,
254 : : struct rte_power_core_capabilities *caps)
255 : : {
256 : : RTE_ASSERT(global_cpufreq_ops != NULL);
257 [ # # # # ]: 0 : RTE_POWER_VALID_LCOREID_OR_ERR_RET(lcore_id, -1);
258 : 0 : return global_cpufreq_ops->get_caps(lcore_id, caps);
259 : : }
|