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