Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <rte_log.h>
6 : :
7 : : #include "roc_api.h"
8 : : #include "roc_priv.h"
9 : :
10 : : #if defined(__linux__)
11 : :
12 : : #include <inttypes.h>
13 : : #include <linux/vfio.h>
14 : : #include <sys/eventfd.h>
15 : : #include <sys/ioctl.h>
16 : : #include <unistd.h>
17 : :
18 : : #define MSIX_IRQ_SET_BUF_LEN \
19 : : (sizeof(struct vfio_irq_set) + sizeof(int) * (plt_intr_max_intr_get(intr_handle)))
20 : :
21 : : static int
22 : 0 : irq_get_info(struct plt_intr_handle *intr_handle)
23 : : {
24 : 0 : struct vfio_irq_info irq = {.argsz = sizeof(irq)};
25 : : int rc, vfio_dev_fd;
26 : :
27 : 0 : irq.index = VFIO_PCI_MSIX_IRQ_INDEX;
28 : :
29 : 0 : vfio_dev_fd = plt_intr_dev_fd_get(intr_handle);
30 : 0 : rc = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
31 [ # # ]: 0 : if (rc < 0) {
32 : 0 : plt_err("Failed to get IRQ info rc=%d errno=%d", rc, errno);
33 : 0 : return rc;
34 : : }
35 : :
36 : 0 : plt_base_dbg("Flags=0x%x index=0x%x count=0x%x max_intr_vec_id=0x%x", irq.flags, irq.index,
37 : : irq.count, PLT_MAX_RXTX_INTR_VEC_ID);
38 : :
39 [ # # ]: 0 : if (irq.count == 0) {
40 : 0 : plt_err("HW max=%d > PLT_MAX_RXTX_INTR_VEC_ID: %d", irq.count,
41 : : PLT_MAX_RXTX_INTR_VEC_ID);
42 : 0 : plt_intr_max_intr_set(intr_handle, PLT_MAX_RXTX_INTR_VEC_ID);
43 : : } else {
44 [ # # ]: 0 : if (plt_intr_max_intr_set(intr_handle, irq.count))
45 : 0 : return -1;
46 : : }
47 : :
48 : : return 0;
49 : : }
50 : :
51 : : static int
52 : 0 : irq_config(struct plt_intr_handle *intr_handle, unsigned int vec)
53 : 0 : {
54 : 0 : char irq_set_buf[MSIX_IRQ_SET_BUF_LEN];
55 : : struct vfio_irq_set *irq_set;
56 : : int len, rc, vfio_dev_fd;
57 : : int32_t *fd_ptr;
58 : :
59 [ # # ]: 0 : if (vec > (uint32_t)plt_intr_max_intr_get(intr_handle)) {
60 : 0 : plt_err("vector=%d greater than max_intr=%d", vec,
61 : : plt_intr_max_intr_get(intr_handle));
62 : 0 : return -EINVAL;
63 : : }
64 : :
65 : : len = sizeof(struct vfio_irq_set) + sizeof(int32_t);
66 : :
67 : : irq_set = (struct vfio_irq_set *)irq_set_buf;
68 : 0 : irq_set->argsz = len;
69 : :
70 : 0 : irq_set->start = vec;
71 : 0 : irq_set->count = 1;
72 : 0 : irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
73 : 0 : irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
74 : :
75 : : /* Use vec fd to set interrupt vectors */
76 : : fd_ptr = (int32_t *)&irq_set->data[0];
77 : 0 : fd_ptr[0] = plt_intr_efds_index_get(intr_handle, vec);
78 : :
79 : 0 : vfio_dev_fd = plt_intr_dev_fd_get(intr_handle);
80 : 0 : rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
81 [ # # ]: 0 : if (rc)
82 : 0 : plt_err("Failed to set_irqs vector=0x%x rc=%d", vec, rc);
83 : :
84 : : return rc;
85 : : }
86 : :
87 : : static int
88 : 0 : irq_init(struct plt_intr_handle *intr_handle)
89 : 0 : {
90 : 0 : char irq_set_buf[MSIX_IRQ_SET_BUF_LEN];
91 : : struct vfio_irq_set *irq_set;
92 : : int len, rc, vfio_dev_fd;
93 : : int32_t *fd_ptr;
94 : : uint32_t i;
95 : :
96 : 0 : len = sizeof(struct vfio_irq_set) + sizeof(int32_t) * plt_intr_max_intr_get(intr_handle);
97 : :
98 : : irq_set = (struct vfio_irq_set *)irq_set_buf;
99 : 0 : irq_set->argsz = len;
100 : 0 : irq_set->start = 0;
101 : 0 : irq_set->count = plt_intr_max_intr_get(intr_handle);
102 : 0 : irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
103 : 0 : irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
104 : :
105 : 0 : fd_ptr = (int32_t *)&irq_set->data[0];
106 [ # # ]: 0 : for (i = 0; i < irq_set->count; i++)
107 : 0 : fd_ptr[i] = -1;
108 : :
109 : 0 : vfio_dev_fd = plt_intr_dev_fd_get(intr_handle);
110 : 0 : rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
111 [ # # ]: 0 : if (rc)
112 : 0 : plt_err("Failed to set irqs vector rc=%d", rc);
113 : :
114 : 0 : return rc;
115 : : }
116 : :
117 : : int
118 : 0 : plt_irq_disable(struct plt_intr_handle *intr_handle)
119 : : {
120 : : /* Clear max_intr to indicate re-init next time */
121 : 0 : plt_intr_max_intr_set(intr_handle, 0);
122 : 0 : return plt_intr_disable(intr_handle);
123 : : }
124 : :
125 : : int
126 : 0 : plt_irq_reconfigure(struct plt_intr_handle *intr_handle, uint16_t max_intr)
127 : : {
128 : : /* Disable interrupts if enabled. */
129 [ # # ]: 0 : if (plt_intr_max_intr_get(intr_handle))
130 : 0 : dev_irqs_disable(intr_handle);
131 : :
132 : 0 : plt_intr_max_intr_set(intr_handle, max_intr);
133 : 0 : return irq_init(intr_handle);
134 : : }
135 : :
136 : : int
137 : 0 : plt_irq_register(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb, void *data,
138 : : unsigned int vec)
139 : : {
140 : : struct plt_intr_handle *tmp_handle;
141 : : uint32_t nb_efd, tmp_nb_efd;
142 : : int rc, fd;
143 : :
144 : : /* If no max_intr read from VFIO */
145 [ # # ]: 0 : if (plt_intr_max_intr_get(intr_handle) == 0) {
146 : 0 : irq_get_info(intr_handle);
147 : 0 : irq_init(intr_handle);
148 : : }
149 : :
150 [ # # ]: 0 : if (vec > (uint32_t)plt_intr_max_intr_get(intr_handle)) {
151 : 0 : plt_err("Vector=%d greater than max_intr=%d or ", vec,
152 : : plt_intr_max_intr_get(intr_handle));
153 : 0 : return -EINVAL;
154 : : }
155 : :
156 : : tmp_handle = intr_handle;
157 : : /* Create new eventfd for interrupt vector */
158 : 0 : fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
159 [ # # ]: 0 : if (fd == -1)
160 : : return -ENODEV;
161 : :
162 [ # # ]: 0 : if (plt_intr_fd_set(tmp_handle, fd))
163 : 0 : return -errno;
164 : :
165 : : /* Register vector interrupt callback */
166 : 0 : rc = plt_intr_callback_register(tmp_handle, cb, data);
167 [ # # ]: 0 : if (rc) {
168 : 0 : plt_err("Failed to register vector:0x%x irq callback.", vec);
169 : 0 : return rc;
170 : : }
171 : :
172 : 0 : rc = plt_intr_efds_index_set(intr_handle, vec, fd);
173 [ # # ]: 0 : if (rc)
174 : : return rc;
175 : :
176 : 0 : nb_efd = (vec > (uint32_t)plt_intr_nb_efd_get(intr_handle)) ?
177 [ # # ]: 0 : vec :
178 : 0 : (uint32_t)plt_intr_nb_efd_get(intr_handle);
179 : 0 : plt_intr_nb_efd_set(intr_handle, nb_efd);
180 : :
181 : 0 : tmp_nb_efd = plt_intr_nb_efd_get(intr_handle) + 1;
182 [ # # ]: 0 : if (tmp_nb_efd > (uint32_t)plt_intr_max_intr_get(intr_handle))
183 : 0 : plt_intr_max_intr_set(intr_handle, tmp_nb_efd);
184 : 0 : plt_base_dbg("Enable vector:0x%x for vfio (efds: %d, max:%d)", vec,
185 : : plt_intr_nb_efd_get(intr_handle), plt_intr_max_intr_get(intr_handle));
186 : :
187 : : /* Enable MSIX vectors to VFIO */
188 : 0 : return irq_config(intr_handle, vec);
189 : : }
190 : :
191 : : void
192 : 0 : plt_irq_unregister(struct plt_intr_handle *intr_handle, plt_intr_callback_fn cb, void *data,
193 : : unsigned int vec)
194 : : {
195 : : struct plt_intr_handle *tmp_handle;
196 : : uint8_t retries = 5; /* 5 ms */
197 : : int rc, fd;
198 : :
199 [ # # ]: 0 : if (vec > (uint32_t)plt_intr_max_intr_get(intr_handle)) {
200 : 0 : plt_err("Error unregistering MSI-X interrupts vec:%d > %d", vec,
201 : : plt_intr_max_intr_get(intr_handle));
202 : 0 : return;
203 : : }
204 : :
205 : : tmp_handle = intr_handle;
206 : 0 : fd = plt_intr_efds_index_get(intr_handle, vec);
207 [ # # ]: 0 : if (fd == -1)
208 : : return;
209 : :
210 [ # # ]: 0 : if (plt_intr_fd_set(tmp_handle, fd))
211 : : return;
212 : :
213 : : do {
214 : : /* Un-register callback func from platform lib */
215 : 0 : rc = plt_intr_callback_unregister(tmp_handle, cb, data);
216 : : /* Retry only if -EAGAIN */
217 [ # # ]: 0 : if (rc != -EAGAIN)
218 : : break;
219 : : plt_delay_ms(1);
220 : 0 : retries--;
221 [ # # ]: 0 : } while (retries);
222 : :
223 [ # # ]: 0 : if (rc < 0) {
224 : 0 : plt_err("Error unregistering MSI-X vec %d cb, rc=%d", vec, rc);
225 : 0 : return;
226 : : }
227 : :
228 : 0 : plt_base_dbg("Disable vector:0x%x for vfio (efds: %d, max:%d)", vec,
229 : : plt_intr_nb_efd_get(intr_handle), plt_intr_max_intr_get(intr_handle));
230 : :
231 [ # # ]: 0 : if (plt_intr_efds_index_get(intr_handle, vec) != -1)
232 : 0 : close(plt_intr_efds_index_get(intr_handle, vec));
233 : : /* Disable MSIX vectors from VFIO */
234 : 0 : plt_intr_efds_index_set(intr_handle, vec, -1);
235 : :
236 : 0 : irq_config(intr_handle, vec);
237 : : }
238 : : #endif
239 : :
240 : : #define PLT_INIT_CB_MAX 8
241 : :
242 : : static int plt_init_cb_num;
243 : : static roc_plt_init_cb_t plt_init_cbs[PLT_INIT_CB_MAX];
244 : :
245 : : int
246 : 504 : roc_plt_init_cb_register(roc_plt_init_cb_t cb)
247 : : {
248 [ + - ]: 504 : if (plt_init_cb_num >= PLT_INIT_CB_MAX)
249 : : return -ERANGE;
250 : :
251 : 504 : plt_init_cbs[plt_init_cb_num++] = cb;
252 : 504 : return 0;
253 : : }
254 : :
255 : : uint16_t
256 [ # # ]: 0 : roc_plt_control_lmt_id_get(void)
257 : : {
258 : : uint32_t lcore_id = plt_lcore_id();
259 [ # # ]: 0 : if (lcore_id != LCORE_ID_ANY)
260 : 0 : return lcore_id << ROC_LMT_LINES_PER_CORE_LOG2;
261 : : else
262 : : /* Return Last LMT ID to be use in control path functionality */
263 : : return ROC_NUM_LMT_LINES - 1;
264 : : }
265 : :
266 : : uint16_t
267 [ # # ]: 0 : roc_plt_lmt_validate(void)
268 : : {
269 [ # # ]: 0 : if (!roc_model_is_cn9k()) {
270 : : /* Last LMT line is reserved for control specific operation and can be
271 : : * use from any EAL or non EAL cores.
272 : : */
273 : : if ((RTE_MAX_LCORE << ROC_LMT_LINES_PER_CORE_LOG2) >
274 : : (ROC_NUM_LMT_LINES - 1))
275 : 0 : return 0;
276 : : }
277 : : return 1;
278 : : }
279 : :
280 : : int
281 : 0 : roc_plt_init(void)
282 : : {
283 : : const struct rte_memzone *mz;
284 : : int i, rc;
285 : :
286 : 0 : mz = rte_memzone_lookup(PLT_MODEL_MZ_NAME);
287 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
288 [ # # ]: 0 : if (mz == NULL) {
289 : 0 : mz = rte_memzone_reserve(PLT_MODEL_MZ_NAME,
290 : : sizeof(struct roc_model),
291 : : SOCKET_ID_ANY, 0);
292 [ # # ]: 0 : if (mz == NULL) {
293 : 0 : plt_err("Failed to reserve mem for roc_model");
294 : 0 : return -ENOMEM;
295 : : }
296 [ # # ]: 0 : if (roc_model_init(mz->addr)) {
297 : 0 : plt_err("Failed to init roc_model");
298 : 0 : rte_memzone_free(mz);
299 : 0 : return -EINVAL;
300 : : }
301 : : }
302 : : } else {
303 [ # # ]: 0 : if (mz == NULL) {
304 : 0 : plt_err("Failed to lookup mem for roc_model");
305 : 0 : return -ENOMEM;
306 : : }
307 : 0 : roc_model = mz->addr;
308 : : }
309 : :
310 [ # # ]: 0 : for (i = 0; i < plt_init_cb_num; i++) {
311 : 0 : rc = (*plt_init_cbs[i])();
312 [ # # ]: 0 : if (rc)
313 : 0 : return rc;
314 : : }
315 : :
316 : : return 0;
317 : : }
318 : :
319 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_base, base, INFO);
320 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_mbox, mbox, NOTICE);
321 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_cpt, crypto, NOTICE);
322 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_ml, ml, NOTICE);
323 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_npa, mempool, NOTICE);
324 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_nix, nix, NOTICE);
325 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_npc, flow, NOTICE);
326 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_sso, event, NOTICE);
327 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_tim, timer, NOTICE);
328 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_tm, tm, NOTICE);
329 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_dpi, dpi, NOTICE);
330 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_rep, rep, NOTICE);
331 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_esw, esw, NOTICE);
332 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_ree, ree, NOTICE);
|