xref: /dpdk/lib/eal/common/eal_common_interrupts.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
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