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 int fd = process_private->fds[i]; 72 73 /* Skip queues that cannot request interrupts. */ 74 if (!rxq || fd == -1) { 75 /* Use invalid intr_vec[] index to disable entry. */ 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, fd)) 86 return -rte_errno; 87 count++; 88 } 89 if (!count) 90 tap_rx_intr_vec_uninstall(dev); 91 else if (rte_intr_nb_efd_set(intr_handle, count)) 92 return -rte_errno; 93 return 0; 94 } 95 96 /** 97 * Register or unregister the Rx interrupts. 98 * 99 * @param dev 100 * Pointer to the tap rte_eth_dev device structure. 101 * @param set 102 * should the operation be register or unregister the interrupts. 103 * 104 * @return 105 * 0 on success, negative errno value otherwise and rte_errno is set. 106 */ 107 int 108 tap_rx_intr_vec_set(struct rte_eth_dev *dev, int set) 109 { 110 tap_rx_intr_vec_uninstall(dev); 111 if (set) 112 return tap_rx_intr_vec_install(dev); 113 return 0; 114 } 115