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