1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2018 Mellanox Technologies, Ltd.
7 * Interrupts handling for failsafe driver.
11 #include <sys/epoll.h>
15 #include "failsafe_private.h"
17 #define NUM_RX_PROXIES (FAILSAFE_MAX_ETHPORTS * RTE_MAX_RXTX_INTR_VEC_ID)
21 * Open an epoll file descriptor.
24 * Flags for defining epoll behavior.
26 * 0 on success, negative errno value otherwise.
29 fs_epoll_create1(int flags)
32 return epoll_create1(flags);
40 * Install failsafe Rx event proxy subsystem.
41 * This is the way the failsafe PMD generates Rx events on behalf of its
45 * Pointer to failsafe private structure.
47 * 0 on success, negative errno value otherwise and rte_errno is set.
50 fs_rx_event_proxy_install(struct fs_priv *priv)
55 * Create the epoll fd and event vector for the proxy service to
56 * wait on for Rx events generated by the subdevices.
58 priv->rxp.efd = fs_epoll_create1(0);
59 if (priv->rxp.efd < 0) {
61 ERROR("Failed to create epoll,"
62 " Rx interrupts will not be supported");
65 priv->rxp.evec = calloc(NUM_RX_PROXIES, sizeof(*priv->rxp.evec));
66 if (priv->rxp.evec == NULL) {
67 ERROR("Failed to allocate memory for event vectors,"
68 " Rx interrupts will not be supported");
74 if (priv->rxp.efd >= 0) {
78 if (priv->rxp.evec != NULL) {
80 priv->rxp.evec = NULL;
87 * RX Interrupt control per subdevice.
90 * Pointer to sub-device structure.
92 * The operation be performed for the vector.
93 * Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}.
96 * - On failure, a negative value.
99 failsafe_eth_rx_intr_ctl_subdevice(struct sub_device *sdev, int op)
101 struct rte_eth_dev *dev;
102 struct rte_eth_dev *fsdev;
110 if (sdev == NULL || (ETH(sdev) == NULL) ||
111 sdev->fs_dev == NULL || (PRIV(sdev->fs_dev) == NULL)) {
112 ERROR("Called with invalid arguments");
116 fsdev = sdev->fs_dev;
117 epfd = PRIV(sdev->fs_dev)->rxp.efd;
121 if (op == RTE_INTR_EVENT_ADD) {
122 ERROR("Proxy events are not initialized");
128 if (dev->data->nb_rx_queues > fsdev->data->nb_rx_queues) {
129 ERROR("subdevice has too many queues,"
130 " Interrupts will not be enabled");
133 for (qid = 0; qid < dev->data->nb_rx_queues; qid++) {
134 fsrxq = fsdev->data->rx_queues[qid];
135 rc = rte_eth_dev_rx_intr_ctl_q(pid, qid, epfd,
138 ERROR("rte_eth_dev_rx_intr_ctl_q failed for "
139 "port %d queue %d, epfd %d, error %d",
148 * Install Rx interrupts subsystem for a subdevice.
149 * This is a support for dynamically adding subdevices.
152 * Pointer to subdevice structure.
155 * 0 on success, negative errno value otherwise and rte_errno is set.
157 int failsafe_rx_intr_install_subdevice(struct sub_device *sdev)
161 struct rte_eth_dev *fsdev;
163 const struct rte_intr_conf *const intr_conf =
164 Ð(sdev)->data->dev_conf.intr_conf;
166 fsdev = sdev->fs_dev;
167 rxq = (struct rxq **)fsdev->data->rx_queues;
168 if (intr_conf->rxq == 0)
170 rc = failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_ADD);
173 /* enable interrupts on already-enabled queues */
174 for (qid = 0; qid < ETH(sdev)->data->nb_rx_queues; qid++) {
175 if (rxq[qid]->enable_events) {
176 int ret = rte_eth_dev_rx_intr_enable(PORT_ID(sdev),
178 if (ret && (ret != -ENOTSUP)) {
179 ERROR("Failed to enable interrupts on "
180 "port %d queue %d", PORT_ID(sdev), qid);
189 * Uninstall Rx interrupts subsystem for a subdevice.
190 * This is a support for dynamically removing subdevices.
193 * Pointer to subdevice structure.
196 * 0 on success, negative errno value otherwise and rte_errno is set.
198 void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev)
201 struct rte_eth_dev *fsdev;
204 fsdev = sdev->fs_dev;
205 for (qid = 0; qid < ETH(sdev)->data->nb_rx_queues; qid++) {
206 if (qid < fsdev->data->nb_rx_queues) {
207 fsrxq = fsdev->data->rx_queues[qid];
208 if (fsrxq->enable_events)
209 rte_eth_dev_rx_intr_disable(PORT_ID(sdev),
213 failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_DEL);
217 * Uninstall failsafe Rx event proxy.
220 * Pointer to failsafe private structure.
223 fs_rx_event_proxy_uninstall(struct fs_priv *priv)
225 if (priv->rxp.evec != NULL) {
226 free(priv->rxp.evec);
227 priv->rxp.evec = NULL;
229 if (priv->rxp.efd > 0) {
230 close(priv->rxp.efd);
236 * Uninstall failsafe interrupt vector.
239 * Pointer to failsafe private structure.
242 fs_rx_intr_vec_uninstall(struct fs_priv *priv)
244 struct rte_intr_handle *intr_handle;
246 intr_handle = &priv->intr_handle;
247 if (intr_handle->intr_vec != NULL) {
248 free(intr_handle->intr_vec);
249 intr_handle->intr_vec = NULL;
251 intr_handle->nb_efd = 0;
255 * Installs failsafe interrupt vector to be registered with EAL later on.
258 * Pointer to failsafe private structure.
261 * 0 on success, negative errno value otherwise and rte_errno is set.
264 fs_rx_intr_vec_install(struct fs_priv *priv)
270 struct rte_intr_handle *intr_handle;
272 rxqs_n = priv->dev->data->nb_rx_queues;
273 n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
275 intr_handle = &priv->intr_handle;
276 RTE_ASSERT(intr_handle->intr_vec == NULL);
277 /* Allocate the interrupt vector of the failsafe Rx proxy interrupts */
278 intr_handle->intr_vec = malloc(n * sizeof(intr_handle->intr_vec[0]));
279 if (intr_handle->intr_vec == NULL) {
280 fs_rx_intr_vec_uninstall(priv);
282 ERROR("Failed to allocate memory for interrupt vector,"
283 " Rx interrupts will not be supported");
286 for (i = 0; i < n; i++) {
287 struct rxq *rxq = priv->dev->data->rx_queues[i];
289 /* Skip queues that cannot request interrupts. */
290 if (rxq == NULL || rxq->event_fd < 0) {
291 /* Use invalid intr_vec[] index to disable entry. */
292 intr_handle->intr_vec[i] =
293 RTE_INTR_VEC_RXTX_OFFSET +
294 RTE_MAX_RXTX_INTR_VEC_ID;
297 if (count >= RTE_MAX_RXTX_INTR_VEC_ID) {
299 ERROR("Too many Rx queues for interrupt vector size"
300 " (%d), Rx interrupts cannot be enabled",
301 RTE_MAX_RXTX_INTR_VEC_ID);
302 fs_rx_intr_vec_uninstall(priv);
305 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count;
306 intr_handle->efds[count] = rxq->event_fd;
310 fs_rx_intr_vec_uninstall(priv);
312 intr_handle->nb_efd = count;
313 intr_handle->efd_counter_size = sizeof(uint64_t);
320 * Uninstall failsafe Rx interrupts subsystem.
323 * Pointer to private structure.
326 * 0 on success, negative errno value otherwise and rte_errno is set.
329 failsafe_rx_intr_uninstall(struct rte_eth_dev *dev)
331 struct fs_priv *priv;
332 struct rte_intr_handle *intr_handle;
335 intr_handle = &priv->intr_handle;
336 rte_intr_free_epoll_fd(intr_handle);
337 fs_rx_event_proxy_uninstall(priv);
338 fs_rx_intr_vec_uninstall(priv);
339 dev->intr_handle = NULL;
343 * Install failsafe Rx interrupts subsystem.
346 * Pointer to private structure.
349 * 0 on success, negative errno value otherwise and rte_errno is set.
352 failsafe_rx_intr_install(struct rte_eth_dev *dev)
354 struct fs_priv *priv = PRIV(dev);
355 const struct rte_intr_conf *const intr_conf =
356 &priv->dev->data->dev_conf.intr_conf;
358 if (intr_conf->rxq == 0)
360 if (fs_rx_intr_vec_install(priv) < 0)
362 if (fs_rx_event_proxy_install(priv) < 0) {
363 fs_rx_intr_vec_uninstall(priv);
366 dev->intr_handle = &priv->intr_handle;