xref: /spdk/module/scheduler/dpdk_governor/dpdk_governor.c (revision 29f0200847c15e8f331d9b70114ebacff5ceed8c)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2020 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk/log.h"
8 #include "spdk/env.h"
9 #include "spdk/event.h"
10 #include "spdk/scheduler.h"
11 
12 #include "spdk_internal/event.h"
13 
14 #include <rte_power.h>
15 #include <rte_version.h>
16 
17 static uint32_t
18 _get_core_avail_freqs(uint32_t lcore_id, uint32_t *freqs, uint32_t num)
19 {
20 	uint32_t rc;
21 
22 	rc = rte_power_freqs(lcore_id, freqs, num);
23 	if (!rc) {
24 		SPDK_ERRLOG("Unable to get current core frequency array for core %d\n.", lcore_id);
25 
26 		return 0;
27 	}
28 
29 	return rc;
30 }
31 
32 static uint32_t
33 _get_core_curr_freq(uint32_t lcore_id)
34 {
35 	uint32_t freqs[SPDK_MAX_LCORE_FREQS];
36 	uint32_t freq_index;
37 	int rc;
38 
39 	rc = rte_power_freqs(lcore_id, freqs, SPDK_MAX_LCORE_FREQS);
40 	if (!rc) {
41 		SPDK_ERRLOG("Unable to get current core frequency array for core %d\n.", lcore_id);
42 
43 		return 0;
44 	}
45 	freq_index = rte_power_get_freq(lcore_id);
46 	if (freq_index >= SPDK_MAX_LCORE_FREQS) {
47 		SPDK_ERRLOG("Unable to get current core frequency for core %d\n.", lcore_id);
48 
49 		return 0;
50 	}
51 
52 	return freqs[freq_index];
53 }
54 
55 static int
56 _core_freq_up(uint32_t lcore_id)
57 {
58 	return rte_power_freq_up(lcore_id);
59 }
60 
61 static int
62 _core_freq_down(uint32_t lcore_id)
63 {
64 	return rte_power_freq_down(lcore_id);
65 }
66 
67 static int
68 _set_core_freq_max(uint32_t lcore_id)
69 {
70 	return rte_power_freq_max(lcore_id);
71 }
72 
73 static int
74 _set_core_freq_min(uint32_t lcore_id)
75 {
76 	return rte_power_freq_min(lcore_id);
77 }
78 
79 static int
80 _get_core_capabilities(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities)
81 {
82 	struct rte_power_core_capabilities caps;
83 	int rc;
84 
85 	rc = rte_power_get_capabilities(lcore_id, &caps);
86 	if (rc != 0) {
87 		return rc;
88 	}
89 
90 	capabilities->priority = caps.priority == 0 ? false : true;
91 
92 	return 0;
93 }
94 
95 static int
96 _dump_info_json(struct spdk_json_write_ctx *w)
97 {
98 	enum power_management_env env;
99 
100 	env = rte_power_get_env();
101 
102 	if (env == PM_ENV_ACPI_CPUFREQ) {
103 		spdk_json_write_named_string(w, "env", "acpi-cpufreq");
104 	} else if (env == PM_ENV_KVM_VM) {
105 		spdk_json_write_named_string(w, "env", "kvm");
106 	} else if (env == PM_ENV_PSTATE_CPUFREQ) {
107 		spdk_json_write_named_string(w, "env", "intel-pstate");
108 	} else if (env == PM_ENV_CPPC_CPUFREQ) {
109 		spdk_json_write_named_string(w, "env", "cppc-cpufreq");
110 #if RTE_VERSION >= RTE_VERSION_NUM(23, 11, 0, 0)
111 	} else if (env == PM_ENV_AMD_PSTATE_CPUFREQ) {
112 		spdk_json_write_named_string(w, "env", "amd-pstate");
113 #endif
114 	} else {
115 		spdk_json_write_named_string(w, "env", "unknown");
116 		return -EINVAL;
117 	}
118 
119 	return 0;
120 }
121 
122 static int
123 _init_core(uint32_t lcore_id)
124 {
125 	struct rte_power_core_capabilities caps;
126 	int rc;
127 
128 	rc = rte_power_init(lcore_id);
129 	if (rc != 0) {
130 		SPDK_ERRLOG("Failed to initialize on core%d\n", lcore_id);
131 		return rc;
132 	}
133 
134 	rc = rte_power_get_capabilities(lcore_id, &caps);
135 	if (rc != 0) {
136 		SPDK_ERRLOG("Failed retrieve capabilities of core%d\n", lcore_id);
137 		return rc;
138 	}
139 
140 	if (caps.turbo) {
141 		rc = rte_power_freq_enable_turbo(lcore_id);
142 		if (rc != 0) {
143 			SPDK_ERRLOG("Failed to set turbo on core%d\n", lcore_id);
144 			return rc;
145 		}
146 	}
147 
148 	return rc;
149 }
150 
151 static int
152 _init(void)
153 {
154 	uint32_t i, j;
155 	int rc = 0;
156 
157 	SPDK_ENV_FOREACH_CORE(i) {
158 		rc = _init_core(i);
159 		if (rc != 0) {
160 			SPDK_ERRLOG("Failed to initialize on core%d\n", i);
161 			break;
162 		}
163 	}
164 
165 	if (rc == 0) {
166 		return rc;
167 	}
168 
169 	/* When initialization of a core failed, deinitialize prior cores. */
170 	SPDK_ENV_FOREACH_CORE(j) {
171 		if (j >= i) {
172 			break;
173 		}
174 		if (rte_power_exit(j) != 0) {
175 			SPDK_ERRLOG("Failed to deinitialize on core%d\n", j);
176 		}
177 	}
178 	return rc;
179 }
180 
181 static void
182 _deinit(void)
183 {
184 	uint32_t i;
185 
186 	SPDK_ENV_FOREACH_CORE(i) {
187 		if (rte_power_exit(i) != 0) {
188 			SPDK_ERRLOG("Failed to deinitialize on core%d\n", i);
189 		}
190 	}
191 }
192 
193 static struct spdk_governor dpdk_governor = {
194 	.name = "dpdk_governor",
195 	.get_core_avail_freqs = _get_core_avail_freqs,
196 	.get_core_curr_freq = _get_core_curr_freq,
197 	.core_freq_up = _core_freq_up,
198 	.core_freq_down = _core_freq_down,
199 	.set_core_freq_max = _set_core_freq_max,
200 	.set_core_freq_min = _set_core_freq_min,
201 	.get_core_capabilities = _get_core_capabilities,
202 	.dump_info_json = _dump_info_json,
203 	.init = _init,
204 	.deinit = _deinit,
205 };
206 
207 SPDK_GOVERNOR_REGISTER(dpdk_governor);
208