xref: /dpdk/lib/power/rte_power_uncore.c (revision e9fd1ebf981f361844aea9ec94e17f4bda5e1479)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  * Copyright(c) 2023 AMD Corporation
4  */
5 
6 #include <errno.h>
7 
8 #include <rte_errno.h>
9 #include <rte_spinlock.h>
10 
11 #include "power_common.h"
12 #include "rte_power_uncore.h"
13 #include "power_intel_uncore.h"
14 
15 enum rte_uncore_power_mgmt_env default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET;
16 
17 static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER;
18 
19 static uint32_t
20 power_get_dummy_uncore_freq(unsigned int pkg __rte_unused,
21 	       unsigned int die __rte_unused)
22 {
23 	return 0;
24 }
25 
26 static int
27 power_set_dummy_uncore_freq(unsigned int pkg __rte_unused,
28 	       unsigned int die __rte_unused, uint32_t index __rte_unused)
29 {
30 	return 0;
31 }
32 
33 static int
34 power_dummy_uncore_freq_max(unsigned int pkg __rte_unused,
35 	       unsigned int die __rte_unused)
36 {
37 	return 0;
38 }
39 
40 static int
41 power_dummy_uncore_freq_min(unsigned int pkg __rte_unused,
42 	       unsigned int die __rte_unused)
43 {
44 	return 0;
45 }
46 
47 static int
48 power_dummy_uncore_freqs(unsigned int pkg __rte_unused, unsigned int die __rte_unused,
49 		uint32_t *freqs __rte_unused, uint32_t num __rte_unused)
50 {
51 	return 0;
52 }
53 
54 static int
55 power_dummy_uncore_get_num_freqs(unsigned int pkg __rte_unused,
56 	       unsigned int die __rte_unused)
57 {
58 	return 0;
59 }
60 
61 static unsigned int
62 power_dummy_uncore_get_num_pkgs(void)
63 {
64 	return 0;
65 }
66 
67 static unsigned int
68 power_dummy_uncore_get_num_dies(unsigned int pkg __rte_unused)
69 {
70 	return 0;
71 }
72 
73 /* function pointers */
74 rte_power_get_uncore_freq_t rte_power_get_uncore_freq = power_get_dummy_uncore_freq;
75 rte_power_set_uncore_freq_t rte_power_set_uncore_freq = power_set_dummy_uncore_freq;
76 rte_power_uncore_freq_change_t rte_power_uncore_freq_max = power_dummy_uncore_freq_max;
77 rte_power_uncore_freq_change_t rte_power_uncore_freq_min = power_dummy_uncore_freq_min;
78 rte_power_uncore_freqs_t rte_power_uncore_freqs = power_dummy_uncore_freqs;
79 rte_power_uncore_get_num_freqs_t rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs;
80 rte_power_uncore_get_num_pkgs_t rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs;
81 rte_power_uncore_get_num_dies_t rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies;
82 
83 static void
84 reset_power_uncore_function_ptrs(void)
85 {
86 	rte_power_get_uncore_freq = power_get_dummy_uncore_freq;
87 	rte_power_set_uncore_freq = power_set_dummy_uncore_freq;
88 	rte_power_uncore_freq_max = power_dummy_uncore_freq_max;
89 	rte_power_uncore_freq_min = power_dummy_uncore_freq_min;
90 	rte_power_uncore_freqs  = power_dummy_uncore_freqs;
91 	rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs;
92 	rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs;
93 	rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies;
94 }
95 
96 int
97 rte_power_set_uncore_env(enum rte_uncore_power_mgmt_env env)
98 {
99 	int ret;
100 
101 	rte_spinlock_lock(&global_env_cfg_lock);
102 
103 	if (default_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) {
104 		POWER_LOG(ERR, "Uncore Power Management Env already set.");
105 		rte_spinlock_unlock(&global_env_cfg_lock);
106 		return -1;
107 	}
108 
109 	if (env == RTE_UNCORE_PM_ENV_AUTO_DETECT)
110 		/* Currently only intel_uncore is supported.
111 		 * This will be extended with auto-detection support
112 		 * for multiple uncore implementations.
113 		 */
114 		env = RTE_UNCORE_PM_ENV_INTEL_UNCORE;
115 
116 	ret = 0;
117 	if (env == RTE_UNCORE_PM_ENV_INTEL_UNCORE) {
118 		rte_power_get_uncore_freq = power_get_intel_uncore_freq;
119 		rte_power_set_uncore_freq = power_set_intel_uncore_freq;
120 		rte_power_uncore_freq_min  = power_intel_uncore_freq_min;
121 		rte_power_uncore_freq_max  = power_intel_uncore_freq_max;
122 		rte_power_uncore_freqs = power_intel_uncore_freqs;
123 		rte_power_uncore_get_num_freqs = power_intel_uncore_get_num_freqs;
124 		rte_power_uncore_get_num_pkgs = power_intel_uncore_get_num_pkgs;
125 		rte_power_uncore_get_num_dies = power_intel_uncore_get_num_dies;
126 	} else {
127 		POWER_LOG(ERR, "Invalid Power Management Environment(%d) set", env);
128 		ret = -1;
129 		goto out;
130 	}
131 
132 	default_uncore_env = env;
133 out:
134 	rte_spinlock_unlock(&global_env_cfg_lock);
135 	return ret;
136 }
137 
138 void
139 rte_power_unset_uncore_env(void)
140 {
141 	rte_spinlock_lock(&global_env_cfg_lock);
142 	default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET;
143 	reset_power_uncore_function_ptrs();
144 	rte_spinlock_unlock(&global_env_cfg_lock);
145 }
146 
147 enum rte_uncore_power_mgmt_env
148 rte_power_get_uncore_env(void)
149 {
150 	return default_uncore_env;
151 }
152 
153 int
154 rte_power_uncore_init(unsigned int pkg, unsigned int die)
155 {
156 	int ret = -1;
157 
158 	switch (default_uncore_env) {
159 	case RTE_UNCORE_PM_ENV_INTEL_UNCORE:
160 		return power_intel_uncore_init(pkg, die);
161 	default:
162 		POWER_LOG(INFO, "Uncore Env isn't set yet!");
163 		break;
164 	}
165 
166 	/* Auto detect Environment */
167 	POWER_LOG(INFO, "Attempting to initialise Intel Uncore power mgmt...");
168 	ret = power_intel_uncore_init(pkg, die);
169 	if (ret == 0) {
170 		rte_power_set_uncore_env(RTE_UNCORE_PM_ENV_INTEL_UNCORE);
171 		goto out;
172 	}
173 
174 	if (default_uncore_env == RTE_UNCORE_PM_ENV_NOT_SET) {
175 		POWER_LOG(ERR, "Unable to set Power Management Environment "
176 			"for package %u Die %u", pkg, die);
177 		ret = 0;
178 	}
179 out:
180 	return ret;
181 }
182 
183 int
184 rte_power_uncore_exit(unsigned int pkg, unsigned int die)
185 {
186 	switch (default_uncore_env) {
187 	case RTE_UNCORE_PM_ENV_INTEL_UNCORE:
188 		return power_intel_uncore_exit(pkg, die);
189 	default:
190 		POWER_LOG(ERR, "Uncore Env has not been set, unable to exit gracefully");
191 		break;
192 	}
193 	return -1;
194 }
195