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