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 rte_intr_vec_list_free(intr_handle); 36 rte_intr_nb_efd_set(intr_handle, 0); 37 38 rte_intr_instance_free(intr_handle); 39 } 40 41 /** 42 * Allocate Rx queue interrupt vector and register Rx interrupts. 43 * 44 * @param dev 45 * Pointer to the tap rte_eth_dev device structure. 46 * 47 * @return 48 * 0 on success, negative errno value otherwise and rte_errno is set. 49 */ 50 static int 51 tap_rx_intr_vec_install(struct rte_eth_dev *dev) 52 { 53 struct pmd_internals *pmd = dev->data->dev_private; 54 struct pmd_process_private *process_private = dev->process_private; 55 unsigned int rxqs_n = pmd->dev->data->nb_rx_queues; 56 struct rte_intr_handle *intr_handle = pmd->intr_handle; 57 unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); 58 unsigned int i; 59 unsigned int count = 0; 60 61 if (!dev->data->dev_conf.intr_conf.rxq) 62 return 0; 63 64 if (rte_intr_vec_list_alloc(intr_handle, NULL, rxqs_n)) { 65 rte_errno = ENOMEM; 66 TAP_LOG(ERR, 67 "failed to allocate memory for interrupt vector," 68 " Rx interrupts will not be supported"); 69 return -rte_errno; 70 } 71 for (i = 0; i < n; i++) { 72 struct rx_queue *rxq = pmd->dev->data->rx_queues[i]; 73 74 /* Skip queues that cannot request interrupts. */ 75 if (!rxq || process_private->rxq_fds[i] == -1) { 76 /* Use invalid intr_vec[] index to disable entry. */ 77 if (rte_intr_vec_list_index_set(intr_handle, i, 78 RTE_INTR_VEC_RXTX_OFFSET + RTE_MAX_RXTX_INTR_VEC_ID)) 79 return -rte_errno; 80 continue; 81 } 82 if (rte_intr_vec_list_index_set(intr_handle, i, 83 RTE_INTR_VEC_RXTX_OFFSET + count)) 84 return -rte_errno; 85 if (rte_intr_efds_index_set(intr_handle, count, 86 process_private->rxq_fds[i])) 87 return -rte_errno; 88 count++; 89 } 90 if (!count) 91 tap_rx_intr_vec_uninstall(dev); 92 else if (rte_intr_nb_efd_set(intr_handle, count)) 93 return -rte_errno; 94 return 0; 95 } 96 97 /** 98 * Register or unregister the Rx interrupts. 99 * 100 * @param dev 101 * Pointer to the tap rte_eth_dev device structure. 102 * @param set 103 * should the operation be register or unregister the interrupts. 104 * 105 * @return 106 * 0 on success, negative errno value otherwise and rte_errno is set. 107 */ 108 int 109 tap_rx_intr_vec_set(struct rte_eth_dev *dev, int set) 110 { 111 tap_rx_intr_vec_uninstall(dev); 112 if (set) 113 return tap_rx_intr_vec_install(dev); 114 return 0; 115 } 116