1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018 Mellanox Technologies, Ltd 3 */ 4 5 /** 6 * @file 7 * Interrupts handling for tap driver. 8 */ 9 10 #include <errno.h> 11 #include <fcntl.h> 12 #include <signal.h> 13 #include <stdint.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 17 #include <rte_eth_tap.h> 18 #include <rte_errno.h> 19 #include <rte_interrupts.h> 20 21 22 /** 23 * Unregister Rx interrupts free the queue interrupt vector. 24 * 25 * @param dev 26 * Pointer to the tap rte_eth_dev structure. 27 */ 28 static void 29 tap_rx_intr_vec_uninstall(struct rte_eth_dev *dev) 30 { 31 struct pmd_internals *pmd = dev->data->dev_private; 32 struct rte_intr_handle *intr_handle = &pmd->intr_handle; 33 34 rte_intr_free_epoll_fd(intr_handle); 35 free(intr_handle->intr_vec); 36 intr_handle->intr_vec = NULL; 37 intr_handle->nb_efd = 0; 38 } 39 40 /** 41 * Allocate Rx queue interrupt vector and register Rx interrupts. 42 * 43 * @param dev 44 * Pointer to the tap rte_eth_dev device structure. 45 * 46 * @return 47 * 0 on success, negative errno value otherwise and rte_errno is set. 48 */ 49 static int 50 tap_rx_intr_vec_install(struct rte_eth_dev *dev) 51 { 52 struct pmd_internals *pmd = dev->data->dev_private; 53 struct pmd_process_private *process_private = dev->process_private; 54 unsigned int rxqs_n = pmd->dev->data->nb_rx_queues; 55 struct rte_intr_handle *intr_handle = &pmd->intr_handle; 56 unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); 57 unsigned int i; 58 unsigned int count = 0; 59 60 if (!dev->data->dev_conf.intr_conf.rxq) 61 return 0; 62 intr_handle->intr_vec = malloc(sizeof(intr_handle->intr_vec[rxqs_n])); 63 if (intr_handle->intr_vec == NULL) { 64 rte_errno = ENOMEM; 65 TAP_LOG(ERR, 66 "failed to allocate memory for interrupt vector," 67 " Rx interrupts will not be supported"); 68 return -rte_errno; 69 } 70 for (i = 0; i < n; i++) { 71 struct rx_queue *rxq = pmd->dev->data->rx_queues[i]; 72 73 /* Skip queues that cannot request interrupts. */ 74 if (!rxq || process_private->rxq_fds[i] == -1) { 75 /* Use invalid intr_vec[] index to disable entry. */ 76 intr_handle->intr_vec[i] = 77 RTE_INTR_VEC_RXTX_OFFSET + 78 RTE_MAX_RXTX_INTR_VEC_ID; 79 continue; 80 } 81 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count; 82 intr_handle->efds[count] = process_private->rxq_fds[i]; 83 count++; 84 } 85 if (!count) 86 tap_rx_intr_vec_uninstall(dev); 87 else 88 intr_handle->nb_efd = count; 89 return 0; 90 } 91 92 /** 93 * Register or unregister the Rx interrupts. 94 * 95 * @param dev 96 * Pointer to the tap rte_eth_dev device structure. 97 * @param set 98 * should the operation be register or unregister the interrupts. 99 * 100 * @return 101 * 0 on success, negative errno value otherwise and rte_errno is set. 102 */ 103 int 104 tap_rx_intr_vec_set(struct rte_eth_dev *dev, int set) 105 { 106 tap_rx_intr_vec_uninstall(dev); 107 if (set) 108 return tap_rx_intr_vec_install(dev); 109 return 0; 110 } 111