Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : * Copyright(c) 2023 AMD Corporation
4 : : */
5 : :
6 : : #include <rte_spinlock.h>
7 : : #include <rte_debug.h>
8 : :
9 : : #include "rte_power_uncore.h"
10 : : #include "power_common.h"
11 : :
12 : : static enum rte_uncore_power_mgmt_env global_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET;
13 : : static struct rte_power_uncore_ops *global_uncore_ops;
14 : :
15 : : static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER;
16 : : static RTE_TAILQ_HEAD(, rte_power_uncore_ops) uncore_ops_list =
17 : : TAILQ_HEAD_INITIALIZER(uncore_ops_list);
18 : :
19 : : const char *uncore_env_str[] = {
20 : : "not set",
21 : : "auto-detect",
22 : : "intel-uncore",
23 : : "amd-hsmp"
24 : : };
25 : :
26 : : /* register the ops struct in rte_power_uncore_ops, return 0 on success. */
27 : : int
28 : 251 : rte_power_register_uncore_ops(struct rte_power_uncore_ops *driver_ops)
29 : : {
30 [ + - + - : 251 : if (!driver_ops->init || !driver_ops->exit || !driver_ops->get_num_pkgs ||
+ - ]
31 [ + - + - ]: 251 : !driver_ops->get_num_dies || !driver_ops->get_num_freqs ||
32 [ + - + - ]: 251 : !driver_ops->get_avail_freqs || !driver_ops->get_freq ||
33 [ + - + - ]: 251 : !driver_ops->set_freq || !driver_ops->freq_max ||
34 [ - + ]: 251 : !driver_ops->freq_min) {
35 : 0 : POWER_LOG(ERR, "Missing callbacks while registering power ops");
36 : 0 : return -1;
37 : : }
38 : :
39 [ - + ]: 251 : if (driver_ops->cb)
40 : 0 : driver_ops->cb();
41 : :
42 : 251 : TAILQ_INSERT_TAIL(&uncore_ops_list, driver_ops, next);
43 : :
44 : 251 : return 0;
45 : : }
46 : :
47 : : int
48 : 1 : rte_power_set_uncore_env(enum rte_uncore_power_mgmt_env env)
49 : : {
50 : : int ret = -1;
51 : : struct rte_power_uncore_ops *ops;
52 : :
53 : : rte_spinlock_lock(&global_env_cfg_lock);
54 : :
55 [ - + ]: 1 : if (global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) {
56 : 0 : POWER_LOG(ERR, "Uncore Power Management Env already set.");
57 : 0 : goto out;
58 : : }
59 : :
60 [ + - ]: 1 : if (env == RTE_UNCORE_PM_ENV_AUTO_DETECT)
61 : : /* Currently only intel_uncore is supported.
62 : : * This will be extended with auto-detection support
63 : : * for multiple uncore implementations.
64 : : */
65 : : env = RTE_UNCORE_PM_ENV_INTEL_UNCORE;
66 : :
67 [ + - ]: 1 : if (env <= RTE_DIM(uncore_env_str)) {
68 [ + - ]: 1 : RTE_TAILQ_FOREACH(ops, &uncore_ops_list, next)
69 [ + - ]: 1 : if (strncmp(ops->name, uncore_env_str[env],
70 : : RTE_POWER_UNCORE_DRIVER_NAMESZ) == 0) {
71 : 1 : global_uncore_env = env;
72 : 1 : global_uncore_ops = ops;
73 : : ret = 0;
74 : 1 : goto out;
75 : : }
76 : 0 : POWER_LOG(ERR, "Power Management (%s) not supported",
77 : : uncore_env_str[env]);
78 : : } else
79 : 0 : POWER_LOG(ERR, "Invalid Power Management Environment");
80 : :
81 : 1 : out:
82 : : rte_spinlock_unlock(&global_env_cfg_lock);
83 : 1 : return ret;
84 : : }
85 : :
86 : : void
87 : 0 : rte_power_unset_uncore_env(void)
88 : : {
89 : : rte_spinlock_lock(&global_env_cfg_lock);
90 : 0 : global_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET;
91 : : rte_spinlock_unlock(&global_env_cfg_lock);
92 : 0 : }
93 : :
94 : : enum rte_uncore_power_mgmt_env
95 : 0 : rte_power_get_uncore_env(void)
96 : : {
97 : 0 : return global_uncore_env;
98 : : }
99 : :
100 : : int
101 : 0 : rte_power_uncore_init(unsigned int pkg, unsigned int die)
102 : : {
103 : : int ret = -1;
104 : : struct rte_power_uncore_ops *ops;
105 : : uint8_t env;
106 : :
107 [ # # ]: 0 : if ((global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) &&
108 : : (global_uncore_env != RTE_UNCORE_PM_ENV_AUTO_DETECT))
109 : 0 : return global_uncore_ops->init(pkg, die);
110 : :
111 : : /* Auto Detect Environment */
112 [ # # ]: 0 : RTE_TAILQ_FOREACH(ops, &uncore_ops_list, next)
113 : : if (ops) {
114 : 0 : POWER_LOG(INFO,
115 : : "Attempting to initialise %s power management...",
116 : : ops->name);
117 : 0 : ret = ops->init(pkg, die);
118 [ # # ]: 0 : if (ret == 0) {
119 [ # # ]: 0 : for (env = 0; env < RTE_DIM(uncore_env_str); env++)
120 [ # # ]: 0 : if (strncmp(ops->name, uncore_env_str[env],
121 : : RTE_POWER_UNCORE_DRIVER_NAMESZ) == 0) {
122 : 0 : rte_power_set_uncore_env(env);
123 : 0 : goto out;
124 : : }
125 : : }
126 : : }
127 : 0 : out:
128 : : return ret;
129 : : }
130 : :
131 : : int
132 : 0 : rte_power_uncore_exit(unsigned int pkg, unsigned int die)
133 : : {
134 [ # # # # ]: 0 : if ((global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) &&
135 : : global_uncore_ops)
136 : 0 : return global_uncore_ops->exit(pkg, die);
137 : :
138 : 0 : POWER_LOG(ERR,
139 : : "Uncore Env has not been set, unable to exit gracefully");
140 : :
141 : 0 : return -1;
142 : : }
143 : :
144 : : uint32_t
145 : 0 : rte_power_get_uncore_freq(unsigned int pkg, unsigned int die)
146 : : {
147 : : RTE_ASSERT(global_uncore_ops != NULL);
148 : 0 : return global_uncore_ops->get_freq(pkg, die);
149 : : }
150 : :
151 : : int
152 : 0 : rte_power_set_uncore_freq(unsigned int pkg, unsigned int die, uint32_t index)
153 : : {
154 : : RTE_ASSERT(global_uncore_ops != NULL);
155 : 0 : return global_uncore_ops->set_freq(pkg, die, index);
156 : : }
157 : :
158 : : int
159 : 0 : rte_power_uncore_freq_max(unsigned int pkg, unsigned int die)
160 : : {
161 : : RTE_ASSERT(global_uncore_ops != NULL);
162 : 0 : return global_uncore_ops->freq_max(pkg, die);
163 : : }
164 : :
165 : : int
166 : 0 : rte_power_uncore_freq_min(unsigned int pkg, unsigned int die)
167 : : {
168 : : RTE_ASSERT(global_uncore_ops != NULL);
169 : 0 : return global_uncore_ops->freq_min(pkg, die);
170 : : }
171 : :
172 : : int
173 : 0 : rte_power_uncore_freqs(unsigned int pkg, unsigned int die,
174 : : uint32_t *freqs, uint32_t num)
175 : : {
176 : : RTE_ASSERT(global_uncore_ops != NULL);
177 : 0 : return global_uncore_ops->get_avail_freqs(pkg, die, freqs, num);
178 : : }
179 : :
180 : : int
181 : 0 : rte_power_uncore_get_num_freqs(unsigned int pkg, unsigned int die)
182 : : {
183 : : RTE_ASSERT(global_uncore_ops != NULL);
184 : 0 : return global_uncore_ops->get_num_freqs(pkg, die);
185 : : }
186 : :
187 : : unsigned int
188 : 1 : rte_power_uncore_get_num_pkgs(void)
189 : : {
190 : : RTE_ASSERT(global_uncore_ops != NULL);
191 : 1 : return global_uncore_ops->get_num_pkgs();
192 : : }
193 : :
194 : : unsigned int
195 : 0 : rte_power_uncore_get_num_dies(unsigned int pkg)
196 : : {
197 : : RTE_ASSERT(global_uncore_ops != NULL);
198 : 0 : return global_uncore_ops->get_num_dies(pkg);
199 : : }
|