xref: /spdk/module/scheduler/dpdk_governor/dpdk_governor.c (revision fecffda6ecf8853b82edccde429b68252f0a62c5)
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_curr_freq(uint32_t lcore_id)
18 {
19 	const uint32_t MAX_CORE_FREQ_NUM = 64;
20 	uint32_t freqs[MAX_CORE_FREQ_NUM];
21 	uint32_t freq_index;
22 	int rc;
23 
24 	rc = rte_power_freqs(lcore_id, freqs, MAX_CORE_FREQ_NUM);
25 	if (!rc) {
26 		SPDK_ERRLOG("Unable to get current core frequency array for core %d\n.", lcore_id);
27 
28 		return 0;
29 	}
30 	freq_index = rte_power_get_freq(lcore_id);
31 	if (freq_index >= MAX_CORE_FREQ_NUM) {
32 		SPDK_ERRLOG("Unable to get current core frequency for core %d\n.", lcore_id);
33 
34 		return 0;
35 	}
36 
37 	return freqs[freq_index];
38 }
39 
40 static int
41 _core_freq_up(uint32_t lcore_id)
42 {
43 	return rte_power_freq_up(lcore_id);
44 }
45 
46 static int
47 _core_freq_down(uint32_t lcore_id)
48 {
49 	return rte_power_freq_down(lcore_id);
50 }
51 
52 static int
53 _set_core_freq_max(uint32_t lcore_id)
54 {
55 	return rte_power_freq_max(lcore_id);
56 }
57 
58 static int
59 _set_core_freq_min(uint32_t lcore_id)
60 {
61 	return rte_power_freq_min(lcore_id);
62 }
63 
64 static int
65 _get_core_capabilities(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities)
66 {
67 	struct rte_power_core_capabilities caps;
68 	int rc;
69 
70 	rc = rte_power_get_capabilities(lcore_id, &caps);
71 	if (rc != 0) {
72 		return rc;
73 	}
74 
75 	capabilities->priority = caps.priority == 0 ? false : true;
76 
77 	return 0;
78 }
79 
80 static int
81 _init_core(uint32_t lcore_id)
82 {
83 	struct rte_power_core_capabilities caps;
84 	int rc;
85 
86 	rc = rte_power_init(lcore_id);
87 	if (rc != 0) {
88 		SPDK_ERRLOG("Failed to initialize on core%d\n", lcore_id);
89 		return rc;
90 	}
91 
92 	rc = rte_power_get_capabilities(lcore_id, &caps);
93 	if (rc != 0) {
94 		SPDK_ERRLOG("Failed retrieve capabilities of core%d\n", lcore_id);
95 		return rc;
96 	}
97 
98 	if (caps.turbo) {
99 		rc = rte_power_freq_enable_turbo(lcore_id);
100 		if (rc != 0) {
101 			SPDK_ERRLOG("Failed to set turbo on core%d\n", lcore_id);
102 			return rc;
103 		}
104 	}
105 
106 	return rc;
107 }
108 
109 static int
110 _init(void)
111 {
112 	uint32_t i, j;
113 	int rc = 0;
114 
115 	SPDK_ENV_FOREACH_CORE(i) {
116 		rc = _init_core(i);
117 		if (rc != 0) {
118 			SPDK_ERRLOG("Failed to initialize on core%d\n", i);
119 			break;
120 		}
121 	}
122 
123 	if (rc == 0) {
124 		return rc;
125 	}
126 
127 	/* When initialization of a core failed, deinitialize prior cores. */
128 	SPDK_ENV_FOREACH_CORE(j) {
129 		if (j >= i) {
130 			break;
131 		}
132 		if (rte_power_exit(j) != 0) {
133 			SPDK_ERRLOG("Failed to deinitialize on core%d\n", j);
134 		}
135 	}
136 	return rc;
137 }
138 
139 static void
140 _deinit(void)
141 {
142 	uint32_t i;
143 
144 	SPDK_ENV_FOREACH_CORE(i) {
145 		if (rte_power_exit(i) != 0) {
146 			SPDK_ERRLOG("Failed to deinitialize on core%d\n", i);
147 		}
148 	}
149 }
150 
151 static struct spdk_governor dpdk_governor = {
152 	.name = "dpdk_governor",
153 	.get_core_curr_freq = _get_core_curr_freq,
154 	.core_freq_up = _core_freq_up,
155 	.core_freq_down = _core_freq_down,
156 	.set_core_freq_max = _set_core_freq_max,
157 	.set_core_freq_min = _set_core_freq_min,
158 	.get_core_capabilities = _get_core_capabilities,
159 	.init = _init,
160 	.deinit = _deinit,
161 };
162 
163 SPDK_GOVERNOR_REGISTER(dpdk_governor);
164