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