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