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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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