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