1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
3 */
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <rte_errno.h>
9 #include <rte_interrupts.h>
10 #include <rte_log.h>
11 #include <rte_malloc.h>
12
13 #include "eal_interrupts.h"
14 #include "eal_private.h"
15
16 /* Macros to check for valid interrupt handle */
17 #define CHECK_VALID_INTR_HANDLE(intr_handle) do { \
18 if (intr_handle == NULL) { \
19 EAL_LOG(DEBUG, "Interrupt instance unallocated"); \
20 rte_errno = EINVAL; \
21 goto fail; \
22 } \
23 } while (0)
24
25 #define RTE_INTR_INSTANCE_KNOWN_FLAGS (RTE_INTR_INSTANCE_F_PRIVATE \
26 | RTE_INTR_INSTANCE_F_SHARED \
27 )
28
29 #define RTE_INTR_INSTANCE_USES_RTE_MEMORY(flags) \
30 (!!(flags & RTE_INTR_INSTANCE_F_SHARED))
31
rte_intr_instance_alloc(uint32_t flags)32 struct rte_intr_handle *rte_intr_instance_alloc(uint32_t flags)
33 {
34 struct rte_intr_handle *intr_handle;
35 bool uses_rte_memory;
36
37 /* Check the flag passed by user, it should be part of the
38 * defined flags.
39 */
40 if ((flags & ~RTE_INTR_INSTANCE_KNOWN_FLAGS) != 0) {
41 EAL_LOG(DEBUG, "Invalid alloc flag passed 0x%x", flags);
42 rte_errno = EINVAL;
43 return NULL;
44 }
45
46 uses_rte_memory = RTE_INTR_INSTANCE_USES_RTE_MEMORY(flags);
47 if (uses_rte_memory)
48 intr_handle = rte_zmalloc(NULL, sizeof(*intr_handle), 0);
49 else
50 intr_handle = calloc(1, sizeof(*intr_handle));
51 if (intr_handle == NULL) {
52 EAL_LOG(ERR, "Failed to allocate intr_handle");
53 rte_errno = ENOMEM;
54 return NULL;
55 }
56
57 if (uses_rte_memory) {
58 intr_handle->efds = rte_zmalloc(NULL,
59 RTE_MAX_RXTX_INTR_VEC_ID * sizeof(int), 0);
60 } else {
61 intr_handle->efds = calloc(RTE_MAX_RXTX_INTR_VEC_ID,
62 sizeof(int));
63 }
64 if (intr_handle->efds == NULL) {
65 EAL_LOG(ERR, "Fail to allocate event fd list");
66 rte_errno = ENOMEM;
67 goto fail;
68 }
69
70 if (uses_rte_memory) {
71 intr_handle->elist = rte_zmalloc(NULL,
72 RTE_MAX_RXTX_INTR_VEC_ID * sizeof(struct rte_epoll_event),
73 0);
74 } else {
75 intr_handle->elist = calloc(RTE_MAX_RXTX_INTR_VEC_ID,
76 sizeof(struct rte_epoll_event));
77 }
78 if (intr_handle->elist == NULL) {
79 EAL_LOG(ERR, "fail to allocate event fd list");
80 rte_errno = ENOMEM;
81 goto fail;
82 }
83
84 intr_handle->alloc_flags = flags;
85 intr_handle->nb_intr = RTE_MAX_RXTX_INTR_VEC_ID;
86
87 return intr_handle;
88 fail:
89 if (uses_rte_memory) {
90 rte_free(intr_handle->efds);
91 rte_free(intr_handle);
92 } else {
93 free(intr_handle->efds);
94 free(intr_handle);
95 }
96 return NULL;
97 }
98
rte_intr_instance_dup(const struct rte_intr_handle * src)99 struct rte_intr_handle *rte_intr_instance_dup(const struct rte_intr_handle *src)
100 {
101 struct rte_intr_handle *intr_handle;
102
103 if (src == NULL) {
104 EAL_LOG(DEBUG, "Source interrupt instance unallocated");
105 rte_errno = EINVAL;
106 return NULL;
107 }
108
109 intr_handle = rte_intr_instance_alloc(src->alloc_flags);
110 if (intr_handle != NULL) {
111 intr_handle->fd = src->fd;
112 intr_handle->dev_fd = src->dev_fd;
113 intr_handle->type = src->type;
114 intr_handle->max_intr = src->max_intr;
115 intr_handle->nb_efd = src->nb_efd;
116 intr_handle->efd_counter_size = src->efd_counter_size;
117 memcpy(intr_handle->efds, src->efds, src->nb_intr);
118 memcpy(intr_handle->elist, src->elist, src->nb_intr);
119 }
120
121 return intr_handle;
122 }
123
rte_intr_event_list_update(struct rte_intr_handle * intr_handle,int size)124 int rte_intr_event_list_update(struct rte_intr_handle *intr_handle, int size)
125 {
126 struct rte_epoll_event *tmp_elist;
127 bool uses_rte_memory;
128 int *tmp_efds;
129
130 CHECK_VALID_INTR_HANDLE(intr_handle);
131
132 if (size == 0) {
133 EAL_LOG(DEBUG, "Size can't be zero");
134 rte_errno = EINVAL;
135 goto fail;
136 }
137
138 uses_rte_memory =
139 RTE_INTR_INSTANCE_USES_RTE_MEMORY(intr_handle->alloc_flags);
140 if (uses_rte_memory) {
141 tmp_efds = rte_realloc(intr_handle->efds, size * sizeof(int),
142 0);
143 } else {
144 tmp_efds = realloc(intr_handle->efds, size * sizeof(int));
145 }
146 if (tmp_efds == NULL) {
147 EAL_LOG(ERR, "Failed to realloc the efds list");
148 rte_errno = ENOMEM;
149 goto fail;
150 }
151 intr_handle->efds = tmp_efds;
152
153 if (uses_rte_memory) {
154 tmp_elist = rte_realloc(intr_handle->elist,
155 size * sizeof(struct rte_epoll_event), 0);
156 } else {
157 tmp_elist = realloc(intr_handle->elist,
158 size * sizeof(struct rte_epoll_event));
159 }
160 if (tmp_elist == NULL) {
161 EAL_LOG(ERR, "Failed to realloc the event list");
162 rte_errno = ENOMEM;
163 goto fail;
164 }
165 intr_handle->elist = tmp_elist;
166
167 intr_handle->nb_intr = size;
168
169 return 0;
170 fail:
171 return -rte_errno;
172 }
173
rte_intr_instance_free(struct rte_intr_handle * intr_handle)174 void rte_intr_instance_free(struct rte_intr_handle *intr_handle)
175 {
176 if (intr_handle == NULL)
177 return;
178 if (RTE_INTR_INSTANCE_USES_RTE_MEMORY(intr_handle->alloc_flags)) {
179 rte_free(intr_handle->efds);
180 rte_free(intr_handle->elist);
181 rte_free(intr_handle);
182 } else {
183 free(intr_handle->efds);
184 free(intr_handle->elist);
185 free(intr_handle);
186 }
187 }
188
rte_intr_fd_set(struct rte_intr_handle * intr_handle,int fd)189 int rte_intr_fd_set(struct rte_intr_handle *intr_handle, int fd)
190 {
191 CHECK_VALID_INTR_HANDLE(intr_handle);
192
193 intr_handle->fd = fd;
194
195 return 0;
196 fail:
197 return -rte_errno;
198 }
199
rte_intr_fd_get(const struct rte_intr_handle * intr_handle)200 int rte_intr_fd_get(const struct rte_intr_handle *intr_handle)
201 {
202 CHECK_VALID_INTR_HANDLE(intr_handle);
203
204 return intr_handle->fd;
205 fail:
206 return -1;
207 }
208
rte_intr_type_set(struct rte_intr_handle * intr_handle,enum rte_intr_handle_type type)209 int rte_intr_type_set(struct rte_intr_handle *intr_handle,
210 enum rte_intr_handle_type type)
211 {
212 CHECK_VALID_INTR_HANDLE(intr_handle);
213
214 intr_handle->type = type;
215
216 return 0;
217 fail:
218 return -rte_errno;
219 }
220
rte_intr_type_get(const struct rte_intr_handle * intr_handle)221 enum rte_intr_handle_type rte_intr_type_get(
222 const struct rte_intr_handle *intr_handle)
223 {
224 CHECK_VALID_INTR_HANDLE(intr_handle);
225
226 return intr_handle->type;
227 fail:
228 return RTE_INTR_HANDLE_UNKNOWN;
229 }
230
rte_intr_dev_fd_set(struct rte_intr_handle * intr_handle,int fd)231 int rte_intr_dev_fd_set(struct rte_intr_handle *intr_handle, int fd)
232 {
233 CHECK_VALID_INTR_HANDLE(intr_handle);
234
235 intr_handle->dev_fd = fd;
236
237 return 0;
238 fail:
239 return -rte_errno;
240 }
241
rte_intr_dev_fd_get(const struct rte_intr_handle * intr_handle)242 int rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle)
243 {
244 CHECK_VALID_INTR_HANDLE(intr_handle);
245
246 return intr_handle->dev_fd;
247 fail:
248 return -1;
249 }
250
rte_intr_max_intr_set(struct rte_intr_handle * intr_handle,int max_intr)251 int rte_intr_max_intr_set(struct rte_intr_handle *intr_handle,
252 int max_intr)
253 {
254 CHECK_VALID_INTR_HANDLE(intr_handle);
255
256 if (max_intr > intr_handle->nb_intr) {
257 EAL_LOG(DEBUG, "Maximum interrupt vector ID (%d) exceeds "
258 "the number of available events (%d)", max_intr,
259 intr_handle->nb_intr);
260 rte_errno = ERANGE;
261 goto fail;
262 }
263
264 intr_handle->max_intr = max_intr;
265
266 return 0;
267 fail:
268 return -rte_errno;
269 }
270
rte_intr_max_intr_get(const struct rte_intr_handle * intr_handle)271 int rte_intr_max_intr_get(const struct rte_intr_handle *intr_handle)
272 {
273 CHECK_VALID_INTR_HANDLE(intr_handle);
274
275 return intr_handle->max_intr;
276 fail:
277 return -rte_errno;
278 }
279
rte_intr_nb_efd_set(struct rte_intr_handle * intr_handle,int nb_efd)280 int rte_intr_nb_efd_set(struct rte_intr_handle *intr_handle, int nb_efd)
281 {
282 CHECK_VALID_INTR_HANDLE(intr_handle);
283
284 intr_handle->nb_efd = nb_efd;
285
286 return 0;
287 fail:
288 return -rte_errno;
289 }
290
rte_intr_nb_efd_get(const struct rte_intr_handle * intr_handle)291 int rte_intr_nb_efd_get(const struct rte_intr_handle *intr_handle)
292 {
293 CHECK_VALID_INTR_HANDLE(intr_handle);
294
295 return intr_handle->nb_efd;
296 fail:
297 return -rte_errno;
298 }
299
rte_intr_nb_intr_get(const struct rte_intr_handle * intr_handle)300 int rte_intr_nb_intr_get(const struct rte_intr_handle *intr_handle)
301 {
302 CHECK_VALID_INTR_HANDLE(intr_handle);
303
304 return intr_handle->nb_intr;
305 fail:
306 return -rte_errno;
307 }
308
rte_intr_efd_counter_size_set(struct rte_intr_handle * intr_handle,uint8_t efd_counter_size)309 int rte_intr_efd_counter_size_set(struct rte_intr_handle *intr_handle,
310 uint8_t efd_counter_size)
311 {
312 CHECK_VALID_INTR_HANDLE(intr_handle);
313
314 intr_handle->efd_counter_size = efd_counter_size;
315
316 return 0;
317 fail:
318 return -rte_errno;
319 }
320
rte_intr_efd_counter_size_get(const struct rte_intr_handle * intr_handle)321 int rte_intr_efd_counter_size_get(const struct rte_intr_handle *intr_handle)
322 {
323 CHECK_VALID_INTR_HANDLE(intr_handle);
324
325 return intr_handle->efd_counter_size;
326 fail:
327 return -rte_errno;
328 }
329
rte_intr_efds_index_get(const struct rte_intr_handle * intr_handle,int index)330 int rte_intr_efds_index_get(const struct rte_intr_handle *intr_handle,
331 int index)
332 {
333 CHECK_VALID_INTR_HANDLE(intr_handle);
334
335 if (index >= intr_handle->nb_intr) {
336 EAL_LOG(DEBUG, "Invalid index %d, max limit %d", index,
337 intr_handle->nb_intr);
338 rte_errno = EINVAL;
339 goto fail;
340 }
341
342 return intr_handle->efds[index];
343 fail:
344 return -rte_errno;
345 }
346
rte_intr_efds_index_set(struct rte_intr_handle * intr_handle,int index,int fd)347 int rte_intr_efds_index_set(struct rte_intr_handle *intr_handle,
348 int index, int fd)
349 {
350 CHECK_VALID_INTR_HANDLE(intr_handle);
351
352 if (index >= intr_handle->nb_intr) {
353 EAL_LOG(DEBUG, "Invalid index %d, max limit %d", index,
354 intr_handle->nb_intr);
355 rte_errno = ERANGE;
356 goto fail;
357 }
358
359 intr_handle->efds[index] = fd;
360
361 return 0;
362 fail:
363 return -rte_errno;
364 }
365
rte_intr_elist_index_get(struct rte_intr_handle * intr_handle,int index)366 struct rte_epoll_event *rte_intr_elist_index_get(
367 struct rte_intr_handle *intr_handle, int index)
368 {
369 CHECK_VALID_INTR_HANDLE(intr_handle);
370
371 if (index >= intr_handle->nb_intr) {
372 EAL_LOG(DEBUG, "Invalid index %d, max limit %d", index,
373 intr_handle->nb_intr);
374 rte_errno = ERANGE;
375 goto fail;
376 }
377
378 return &intr_handle->elist[index];
379 fail:
380 return NULL;
381 }
382
rte_intr_elist_index_set(struct rte_intr_handle * intr_handle,int index,struct rte_epoll_event elist)383 int rte_intr_elist_index_set(struct rte_intr_handle *intr_handle,
384 int index, struct rte_epoll_event elist)
385 {
386 CHECK_VALID_INTR_HANDLE(intr_handle);
387
388 if (index >= intr_handle->nb_intr) {
389 EAL_LOG(DEBUG, "Invalid index %d, max limit %d", index,
390 intr_handle->nb_intr);
391 rte_errno = ERANGE;
392 goto fail;
393 }
394
395 intr_handle->elist[index] = elist;
396
397 return 0;
398 fail:
399 return -rte_errno;
400 }
401
rte_intr_vec_list_alloc(struct rte_intr_handle * intr_handle,const char * name,int size)402 int rte_intr_vec_list_alloc(struct rte_intr_handle *intr_handle,
403 const char *name, int size)
404 {
405 CHECK_VALID_INTR_HANDLE(intr_handle);
406
407 /* Vector list already allocated */
408 if (intr_handle->intr_vec != NULL)
409 return 0;
410
411 if (size > intr_handle->nb_intr) {
412 EAL_LOG(DEBUG, "Invalid size %d, max limit %d", size,
413 intr_handle->nb_intr);
414 rte_errno = ERANGE;
415 goto fail;
416 }
417
418 if (RTE_INTR_INSTANCE_USES_RTE_MEMORY(intr_handle->alloc_flags))
419 intr_handle->intr_vec = rte_zmalloc(name, size * sizeof(int), 0);
420 else
421 intr_handle->intr_vec = calloc(size, sizeof(int));
422 if (intr_handle->intr_vec == NULL) {
423 EAL_LOG(ERR, "Failed to allocate %d intr_vec", size);
424 rte_errno = ENOMEM;
425 goto fail;
426 }
427
428 intr_handle->vec_list_size = size;
429
430 return 0;
431 fail:
432 return -rte_errno;
433 }
434
rte_intr_vec_list_index_get(const struct rte_intr_handle * intr_handle,int index)435 int rte_intr_vec_list_index_get(const struct rte_intr_handle *intr_handle,
436 int index)
437 {
438 CHECK_VALID_INTR_HANDLE(intr_handle);
439
440 if (index >= intr_handle->vec_list_size) {
441 EAL_LOG(DEBUG, "Index %d greater than vec list size %d",
442 index, intr_handle->vec_list_size);
443 rte_errno = ERANGE;
444 goto fail;
445 }
446
447 return intr_handle->intr_vec[index];
448 fail:
449 return -rte_errno;
450 }
451
rte_intr_vec_list_index_set(struct rte_intr_handle * intr_handle,int index,int vec)452 int rte_intr_vec_list_index_set(struct rte_intr_handle *intr_handle,
453 int index, int vec)
454 {
455 CHECK_VALID_INTR_HANDLE(intr_handle);
456
457 if (index >= intr_handle->vec_list_size) {
458 EAL_LOG(DEBUG, "Index %d greater than vec list size %d",
459 index, intr_handle->vec_list_size);
460 rte_errno = ERANGE;
461 goto fail;
462 }
463
464 intr_handle->intr_vec[index] = vec;
465
466 return 0;
467 fail:
468 return -rte_errno;
469 }
470
rte_intr_vec_list_free(struct rte_intr_handle * intr_handle)471 void rte_intr_vec_list_free(struct rte_intr_handle *intr_handle)
472 {
473 if (intr_handle == NULL)
474 return;
475 if (RTE_INTR_INSTANCE_USES_RTE_MEMORY(intr_handle->alloc_flags))
476 rte_free(intr_handle->intr_vec);
477 else
478 free(intr_handle->intr_vec);
479 intr_handle->intr_vec = NULL;
480 intr_handle->vec_list_size = 0;
481 }
482
rte_intr_instance_windows_handle_get(struct rte_intr_handle * intr_handle)483 void *rte_intr_instance_windows_handle_get(struct rte_intr_handle *intr_handle)
484 {
485 CHECK_VALID_INTR_HANDLE(intr_handle);
486
487 return intr_handle->windows_handle;
488 fail:
489 return NULL;
490 }
491
rte_intr_instance_windows_handle_set(struct rte_intr_handle * intr_handle,void * windows_handle)492 int rte_intr_instance_windows_handle_set(struct rte_intr_handle *intr_handle,
493 void *windows_handle)
494 {
495 CHECK_VALID_INTR_HANDLE(intr_handle);
496
497 intr_handle->windows_handle = windows_handle;
498
499 return 0;
500 fail:
501 return -rte_errno;
502 }
503