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 "rte_power_cpufreq.h"
10 : : #include "power_common.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 : 1260 : rte_power_register_cpufreq_ops(struct rte_power_cpufreq_ops *driver_ops)
32 : : {
33 [ + - + - ]: 1260 : if (!driver_ops->init || !driver_ops->exit ||
34 [ + - + - ]: 1260 : !driver_ops->check_env_support || !driver_ops->get_avail_freqs ||
35 [ + - + - ]: 1260 : !driver_ops->get_freq || !driver_ops->set_freq ||
36 [ + - + - ]: 1260 : !driver_ops->freq_up || !driver_ops->freq_down ||
37 [ + - + - ]: 1260 : !driver_ops->freq_max || !driver_ops->freq_min ||
38 [ + - + - ]: 1260 : !driver_ops->turbo_status || !driver_ops->enable_turbo ||
39 [ + - - + ]: 1260 : !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 : 1260 : TAILQ_INSERT_TAIL(&cpufreq_ops_list, driver_ops, next);
45 : :
46 : 1260 : 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 : 8 : rte_power_unset_env(void)
99 : : {
100 : : rte_spinlock_lock(&global_env_cfg_lock);
101 : 8 : global_default_env = PM_ENV_NOT_SET;
102 : 8 : global_cpufreq_ops = NULL;
103 : : rte_spinlock_unlock(&global_env_cfg_lock);
104 : 8 : }
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 : 3 : rte_power_init(unsigned int lcore_id)
115 : : {
116 : : struct rte_power_cpufreq_ops *ops;
117 : : uint8_t env;
118 : :
119 [ + + ]: 3 : if (global_default_env != PM_ENV_NOT_SET)
120 : 2 : return global_cpufreq_ops->init(lcore_id);
121 : :
122 : 1 : POWER_LOG(INFO, "Env isn't set yet!");
123 : :
124 : : /* Auto detect Environment */
125 [ + + ]: 6 : RTE_TAILQ_FOREACH(ops, &cpufreq_ops_list, next) {
126 : 5 : POWER_LOG(INFO,
127 : : "Attempting to initialise %s cpufreq power management...",
128 : : ops->name);
129 [ + + ]: 35 : for (env = 0; env < RTE_DIM(power_env_str); env++) {
130 [ + + ]: 30 : if ((strncmp(ops->name, power_env_str[env],
131 [ - + ]: 5 : RTE_POWER_DRIVER_NAMESZ) == 0) &&
132 : 5 : (ops->init(lcore_id) == 0)) {
133 : 0 : rte_power_set_env(env);
134 : 0 : return 0;
135 : : }
136 : : }
137 : : }
138 : :
139 : 1 : POWER_LOG(ERR,
140 : : "Unable to set Power Management Environment for lcore %u",
141 : : lcore_id);
142 : :
143 : 1 : return -1;
144 : : }
145 : :
146 : : RTE_EXPORT_SYMBOL(rte_power_exit)
147 : : int
148 : 0 : rte_power_exit(unsigned int lcore_id)
149 : : {
150 [ # # ]: 0 : if (global_default_env != PM_ENV_NOT_SET)
151 : 0 : return global_cpufreq_ops->exit(lcore_id);
152 : :
153 : 0 : POWER_LOG(ERR,
154 : : "Environment has not been set, unable to exit gracefully");
155 : :
156 : 0 : return -1;
157 : : }
158 : :
159 : : RTE_EXPORT_SYMBOL(rte_power_freqs)
160 : : uint32_t
161 : 0 : rte_power_freqs(unsigned int lcore_id, uint32_t *freqs, uint32_t n)
162 : : {
163 : : RTE_ASSERT(global_cpufreq_ops != NULL);
164 : 0 : return global_cpufreq_ops->get_avail_freqs(lcore_id, freqs, n);
165 : : }
166 : :
167 : : RTE_EXPORT_SYMBOL(rte_power_get_freq)
168 : : uint32_t
169 : 0 : rte_power_get_freq(unsigned int lcore_id)
170 : : {
171 : : RTE_ASSERT(global_cpufreq_ops != NULL);
172 : 0 : return global_cpufreq_ops->get_freq(lcore_id);
173 : : }
174 : :
175 : : RTE_EXPORT_SYMBOL(rte_power_set_freq)
176 : : uint32_t
177 : 0 : rte_power_set_freq(unsigned int lcore_id, uint32_t index)
178 : : {
179 : : RTE_ASSERT(global_cpufreq_ops != NULL);
180 : 0 : return global_cpufreq_ops->set_freq(lcore_id, index);
181 : : }
182 : :
183 : : RTE_EXPORT_SYMBOL(rte_power_freq_up)
184 : : int
185 : 0 : rte_power_freq_up(unsigned int lcore_id)
186 : : {
187 : : RTE_ASSERT(global_cpufreq_ops != NULL);
188 : 0 : return global_cpufreq_ops->freq_up(lcore_id);
189 : : }
190 : :
191 : : RTE_EXPORT_SYMBOL(rte_power_freq_down)
192 : : int
193 : 0 : rte_power_freq_down(unsigned int lcore_id)
194 : : {
195 : : RTE_ASSERT(global_cpufreq_ops != NULL);
196 : 0 : return global_cpufreq_ops->freq_down(lcore_id);
197 : : }
198 : :
199 : : RTE_EXPORT_SYMBOL(rte_power_freq_max)
200 : : int
201 : 0 : rte_power_freq_max(unsigned int lcore_id)
202 : : {
203 : : RTE_ASSERT(global_cpufreq_ops != NULL);
204 : 0 : return global_cpufreq_ops->freq_max(lcore_id);
205 : : }
206 : :
207 : : RTE_EXPORT_SYMBOL(rte_power_freq_min)
208 : : int
209 : 0 : rte_power_freq_min(unsigned int lcore_id)
210 : : {
211 : : RTE_ASSERT(global_cpufreq_ops != NULL);
212 : 0 : return global_cpufreq_ops->freq_min(lcore_id);
213 : : }
214 : :
215 : : RTE_EXPORT_SYMBOL(rte_power_turbo_status)
216 : : int
217 : 0 : rte_power_turbo_status(unsigned int lcore_id)
218 : : {
219 : : RTE_ASSERT(global_cpufreq_ops != NULL);
220 : 0 : return global_cpufreq_ops->turbo_status(lcore_id);
221 : : }
222 : :
223 : : RTE_EXPORT_SYMBOL(rte_power_freq_enable_turbo)
224 : : int
225 : 0 : rte_power_freq_enable_turbo(unsigned int lcore_id)
226 : : {
227 : : RTE_ASSERT(global_cpufreq_ops != NULL);
228 : 0 : return global_cpufreq_ops->enable_turbo(lcore_id);
229 : : }
230 : :
231 : : RTE_EXPORT_SYMBOL(rte_power_freq_disable_turbo)
232 : : int
233 : 0 : rte_power_freq_disable_turbo(unsigned int lcore_id)
234 : : {
235 : : RTE_ASSERT(global_cpufreq_ops != NULL);
236 : 0 : return global_cpufreq_ops->disable_turbo(lcore_id);
237 : : }
238 : :
239 : : RTE_EXPORT_SYMBOL(rte_power_get_capabilities)
240 : : int
241 : 0 : rte_power_get_capabilities(unsigned int lcore_id,
242 : : struct rte_power_core_capabilities *caps)
243 : : {
244 : : RTE_ASSERT(global_cpufreq_ops != NULL);
245 : 0 : return global_cpufreq_ops->get_caps(lcore_id, caps);
246 : : }
|