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