xref: /dpdk/drivers/net/failsafe/failsafe_intr.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
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 #if defined(LINUX)
11 #include <sys/epoll.h>
12 #endif
13 #include <stdlib.h>
14 #include <unistd.h>
15 
16 #include <rte_alarm.h>
17 #include <rte_errno.h>
18 #include <rte_ethdev.h>
19 #include <rte_interrupts.h>
20 #include <rte_io.h>
21 #include <rte_service_component.h>
22 
23 #include "failsafe_private.h"
24 
25 #define NUM_RX_PROXIES (FAILSAFE_MAX_ETHPORTS * RTE_MAX_RXTX_INTR_VEC_ID)
26 
27 
28 /**
29  * Open an epoll file descriptor.
30  *
31  * @param flags
32  *   Flags for defining epoll behavior.
33  * @return
34  *   0 on success, negative errno value otherwise.
35  */
36 static int
37 fs_epoll_create1(int flags)
38 {
39 #if defined(LINUX)
40 	return epoll_create1(flags);
41 #elif defined(BSD)
42 	RTE_SET_USED(flags);
43 	return -ENOTSUP;
44 #endif
45 }
46 
47 /**
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.
51  *
52  * @param priv
53  *   Pointer to failsafe private structure.
54  * @return
55  *   0 on success, negative errno value otherwise.
56  */
57 static int
58 fs_rx_event_proxy_routine(void *data)
59 {
60 	struct fs_priv *priv;
61 	struct rxq *rxq;
62 	struct rte_epoll_event *events;
63 	uint64_t u64;
64 	int i, n;
65 	int rc = 0;
66 
67 	u64 = 1;
68 	priv = data;
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)) !=
75 			    sizeof(u64)) {
76 				ERROR("Failed to proxy Rx event to socket %d",
77 				       rxq->event_fd);
78 				rc = -EIO;
79 			}
80 		}
81 	}
82 	return rc;
83 }
84 
85 /**
86  * Uninstall failsafe Rx event proxy service.
87  *
88  * @param priv
89  *   Pointer to failsafe private structure.
90  */
91 static void
92 fs_rx_event_proxy_service_uninstall(struct fs_priv *priv)
93 {
94 	/* Unregister the event service. */
95 	switch (priv->rxp.sstate) {
96 	case SS_RUNNING:
97 		rte_service_map_lcore_set(priv->rxp.sid, priv->rxp.scid, 0);
98 		/* fall through */
99 	case SS_READY:
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);
103 		/* fall through */
104 	case SS_REGISTERED:
105 		rte_service_component_unregister(priv->rxp.sid);
106 		/* fall through */
107 	default:
108 		break;
109 	}
110 }
111 
112 /**
113  * Install the failsafe Rx event proxy service.
114  *
115  * @param priv
116  *   Pointer to failsafe private structure.
117  * @return
118  *   0 on success, negative errno value otherwise.
119  */
120 static int
121 fs_rx_event_proxy_service_install(struct fs_priv *priv)
122 {
123 	struct rte_service_spec service;
124 	int32_t num_service_cores;
125 	int ret = 0;
126 
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");
131 		return -ENOTSUP;
132 	}
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->data->name);
137 	service.socket_id = priv->data->numa_node;
138 	service.callback = fs_rx_event_proxy_routine;
139 	service.callback_userdata = priv;
140 
141 	if (priv->rxp.sstate == SS_NO_SERVICE) {
142 		uint32_t service_core_list[num_service_cores];
143 
144 		/* get a service core to work with */
145 		ret = rte_service_lcore_list(service_core_list,
146 					     num_service_cores);
147 		if (ret <= 0) {
148 			ERROR("Failed to install Rx interrupts, "
149 			      "service core list empty or corrupted");
150 			return -ENOTSUP;
151 		}
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");
156 			return ret;
157 		}
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");
163 			return ret;
164 		}
165 		/* register our service */
166 		int32_t ret = rte_service_component_register(&service,
167 							     &priv->rxp.sid);
168 		if (ret) {
169 			ERROR("service register() failed");
170 			return -ENOEXEC;
171 		}
172 		priv->rxp.sstate = SS_REGISTERED;
173 		/* run the service */
174 		ret = rte_service_component_runstate_set(priv->rxp.sid, 1);
175 		if (ret < 0) {
176 			ERROR("Failed Setting component runstate");
177 			return ret;
178 		}
179 		ret = rte_service_set_stats_enable(priv->rxp.sid, 1);
180 		if (ret < 0) {
181 			ERROR("Failed enabling stats");
182 			return ret;
183 		}
184 		ret = rte_service_runstate_set(priv->rxp.sid, 1);
185 		if (ret < 0) {
186 			ERROR("Failed to run service");
187 			return ret;
188 		}
189 		priv->rxp.sstate = SS_READY;
190 		/* map the service with the service core */
191 		ret = rte_service_map_lcore_set(priv->rxp.sid,
192 						priv->rxp.scid, 1);
193 		if (ret) {
194 			ERROR("Failed to install Rx interrupts, "
195 			      "could not map service core");
196 			return ret;
197 		}
198 		priv->rxp.sstate = SS_RUNNING;
199 	}
200 	return 0;
201 }
202 
203 /**
204  * Install failsafe Rx event proxy subsystem.
205  * This is the way the failsafe PMD generates Rx events on behalf of its
206  * subdevices.
207  *
208  * @param priv
209  *   Pointer to failsafe private structure.
210  * @return
211  *   0 on success, negative errno value otherwise and rte_errno is set.
212  */
213 static int
214 fs_rx_event_proxy_install(struct fs_priv *priv)
215 {
216 	int rc = 0;
217 
218 	/*
219 	 * Create the epoll fd and event vector for the proxy service to
220 	 * wait on for Rx events generated by the subdevices.
221 	 */
222 	priv->rxp.efd = fs_epoll_create1(0);
223 	if (priv->rxp.efd < 0) {
224 		rte_errno = errno;
225 		ERROR("Failed to create epoll,"
226 		      " Rx interrupts will not be supported");
227 		return -rte_errno;
228 	}
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");
233 		rc = -ENOMEM;
234 		goto error;
235 	}
236 	rc = fs_rx_event_proxy_service_install(priv);
237 	if (rc < 0)
238 		goto error;
239 	return 0;
240 error:
241 	if (priv->rxp.efd >= 0) {
242 		close(priv->rxp.efd);
243 		priv->rxp.efd = -1;
244 	}
245 	if (priv->rxp.evec != NULL) {
246 		free(priv->rxp.evec);
247 		priv->rxp.evec = NULL;
248 	}
249 	rte_errno = -rc;
250 	return rc;
251 }
252 
253 /**
254  * RX Interrupt control per subdevice.
255  *
256  * @param sdev
257  *   Pointer to sub-device structure.
258  * @param op
259  *   The operation be performed for the vector.
260  *   Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}.
261  * @return
262  *   - On success, zero.
263  *   - On failure, a negative value.
264  */
265 static int
266 failsafe_eth_rx_intr_ctl_subdevice(struct sub_device *sdev, int op)
267 {
268 	struct rte_eth_dev *dev;
269 	struct rte_eth_dev *fsdev;
270 	int epfd;
271 	uint16_t pid;
272 	uint16_t qid;
273 	struct rxq *fsrxq;
274 	int rc;
275 	int ret = 0;
276 
277 	fsdev = fs_dev(sdev);
278 	if (sdev == NULL || (ETH(sdev) == NULL) ||
279 		fsdev == NULL || (PRIV(fsdev) == NULL)) {
280 		ERROR("Called with invalid arguments");
281 		return -EINVAL;
282 	}
283 	dev = ETH(sdev);
284 	epfd = PRIV(fsdev)->rxp.efd;
285 	pid = PORT_ID(sdev);
286 
287 	if (epfd <= 0) {
288 		if (op == RTE_INTR_EVENT_ADD) {
289 			ERROR("Proxy events are not initialized");
290 			return -EBADF;
291 		} else {
292 			return 0;
293 		}
294 	}
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");
298 			return -E2BIG;
299 	}
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,
303 					       op, (void *)fsrxq);
304 		if (rc) {
305 			ERROR("rte_eth_dev_rx_intr_ctl_q failed for "
306 			      "port %d  queue %d, epfd %d, error %d",
307 			      pid, qid, epfd, rc);
308 			ret = rc;
309 		}
310 	}
311 	return ret;
312 }
313 
314 /**
315  * Install Rx interrupts subsystem for a subdevice.
316  * This is a support for dynamically adding subdevices.
317  *
318  * @param sdev
319  *   Pointer to subdevice structure.
320  *
321  * @return
322  *   0 on success, negative errno value otherwise and rte_errno is set.
323  */
324 int failsafe_rx_intr_install_subdevice(struct sub_device *sdev)
325 {
326 	int rc;
327 	int qid;
328 	struct rte_eth_dev *fsdev;
329 	struct rxq **rxq;
330 	const struct rte_eth_intr_conf *const intr_conf =
331 				&ETH(sdev)->data->dev_conf.intr_conf;
332 
333 	fsdev = fs_dev(sdev);
334 	rxq = (struct rxq **)fsdev->data->rx_queues;
335 	if (intr_conf->rxq == 0)
336 		return 0;
337 	rc = failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_ADD);
338 	if (rc)
339 		return rc;
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),
344 							     qid);
345 			if (ret && (ret != -ENOTSUP)) {
346 				ERROR("Failed to enable interrupts on "
347 				      "port %d queue %d", PORT_ID(sdev), qid);
348 				rc = ret;
349 			}
350 		}
351 	}
352 	return rc;
353 }
354 
355 /**
356  * Uninstall Rx interrupts subsystem for a subdevice.
357  * This is a support for dynamically removing subdevices.
358  *
359  * @param sdev
360  *   Pointer to subdevice structure.
361  *
362  * @return
363  *   0 on success, negative errno value otherwise and rte_errno is set.
364  */
365 void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev)
366 {
367 	int qid;
368 	struct rte_eth_dev *fsdev;
369 	struct rxq *fsrxq;
370 
371 	fsdev = fs_dev(sdev);
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 != NULL && fsrxq->enable_events)
376 				rte_eth_dev_rx_intr_disable(PORT_ID(sdev),
377 							    qid);
378 		}
379 	}
380 	failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_DEL);
381 }
382 
383 /**
384  * Uninstall failsafe Rx event proxy.
385  *
386  * @param priv
387  *   Pointer to failsafe private structure.
388  */
389 static void
390 fs_rx_event_proxy_uninstall(struct fs_priv *priv)
391 {
392 	fs_rx_event_proxy_service_uninstall(priv);
393 	if (priv->rxp.evec != NULL) {
394 		free(priv->rxp.evec);
395 		priv->rxp.evec = NULL;
396 	}
397 	if (priv->rxp.efd >= 0) {
398 		close(priv->rxp.efd);
399 		priv->rxp.efd = -1;
400 	}
401 }
402 
403 /**
404  * Uninstall failsafe interrupt vector.
405  *
406  * @param priv
407  *   Pointer to failsafe private structure.
408  */
409 static void
410 fs_rx_intr_vec_uninstall(struct fs_priv *priv)
411 {
412 	struct rte_intr_handle *intr_handle;
413 
414 	intr_handle = priv->intr_handle;
415 	rte_intr_vec_list_free(intr_handle);
416 
417 	rte_intr_nb_efd_set(intr_handle, 0);
418 }
419 
420 /**
421  * Installs failsafe interrupt vector to be registered with EAL later on.
422  *
423  * @param priv
424  *   Pointer to failsafe private structure.
425  *
426  * @return
427  *   0 on success, negative errno value otherwise and rte_errno is set.
428  */
429 static int
430 fs_rx_intr_vec_install(struct fs_priv *priv)
431 {
432 	unsigned int i;
433 	unsigned int rxqs_n;
434 	unsigned int n;
435 	unsigned int count;
436 	struct rte_intr_handle *intr_handle;
437 
438 	rxqs_n = priv->data->nb_rx_queues;
439 	n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
440 	count = 0;
441 	intr_handle = priv->intr_handle;
442 	/* Allocate the interrupt vector of the failsafe Rx proxy interrupts */
443 	if (rte_intr_vec_list_alloc(intr_handle, NULL, n)) {
444 		fs_rx_intr_vec_uninstall(priv);
445 		rte_errno = ENOMEM;
446 		ERROR("Failed to allocate memory for interrupt vector,"
447 		      " Rx interrupts will not be supported");
448 		return -rte_errno;
449 	}
450 	for (i = 0; i < n; i++) {
451 		struct rxq *rxq = priv->data->rx_queues[i];
452 
453 		/* Skip queues that cannot request interrupts. */
454 		if (rxq == NULL || rxq->event_fd < 0) {
455 			/* Use invalid intr_vec[] index to disable entry. */
456 			if (rte_intr_vec_list_index_set(intr_handle, i,
457 			RTE_INTR_VEC_RXTX_OFFSET + RTE_MAX_RXTX_INTR_VEC_ID))
458 				return -rte_errno;
459 			continue;
460 		}
461 		if (count >= RTE_MAX_RXTX_INTR_VEC_ID) {
462 			rte_errno = E2BIG;
463 			ERROR("Too many Rx queues for interrupt vector size"
464 			      " (%d), Rx interrupts cannot be enabled",
465 			      RTE_MAX_RXTX_INTR_VEC_ID);
466 			fs_rx_intr_vec_uninstall(priv);
467 			return -rte_errno;
468 		}
469 		if (rte_intr_vec_list_index_set(intr_handle, i,
470 					RTE_INTR_VEC_RXTX_OFFSET + count))
471 			return -rte_errno;
472 
473 		if (rte_intr_efds_index_set(intr_handle, count,
474 						   rxq->event_fd))
475 			return -rte_errno;
476 		count++;
477 	}
478 	if (count == 0) {
479 		fs_rx_intr_vec_uninstall(priv);
480 	} else {
481 		if (rte_intr_nb_efd_set(intr_handle, count))
482 			return -rte_errno;
483 
484 		if (rte_intr_efd_counter_size_set(intr_handle,
485 				sizeof(uint64_t)))
486 			return -rte_errno;
487 	}
488 	return 0;
489 }
490 
491 
492 /**
493  * Uninstall failsafe Rx interrupts subsystem.
494  *
495  * @param priv
496  *   Pointer to private structure.
497  *
498  * @return
499  *   0 on success, negative errno value otherwise and rte_errno is set.
500  */
501 void
502 failsafe_rx_intr_uninstall(struct rte_eth_dev *dev)
503 {
504 	struct fs_priv *priv;
505 	struct rte_intr_handle *intr_handle;
506 
507 	priv = PRIV(dev);
508 	intr_handle = priv->intr_handle;
509 	rte_intr_free_epoll_fd(intr_handle);
510 	fs_rx_event_proxy_uninstall(priv);
511 	fs_rx_intr_vec_uninstall(priv);
512 	dev->intr_handle = NULL;
513 }
514 
515 /**
516  * Install failsafe Rx interrupts subsystem.
517  *
518  * @param priv
519  *   Pointer to private structure.
520  *
521  * @return
522  *   0 on success, negative errno value otherwise and rte_errno is set.
523  */
524 int
525 failsafe_rx_intr_install(struct rte_eth_dev *dev)
526 {
527 	struct fs_priv *priv = PRIV(dev);
528 	const struct rte_eth_intr_conf *const intr_conf =
529 			&priv->data->dev_conf.intr_conf;
530 
531 	if (intr_conf->rxq == 0 || dev->intr_handle != NULL)
532 		return 0;
533 	if (fs_rx_intr_vec_install(priv) < 0)
534 		return -rte_errno;
535 	if (fs_rx_event_proxy_install(priv) < 0) {
536 		fs_rx_intr_vec_uninstall(priv);
537 		return -rte_errno;
538 	}
539 	dev->intr_handle = priv->intr_handle;
540 	return 0;
541 }
542