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 <rte_alarm.h>
16 #include <rte_config.h>
17 #include <rte_errno.h>
18 #include <rte_ethdev.h>
19 #include <rte_interrupts.h>
21 #include <rte_service_component.h>
23 #include "failsafe_private.h"
25 #define NUM_RX_PROXIES (FAILSAFE_MAX_ETHPORTS * RTE_MAX_RXTX_INTR_VEC_ID)
29 * Open an epoll file descriptor.
32 * Flags for defining epoll behavior.
34 * 0 on success, negative errno value otherwise.
37 fs_epoll_create1(int flags)
40 return epoll_create1(flags);
48 * Install failsafe Rx event proxy service.
49 * The Rx event proxy is the service that listens to Rx events from the
50 * subdevices and triggers failsafe Rx events accordingly.
53 * Pointer to failsafe private structure.
55 * 0 on success, negative errno value otherwise.
58 fs_rx_event_proxy_routine(void *data)
62 struct rte_epoll_event *events;
69 events = priv->rxp.evec;
70 n = rte_epoll_wait(priv->rxp.efd, events, NUM_RX_PROXIES, -1);
71 for (i = 0; i < n; i++) {
72 rxq = events[i].epdata.data;
73 if (rxq->enable_events && rxq->event_fd != -1) {
74 if (write(rxq->event_fd, &u64, sizeof(u64)) !=
76 ERROR("Failed to proxy Rx event to socket %d",
86 * Uninstall failsafe Rx event proxy service.
89 * Pointer to failsafe private structure.
92 fs_rx_event_proxy_service_uninstall(struct fs_priv *priv)
94 /* Unregister the event service. */
95 switch (priv->rxp.sstate) {
97 rte_service_map_lcore_set(priv->rxp.sid, priv->rxp.scid, 0);
100 rte_service_runstate_set(priv->rxp.sid, 0);
101 rte_service_set_stats_enable(priv->rxp.sid, 0);
102 rte_service_component_runstate_set(priv->rxp.sid, 0);
105 rte_service_component_unregister(priv->rxp.sid);
113 * Install the failsafe Rx event proxy service.
116 * Pointer to failsafe private structure.
118 * 0 on success, negative errno value otherwise.
121 fs_rx_event_proxy_service_install(struct fs_priv *priv)
123 struct rte_service_spec service;
124 int32_t num_service_cores;
127 num_service_cores = rte_service_lcore_count();
128 if (num_service_cores <= 0) {
129 ERROR("Failed to install Rx interrupts, "
130 "no service core found");
133 /* prepare service info */
134 memset(&service, 0, sizeof(struct rte_service_spec));
135 snprintf(service.name, sizeof(service.name), "%s_Rx_service",
136 priv->dev->data->name);
137 service.socket_id = priv->dev->data->numa_node;
138 service.callback = fs_rx_event_proxy_routine;
139 service.callback_userdata = priv;
141 if (priv->rxp.sstate == SS_NO_SERVICE) {
142 uint32_t service_core_list[num_service_cores];
144 /* get a service core to work with */
145 ret = rte_service_lcore_list(service_core_list,
148 ERROR("Failed to install Rx interrupts, "
149 "service core list empty or corrupted");
152 priv->rxp.scid = service_core_list[0];
153 ret = rte_service_lcore_add(priv->rxp.scid);
154 if (ret && ret != -EALREADY) {
155 ERROR("Failed adding service core");
158 /* service core may be in "stopped" state, start it */
159 ret = rte_service_lcore_start(priv->rxp.scid);
160 if (ret && (ret != -EALREADY)) {
161 ERROR("Failed to install Rx interrupts, "
162 "service core not started");
165 /* register our service */
166 int32_t ret = rte_service_component_register(&service,
169 ERROR("service register() failed");
172 priv->rxp.sstate = SS_REGISTERED;
173 /* run the service */
174 ret = rte_service_component_runstate_set(priv->rxp.sid, 1);
176 ERROR("Failed Setting component runstate\n");
179 ret = rte_service_set_stats_enable(priv->rxp.sid, 1);
181 ERROR("Failed enabling stats\n");
184 ret = rte_service_runstate_set(priv->rxp.sid, 1);
186 ERROR("Failed to run service\n");
189 priv->rxp.sstate = SS_READY;
190 /* map the service with the service core */
191 ret = rte_service_map_lcore_set(priv->rxp.sid,
194 ERROR("Failed to install Rx interrupts, "
195 "could not map service core");
198 priv->rxp.sstate = SS_RUNNING;
204 * Install failsafe Rx event proxy subsystem.
205 * This is the way the failsafe PMD generates Rx events on behalf of its
209 * Pointer to failsafe private structure.
211 * 0 on success, negative errno value otherwise and rte_errno is set.
214 fs_rx_event_proxy_install(struct fs_priv *priv)
219 * Create the epoll fd and event vector for the proxy service to
220 * wait on for Rx events generated by the subdevices.
222 priv->rxp.efd = fs_epoll_create1(0);
223 if (priv->rxp.efd < 0) {
225 ERROR("Failed to create epoll,"
226 " Rx interrupts will not be supported");
229 priv->rxp.evec = calloc(NUM_RX_PROXIES, sizeof(*priv->rxp.evec));
230 if (priv->rxp.evec == NULL) {
231 ERROR("Failed to allocate memory for event vectors,"
232 " Rx interrupts will not be supported");
236 rc = fs_rx_event_proxy_service_install(priv);
241 if (priv->rxp.efd >= 0) {
242 close(priv->rxp.efd);
245 if (priv->rxp.evec != NULL) {
246 free(priv->rxp.evec);
247 priv->rxp.evec = NULL;
254 * RX Interrupt control per subdevice.
257 * Pointer to sub-device structure.
259 * The operation be performed for the vector.
260 * Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}.
262 * - On success, zero.
263 * - On failure, a negative value.
266 failsafe_eth_rx_intr_ctl_subdevice(struct sub_device *sdev, int op)
268 struct rte_eth_dev *dev;
269 struct rte_eth_dev *fsdev;
277 if (sdev == NULL || (ETH(sdev) == NULL) ||
278 sdev->fs_dev == NULL || (PRIV(sdev->fs_dev) == NULL)) {
279 ERROR("Called with invalid arguments");
283 fsdev = sdev->fs_dev;
284 epfd = PRIV(sdev->fs_dev)->rxp.efd;
288 if (op == RTE_INTR_EVENT_ADD) {
289 ERROR("Proxy events are not initialized");
295 if (dev->data->nb_rx_queues > fsdev->data->nb_rx_queues) {
296 ERROR("subdevice has too many queues,"
297 " Interrupts will not be enabled");
300 for (qid = 0; qid < dev->data->nb_rx_queues; qid++) {
301 fsrxq = fsdev->data->rx_queues[qid];
302 rc = rte_eth_dev_rx_intr_ctl_q(pid, qid, epfd,
305 ERROR("rte_eth_dev_rx_intr_ctl_q failed for "
306 "port %d queue %d, epfd %d, error %d",
315 * Install Rx interrupts subsystem for a subdevice.
316 * This is a support for dynamically adding subdevices.
319 * Pointer to subdevice structure.
322 * 0 on success, negative errno value otherwise and rte_errno is set.
324 int failsafe_rx_intr_install_subdevice(struct sub_device *sdev)
328 struct rte_eth_dev *fsdev;
330 const struct rte_intr_conf *const intr_conf =
331 Ð(sdev)->data->dev_conf.intr_conf;
333 fsdev = sdev->fs_dev;
334 rxq = (struct rxq **)fsdev->data->rx_queues;
335 if (intr_conf->rxq == 0)
337 rc = failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_ADD);
340 /* enable interrupts on already-enabled queues */
341 for (qid = 0; qid < ETH(sdev)->data->nb_rx_queues; qid++) {
342 if (rxq[qid]->enable_events) {
343 int ret = rte_eth_dev_rx_intr_enable(PORT_ID(sdev),
345 if (ret && (ret != -ENOTSUP)) {
346 ERROR("Failed to enable interrupts on "
347 "port %d queue %d", PORT_ID(sdev), qid);
356 * Uninstall Rx interrupts subsystem for a subdevice.
357 * This is a support for dynamically removing subdevices.
360 * Pointer to subdevice structure.
363 * 0 on success, negative errno value otherwise and rte_errno is set.
365 void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev)
368 struct rte_eth_dev *fsdev;
371 fsdev = sdev->fs_dev;
372 for (qid = 0; qid < ETH(sdev)->data->nb_rx_queues; qid++) {
373 if (qid < fsdev->data->nb_rx_queues) {
374 fsrxq = fsdev->data->rx_queues[qid];
375 if (fsrxq->enable_events)
376 rte_eth_dev_rx_intr_disable(PORT_ID(sdev),
380 failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_DEL);
384 * Uninstall failsafe Rx event proxy.
387 * Pointer to failsafe private structure.
390 fs_rx_event_proxy_uninstall(struct fs_priv *priv)
392 fs_rx_event_proxy_service_uninstall(priv);
393 if (priv->rxp.evec != NULL) {
394 free(priv->rxp.evec);
395 priv->rxp.evec = NULL;
397 if (priv->rxp.efd > 0) {
398 close(priv->rxp.efd);
404 * Uninstall failsafe interrupt vector.
407 * Pointer to failsafe private structure.
410 fs_rx_intr_vec_uninstall(struct fs_priv *priv)
412 struct rte_intr_handle *intr_handle;
414 intr_handle = &priv->intr_handle;
415 if (intr_handle->intr_vec != NULL) {
416 free(intr_handle->intr_vec);
417 intr_handle->intr_vec = NULL;
419 intr_handle->nb_efd = 0;
423 * Installs failsafe interrupt vector to be registered with EAL later on.
426 * Pointer to failsafe private structure.
429 * 0 on success, negative errno value otherwise and rte_errno is set.
432 fs_rx_intr_vec_install(struct fs_priv *priv)
438 struct rte_intr_handle *intr_handle;
440 rxqs_n = priv->dev->data->nb_rx_queues;
441 n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
443 intr_handle = &priv->intr_handle;
444 RTE_ASSERT(intr_handle->intr_vec == NULL);
445 /* Allocate the interrupt vector of the failsafe Rx proxy interrupts */
446 intr_handle->intr_vec = malloc(n * sizeof(intr_handle->intr_vec[0]));
447 if (intr_handle->intr_vec == NULL) {
448 fs_rx_intr_vec_uninstall(priv);
450 ERROR("Failed to allocate memory for interrupt vector,"
451 " Rx interrupts will not be supported");
454 for (i = 0; i < n; i++) {
455 struct rxq *rxq = priv->dev->data->rx_queues[i];
457 /* Skip queues that cannot request interrupts. */
458 if (rxq == NULL || rxq->event_fd < 0) {
459 /* Use invalid intr_vec[] index to disable entry. */
460 intr_handle->intr_vec[i] =
461 RTE_INTR_VEC_RXTX_OFFSET +
462 RTE_MAX_RXTX_INTR_VEC_ID;
465 if (count >= RTE_MAX_RXTX_INTR_VEC_ID) {
467 ERROR("Too many Rx queues for interrupt vector size"
468 " (%d), Rx interrupts cannot be enabled",
469 RTE_MAX_RXTX_INTR_VEC_ID);
470 fs_rx_intr_vec_uninstall(priv);
473 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count;
474 intr_handle->efds[count] = rxq->event_fd;
478 fs_rx_intr_vec_uninstall(priv);
480 intr_handle->nb_efd = count;
481 intr_handle->efd_counter_size = sizeof(uint64_t);
488 * Uninstall failsafe Rx interrupts subsystem.
491 * Pointer to private structure.
494 * 0 on success, negative errno value otherwise and rte_errno is set.
497 failsafe_rx_intr_uninstall(struct rte_eth_dev *dev)
499 struct fs_priv *priv;
500 struct rte_intr_handle *intr_handle;
503 intr_handle = &priv->intr_handle;
504 rte_intr_free_epoll_fd(intr_handle);
505 fs_rx_event_proxy_uninstall(priv);
506 fs_rx_intr_vec_uninstall(priv);
507 dev->intr_handle = NULL;
511 * Install failsafe Rx interrupts subsystem.
514 * Pointer to private structure.
517 * 0 on success, negative errno value otherwise and rte_errno is set.
520 failsafe_rx_intr_install(struct rte_eth_dev *dev)
522 struct fs_priv *priv = PRIV(dev);
523 const struct rte_intr_conf *const intr_conf =
524 &priv->dev->data->dev_conf.intr_conf;
526 if (intr_conf->rxq == 0 || dev->intr_handle != NULL)
528 if (fs_rx_intr_vec_install(priv) < 0)
530 if (fs_rx_event_proxy_install(priv) < 0) {
531 fs_rx_intr_vec_uninstall(priv);
534 dev->intr_handle = &priv->intr_handle;