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