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