net/failsafe: register as Rx interrupt mode
[dpdk.git] / drivers / net / failsafe / failsafe_intr.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2018 Mellanox Technologies, Ltd.
3  */
4
5 /**
6  * @file
7  * Interrupts handling for failsafe driver.
8  */
9
10 #include <unistd.h>
11
12 #include "failsafe_private.h"
13
14 /**
15  * Uninstall failsafe interrupt vector.
16  *
17  * @param priv
18  *   Pointer to failsafe private structure.
19  */
20 static void
21 fs_rx_intr_vec_uninstall(struct fs_priv *priv)
22 {
23         struct rte_intr_handle *intr_handle;
24
25         intr_handle = &priv->intr_handle;
26         if (intr_handle->intr_vec != NULL) {
27                 free(intr_handle->intr_vec);
28                 intr_handle->intr_vec = NULL;
29         }
30         intr_handle->nb_efd = 0;
31 }
32
33 /**
34  * Installs failsafe interrupt vector to be registered with EAL later on.
35  *
36  * @param priv
37  *   Pointer to failsafe private structure.
38  *
39  * @return
40  *   0 on success, negative errno value otherwise and rte_errno is set.
41  */
42 static int
43 fs_rx_intr_vec_install(struct fs_priv *priv)
44 {
45         unsigned int i;
46         unsigned int rxqs_n;
47         unsigned int n;
48         unsigned int count;
49         struct rte_intr_handle *intr_handle;
50
51         rxqs_n = priv->dev->data->nb_rx_queues;
52         n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
53         count = 0;
54         intr_handle = &priv->intr_handle;
55         RTE_ASSERT(intr_handle->intr_vec == NULL);
56         /* Allocate the interrupt vector of the failsafe Rx proxy interrupts */
57         intr_handle->intr_vec = malloc(n * sizeof(intr_handle->intr_vec[0]));
58         if (intr_handle->intr_vec == NULL) {
59                 fs_rx_intr_vec_uninstall(priv);
60                 rte_errno = ENOMEM;
61                 ERROR("Failed to allocate memory for interrupt vector,"
62                       " Rx interrupts will not be supported");
63                 return -rte_errno;
64         }
65         for (i = 0; i < n; i++) {
66                 struct rxq *rxq = priv->dev->data->rx_queues[i];
67
68                 /* Skip queues that cannot request interrupts. */
69                 if (rxq == NULL || rxq->event_fd < 0) {
70                         /* Use invalid intr_vec[] index to disable entry. */
71                         intr_handle->intr_vec[i] =
72                                 RTE_INTR_VEC_RXTX_OFFSET +
73                                 RTE_MAX_RXTX_INTR_VEC_ID;
74                         continue;
75                 }
76                 if (count >= RTE_MAX_RXTX_INTR_VEC_ID) {
77                         rte_errno = E2BIG;
78                         ERROR("Too many Rx queues for interrupt vector size"
79                               " (%d), Rx interrupts cannot be enabled",
80                               RTE_MAX_RXTX_INTR_VEC_ID);
81                         fs_rx_intr_vec_uninstall(priv);
82                         return -rte_errno;
83                 }
84                 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count;
85                 intr_handle->efds[count] = rxq->event_fd;
86                 count++;
87         }
88         if (count == 0) {
89                 fs_rx_intr_vec_uninstall(priv);
90         } else {
91                 intr_handle->nb_efd = count;
92                 intr_handle->efd_counter_size = sizeof(uint64_t);
93         }
94         return 0;
95 }
96
97
98 /**
99  * Uninstall failsafe Rx interrupts subsystem.
100  *
101  * @param priv
102  *   Pointer to private structure.
103  *
104  * @return
105  *   0 on success, negative errno value otherwise and rte_errno is set.
106  */
107 void
108 failsafe_rx_intr_uninstall(struct rte_eth_dev *dev)
109 {
110         fs_rx_intr_vec_uninstall(PRIV(dev));
111         dev->intr_handle = NULL;
112 }
113
114 /**
115  * Install failsafe Rx interrupts subsystem.
116  *
117  * @param priv
118  *   Pointer to private structure.
119  *
120  * @return
121  *   0 on success, negative errno value otherwise and rte_errno is set.
122  */
123 int
124 failsafe_rx_intr_install(struct rte_eth_dev *dev)
125 {
126         struct fs_priv *priv = PRIV(dev);
127         const struct rte_intr_conf *const intr_conf =
128                         &priv->dev->data->dev_conf.intr_conf;
129
130         if (intr_conf->rxq == 0)
131                 return 0;
132         if (fs_rx_intr_vec_install(priv) < 0)
133                 return -rte_errno;
134         dev->intr_handle = &priv->intr_handle;
135         return 0;
136 }