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