Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2017 6WIND S.A.
3 : : * Copyright 2017 Mellanox Technologies, Ltd
4 : : */
5 : :
6 : : #include <stdbool.h>
7 : : #include <stdint.h>
8 : : #include <unistd.h>
9 : : #ifdef RTE_EXEC_ENV_LINUX
10 : : #include <sys/eventfd.h>
11 : : #endif
12 : :
13 : : #include <rte_debug.h>
14 : : #include <rte_atomic.h>
15 : : #include <ethdev_driver.h>
16 : : #include <rte_malloc.h>
17 : : #include <rte_flow.h>
18 : : #include <rte_cycles.h>
19 : : #include <rte_ethdev.h>
20 : : #include <rte_string_fns.h>
21 : :
22 : : #include "failsafe_private.h"
23 : :
24 : : static int
25 : 0 : fs_dev_configure(struct rte_eth_dev *dev)
26 : : {
27 : : struct sub_device *sdev;
28 : : uint8_t i;
29 : : int ret;
30 : :
31 : 0 : ret = fs_lock(dev, 0);
32 [ # # ]: 0 : if (ret != 0)
33 : : return ret;
34 [ # # # # ]: 0 : FOREACH_SUBDEV(sdev, i, dev) {
35 : : int rmv_interrupt = 0;
36 : : int lsc_interrupt = 0;
37 : : int lsc_enabled;
38 : :
39 [ # # ]: 0 : if (sdev->state != DEV_PROBED &&
40 [ # # # # ]: 0 : !(PRIV(dev)->alarm_lock == 0 && sdev->state == DEV_ACTIVE))
41 : 0 : continue;
42 : :
43 [ # # ]: 0 : rmv_interrupt = ETH(sdev)->data->dev_flags &
44 : : RTE_ETH_DEV_INTR_RMV;
45 [ # # ]: 0 : if (rmv_interrupt) {
46 : 0 : DEBUG("Enabling RMV interrupts for sub_device %d", i);
47 : 0 : dev->data->dev_conf.intr_conf.rmv = 1;
48 : : } else {
49 : 0 : DEBUG("sub_device %d does not support RMV event", i);
50 : : }
51 : 0 : lsc_enabled = dev->data->dev_conf.intr_conf.lsc;
52 [ # # ]: 0 : lsc_interrupt = lsc_enabled &&
53 [ # # # # ]: 0 : (ETH(sdev)->data->dev_flags &
54 : : RTE_ETH_DEV_INTR_LSC);
55 : : if (lsc_interrupt) {
56 : 0 : DEBUG("Enabling LSC interrupts for sub_device %d", i);
57 : 0 : dev->data->dev_conf.intr_conf.lsc = 1;
58 [ # # ]: 0 : } else if (lsc_enabled && !lsc_interrupt) {
59 : 0 : DEBUG("Disabling LSC interrupts for sub_device %d", i);
60 : 0 : dev->data->dev_conf.intr_conf.lsc = 0;
61 : : }
62 : 0 : DEBUG("Configuring sub-device %d", i);
63 : 0 : ret = rte_eth_dev_configure(PORT_ID(sdev),
64 : 0 : dev->data->nb_rx_queues,
65 : 0 : dev->data->nb_tx_queues,
66 : 0 : &dev->data->dev_conf);
67 [ # # ]: 0 : if (ret) {
68 : 0 : if (!fs_err(sdev, ret))
69 : 0 : continue;
70 : 0 : ERROR("Could not configure sub_device %d", i);
71 : 0 : fs_unlock(dev, 0);
72 : 0 : return ret;
73 : : }
74 [ # # # # ]: 0 : if (rmv_interrupt && sdev->rmv_callback == 0) {
75 : 0 : ret = rte_eth_dev_callback_register(PORT_ID(sdev),
76 : : RTE_ETH_EVENT_INTR_RMV,
77 : : failsafe_eth_rmv_event_callback,
78 : : sdev);
79 [ # # ]: 0 : if (ret)
80 : 0 : WARN("Failed to register RMV callback for sub_device %d",
81 : : SUB_ID(sdev));
82 : : else
83 : 0 : sdev->rmv_callback = 1;
84 : : }
85 : 0 : dev->data->dev_conf.intr_conf.rmv = 0;
86 [ # # # # ]: 0 : if (lsc_interrupt && sdev->lsc_callback == 0) {
87 : 0 : ret = rte_eth_dev_callback_register(PORT_ID(sdev),
88 : : RTE_ETH_EVENT_INTR_LSC,
89 : : failsafe_eth_lsc_event_callback,
90 : : dev);
91 [ # # ]: 0 : if (ret)
92 : 0 : WARN("Failed to register LSC callback for sub_device %d",
93 : : SUB_ID(sdev));
94 : : else
95 : 0 : sdev->lsc_callback = 1;
96 : : }
97 : 0 : dev->data->dev_conf.intr_conf.lsc = lsc_enabled;
98 : 0 : sdev->state = DEV_ACTIVE;
99 : : }
100 [ # # ]: 0 : if (PRIV(dev)->state < DEV_ACTIVE)
101 : 0 : PRIV(dev)->state = DEV_ACTIVE;
102 : 0 : fs_unlock(dev, 0);
103 : 0 : return 0;
104 : : }
105 : :
106 : : static void
107 : 0 : fs_set_queues_state_start(struct rte_eth_dev *dev)
108 : : {
109 : : struct rxq *rxq;
110 : : struct txq *txq;
111 : : uint16_t i;
112 : :
113 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
114 [ # # ]: 0 : __rte_assume(i < RTE_MAX_QUEUES_PER_PORT);
115 : 0 : rxq = dev->data->rx_queues[i];
116 [ # # # # ]: 0 : if (rxq != NULL && !rxq->info.conf.rx_deferred_start)
117 : 0 : dev->data->rx_queue_state[i] =
118 : : RTE_ETH_QUEUE_STATE_STARTED;
119 : : }
120 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
121 [ # # ]: 0 : __rte_assume(i < RTE_MAX_QUEUES_PER_PORT);
122 : 0 : txq = dev->data->tx_queues[i];
123 [ # # # # ]: 0 : if (txq != NULL && !txq->info.conf.tx_deferred_start)
124 : 0 : dev->data->tx_queue_state[i] =
125 : : RTE_ETH_QUEUE_STATE_STARTED;
126 : : }
127 : 0 : }
128 : :
129 : : static int
130 : 0 : fs_dev_start(struct rte_eth_dev *dev)
131 : : {
132 : : struct sub_device *sdev;
133 : : uint8_t i;
134 : : int ret;
135 : :
136 : 0 : ret = fs_lock(dev, 0);
137 [ # # ]: 0 : if (ret != 0)
138 : : return ret;
139 : 0 : ret = failsafe_rx_intr_install(dev);
140 [ # # ]: 0 : if (ret) {
141 : 0 : fs_unlock(dev, 0);
142 : 0 : return ret;
143 : : }
144 [ # # # # ]: 0 : FOREACH_SUBDEV(sdev, i, dev) {
145 [ # # ]: 0 : if (sdev->state != DEV_ACTIVE)
146 : 0 : continue;
147 : 0 : DEBUG("Starting sub_device %d", i);
148 : 0 : ret = rte_eth_dev_start(PORT_ID(sdev));
149 [ # # ]: 0 : if (ret) {
150 : 0 : if (!fs_err(sdev, ret))
151 : 0 : continue;
152 : 0 : fs_unlock(dev, 0);
153 : 0 : return ret;
154 : : }
155 : 0 : ret = failsafe_rx_intr_install_subdevice(sdev);
156 [ # # ]: 0 : if (ret) {
157 : 0 : if (!fs_err(sdev, ret))
158 : 0 : continue;
159 [ # # ]: 0 : if (fs_err(sdev, rte_eth_dev_stop(PORT_ID(sdev))) < 0)
160 : 0 : ERROR("Failed to stop sub-device %u",
161 : : SUB_ID(sdev));
162 : 0 : fs_unlock(dev, 0);
163 : 0 : return ret;
164 : : }
165 : 0 : sdev->state = DEV_STARTED;
166 : : }
167 [ # # ]: 0 : if (PRIV(dev)->state < DEV_STARTED) {
168 : 0 : PRIV(dev)->state = DEV_STARTED;
169 : 0 : fs_set_queues_state_start(dev);
170 : : }
171 : 0 : fs_switch_dev(dev, NULL);
172 : 0 : fs_unlock(dev, 0);
173 : 0 : return 0;
174 : : }
175 : :
176 : : static void
177 : 0 : fs_set_queues_state_stop(struct rte_eth_dev *dev)
178 : : {
179 : : uint16_t i;
180 : :
181 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
182 [ # # ]: 0 : __rte_assume(i < RTE_MAX_QUEUES_PER_PORT);
183 [ # # ]: 0 : if (dev->data->rx_queues[i] != NULL)
184 : 0 : dev->data->rx_queue_state[i] =
185 : : RTE_ETH_QUEUE_STATE_STOPPED;
186 : : }
187 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
188 [ # # ]: 0 : __rte_assume(i < RTE_MAX_QUEUES_PER_PORT);
189 [ # # ]: 0 : if (dev->data->tx_queues[i] != NULL)
190 : 0 : dev->data->tx_queue_state[i] =
191 : : RTE_ETH_QUEUE_STATE_STOPPED;
192 : : }
193 : 0 : }
194 : :
195 : : static int
196 : 0 : fs_dev_stop(struct rte_eth_dev *dev)
197 : : {
198 : : struct sub_device *sdev;
199 : : uint8_t i;
200 : : int ret;
201 : :
202 : 0 : ret = fs_lock(dev, 0);
203 [ # # ]: 0 : if (ret != 0)
204 : : return ret;
205 : 0 : PRIV(dev)->state = DEV_STARTED - 1;
206 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_STARTED) {
207 : 0 : ret = rte_eth_dev_stop(PORT_ID(sdev));
208 [ # # ]: 0 : if (fs_err(sdev, ret) < 0) {
209 : 0 : ERROR("Failed to stop device %u",
210 : : PORT_ID(sdev));
211 : 0 : PRIV(dev)->state = DEV_STARTED + 1;
212 : 0 : fs_unlock(dev, 0);
213 : 0 : return ret;
214 : : }
215 : 0 : failsafe_rx_intr_uninstall_subdevice(sdev);
216 : 0 : sdev->state = DEV_STARTED - 1;
217 : : }
218 : 0 : failsafe_rx_intr_uninstall(dev);
219 : 0 : fs_set_queues_state_stop(dev);
220 : 0 : fs_unlock(dev, 0);
221 : :
222 : 0 : return 0;
223 : : }
224 : :
225 : : static int
226 : 0 : fs_dev_set_link_up(struct rte_eth_dev *dev)
227 : : {
228 : : struct sub_device *sdev;
229 : : uint8_t i;
230 : : int ret;
231 : :
232 : 0 : ret = fs_lock(dev, 0);
233 [ # # ]: 0 : if (ret != 0)
234 : : return ret;
235 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
236 : 0 : DEBUG("Calling rte_eth_dev_set_link_up on sub_device %d", i);
237 : 0 : ret = rte_eth_dev_set_link_up(PORT_ID(sdev));
238 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
239 : 0 : ERROR("Operation rte_eth_dev_set_link_up failed for sub_device %d"
240 : : " with error %d", i, ret);
241 : 0 : fs_unlock(dev, 0);
242 : 0 : return ret;
243 : : }
244 : : }
245 : 0 : fs_unlock(dev, 0);
246 : 0 : return 0;
247 : : }
248 : :
249 : : static int
250 : 0 : fs_dev_set_link_down(struct rte_eth_dev *dev)
251 : : {
252 : : struct sub_device *sdev;
253 : : uint8_t i;
254 : : int ret;
255 : :
256 : 0 : ret = fs_lock(dev, 0);
257 [ # # ]: 0 : if (ret != 0)
258 : : return ret;
259 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
260 : 0 : DEBUG("Calling rte_eth_dev_set_link_down on sub_device %d", i);
261 : 0 : ret = rte_eth_dev_set_link_down(PORT_ID(sdev));
262 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
263 : 0 : ERROR("Operation rte_eth_dev_set_link_down failed for sub_device %d"
264 : : " with error %d", i, ret);
265 : 0 : fs_unlock(dev, 0);
266 : 0 : return ret;
267 : : }
268 : : }
269 : 0 : fs_unlock(dev, 0);
270 : 0 : return 0;
271 : : }
272 : :
273 : : static int
274 : 0 : fs_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
275 : : {
276 : : struct sub_device *sdev;
277 : : uint8_t i;
278 : : int ret;
279 : : int err = 0;
280 : : bool failure = true;
281 : :
282 : 0 : ret = fs_lock(dev, 0);
283 [ # # ]: 0 : if (ret != 0)
284 : : return ret;
285 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
286 [ # # ]: 0 : uint16_t port_id = ETH(sdev)->data->port_id;
287 : :
288 : 0 : ret = rte_eth_dev_rx_queue_stop(port_id, rx_queue_id);
289 : : ret = fs_err(sdev, ret);
290 [ # # ]: 0 : if (ret) {
291 : 0 : ERROR("Rx queue stop failed for subdevice %d", i);
292 : : err = ret;
293 : : } else {
294 : : failure = false;
295 : : }
296 : : }
297 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
298 : 0 : fs_unlock(dev, 0);
299 : : /* Return 0 in case of at least one successful queue stop */
300 [ # # ]: 0 : return (failure) ? err : 0;
301 : : }
302 : :
303 : : static int
304 : 0 : fs_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
305 : : {
306 : : struct sub_device *sdev;
307 : : uint8_t i;
308 : : int ret;
309 : :
310 : 0 : ret = fs_lock(dev, 0);
311 [ # # ]: 0 : if (ret != 0)
312 : : return ret;
313 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
314 [ # # ]: 0 : uint16_t port_id = ETH(sdev)->data->port_id;
315 : :
316 : 0 : ret = rte_eth_dev_rx_queue_start(port_id, rx_queue_id);
317 : : ret = fs_err(sdev, ret);
318 [ # # ]: 0 : if (ret) {
319 : 0 : ERROR("Rx queue start failed for subdevice %d", i);
320 : 0 : fs_rx_queue_stop(dev, rx_queue_id);
321 : 0 : fs_unlock(dev, 0);
322 : 0 : return ret;
323 : : }
324 : : }
325 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
326 : 0 : fs_unlock(dev, 0);
327 : 0 : return 0;
328 : : }
329 : :
330 : : static int
331 : 0 : fs_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
332 : : {
333 : : struct sub_device *sdev;
334 : : uint8_t i;
335 : : int ret;
336 : : int err = 0;
337 : : bool failure = true;
338 : :
339 : 0 : ret = fs_lock(dev, 0);
340 [ # # ]: 0 : if (ret != 0)
341 : : return ret;
342 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
343 [ # # ]: 0 : uint16_t port_id = ETH(sdev)->data->port_id;
344 : :
345 : 0 : ret = rte_eth_dev_tx_queue_stop(port_id, tx_queue_id);
346 : : ret = fs_err(sdev, ret);
347 [ # # ]: 0 : if (ret) {
348 : 0 : ERROR("Tx queue stop failed for subdevice %d", i);
349 : : err = ret;
350 : : } else {
351 : : failure = false;
352 : : }
353 : : }
354 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
355 : 0 : fs_unlock(dev, 0);
356 : : /* Return 0 in case of at least one successful queue stop */
357 [ # # ]: 0 : return (failure) ? err : 0;
358 : : }
359 : :
360 : : static int
361 : 0 : fs_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
362 : : {
363 : : struct sub_device *sdev;
364 : : uint8_t i;
365 : : int ret;
366 : :
367 : 0 : ret = fs_lock(dev, 0);
368 [ # # ]: 0 : if (ret != 0)
369 : : return ret;
370 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
371 [ # # ]: 0 : uint16_t port_id = ETH(sdev)->data->port_id;
372 : :
373 : 0 : ret = rte_eth_dev_tx_queue_start(port_id, tx_queue_id);
374 : : ret = fs_err(sdev, ret);
375 [ # # ]: 0 : if (ret) {
376 : 0 : ERROR("Tx queue start failed for subdevice %d", i);
377 : 0 : fs_tx_queue_stop(dev, tx_queue_id);
378 : 0 : fs_unlock(dev, 0);
379 : 0 : return ret;
380 : : }
381 : : }
382 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
383 : 0 : fs_unlock(dev, 0);
384 : 0 : return 0;
385 : : }
386 : :
387 : : static void
388 : 0 : fs_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
389 : : {
390 : : struct sub_device *sdev;
391 : : uint8_t i;
392 : 0 : struct rxq *rxq = dev->data->rx_queues[qid];
393 : :
394 [ # # ]: 0 : if (rxq == NULL)
395 : : return;
396 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
397 : : return;
398 [ # # ]: 0 : if (rxq->event_fd >= 0)
399 : 0 : close(rxq->event_fd);
400 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
401 [ # # # # ]: 0 : if (ETH(sdev)->data->rx_queues != NULL &&
402 [ # # ]: 0 : ETH(sdev)->data->rx_queues[rxq->qid] != NULL)
403 : 0 : SUBOPS(sdev, rx_queue_release)(ETH(sdev), rxq->qid);
404 : : }
405 : 0 : dev->data->rx_queues[rxq->qid] = NULL;
406 : 0 : rte_free(rxq);
407 : 0 : fs_unlock(dev, 0);
408 : : }
409 : :
410 : : static int
411 : 0 : fs_rx_queue_setup(struct rte_eth_dev *dev,
412 : : uint16_t rx_queue_id,
413 : : uint16_t nb_rx_desc,
414 : : unsigned int socket_id,
415 : : const struct rte_eth_rxconf *rx_conf,
416 : : struct rte_mempool *mb_pool)
417 : : {
418 : : struct sub_device *sdev;
419 : : struct rxq *rxq;
420 : : uint8_t i;
421 : : int ret;
422 : :
423 : 0 : ret = fs_lock(dev, 0);
424 [ # # ]: 0 : if (ret != 0)
425 : : return ret;
426 [ # # ]: 0 : if (rx_conf->rx_deferred_start) {
427 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
428 [ # # # # ]: 0 : if (SUBOPS(sdev, rx_queue_start) == NULL) {
429 : 0 : ERROR("Rx queue deferred start is not "
430 : : "supported for subdevice %d", i);
431 : 0 : fs_unlock(dev, 0);
432 : 0 : return -EINVAL;
433 : : }
434 : : }
435 : : }
436 : 0 : rxq = dev->data->rx_queues[rx_queue_id];
437 [ # # ]: 0 : if (rxq != NULL) {
438 : 0 : fs_rx_queue_release(dev, rx_queue_id);
439 : 0 : dev->data->rx_queues[rx_queue_id] = NULL;
440 : : }
441 : 0 : rxq = rte_zmalloc(NULL,
442 : 0 : sizeof(*rxq) +
443 : 0 : sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,
444 : : RTE_CACHE_LINE_SIZE);
445 [ # # ]: 0 : if (rxq == NULL) {
446 : 0 : fs_unlock(dev, 0);
447 : 0 : return -ENOMEM;
448 : : }
449 [ # # # # ]: 0 : FOREACH_SUBDEV(sdev, i, dev)
450 [ # # ]: 0 : rte_atomic64_init(&rxq->refcnt[i]);
451 : 0 : rxq->qid = rx_queue_id;
452 : 0 : rxq->socket_id = socket_id;
453 : 0 : rxq->info.mp = mb_pool;
454 : 0 : rxq->info.conf = *rx_conf;
455 : 0 : rxq->info.nb_desc = nb_rx_desc;
456 : 0 : rxq->priv = PRIV(dev);
457 : 0 : rxq->sdev = PRIV(dev)->subs;
458 : : #ifdef RTE_EXEC_ENV_LINUX
459 : 0 : rxq->event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
460 [ # # ]: 0 : if (rxq->event_fd < 0) {
461 : 0 : ERROR("Failed to create an eventfd: %s", strerror(errno));
462 : 0 : fs_unlock(dev, 0);
463 : 0 : return -errno;
464 : : }
465 : : #else
466 : : rxq->event_fd = -1;
467 : : #endif
468 : 0 : dev->data->rx_queues[rx_queue_id] = rxq;
469 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
470 : 0 : ret = rte_eth_rx_queue_setup(PORT_ID(sdev),
471 : : rx_queue_id,
472 : : nb_rx_desc, socket_id,
473 : : rx_conf, mb_pool);
474 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
475 : 0 : ERROR("RX queue setup failed for sub_device %d", i);
476 : 0 : goto free_rxq;
477 : : }
478 : : }
479 : 0 : fs_unlock(dev, 0);
480 : 0 : return 0;
481 : : free_rxq:
482 : 0 : fs_rx_queue_release(dev, rx_queue_id);
483 : 0 : fs_unlock(dev, 0);
484 : 0 : return ret;
485 : : }
486 : :
487 : : static int
488 : 0 : fs_rx_intr_enable(struct rte_eth_dev *dev, uint16_t idx)
489 : : {
490 : : struct rxq *rxq;
491 : : struct sub_device *sdev;
492 : : uint8_t i;
493 : : int ret;
494 : : int rc = 0;
495 : :
496 : 0 : ret = fs_lock(dev, 0);
497 [ # # ]: 0 : if (ret != 0)
498 : : return ret;
499 [ # # ]: 0 : if (idx >= dev->data->nb_rx_queues) {
500 : : rc = -EINVAL;
501 : 0 : goto unlock;
502 : : }
503 : 0 : rxq = dev->data->rx_queues[idx];
504 [ # # # # ]: 0 : if (rxq == NULL || rxq->event_fd <= 0) {
505 : : rc = -EINVAL;
506 : 0 : goto unlock;
507 : : }
508 : : /* Fail if proxy service is nor running. */
509 [ # # ]: 0 : if (PRIV(dev)->rxp.sstate != SS_RUNNING) {
510 : 0 : ERROR("failsafe interrupt services are not running");
511 : : rc = -EAGAIN;
512 : 0 : goto unlock;
513 : : }
514 : 0 : rxq->enable_events = 1;
515 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
516 : 0 : ret = rte_eth_dev_rx_intr_enable(PORT_ID(sdev), idx);
517 : : ret = fs_err(sdev, ret);
518 [ # # ]: 0 : if (ret)
519 : : rc = ret;
520 : : }
521 : 0 : unlock:
522 : 0 : fs_unlock(dev, 0);
523 [ # # ]: 0 : if (rc)
524 : 0 : rte_errno = -rc;
525 : : return rc;
526 : : }
527 : :
528 : : static int
529 : 0 : fs_rx_intr_disable(struct rte_eth_dev *dev, uint16_t idx)
530 : : {
531 : : struct rxq *rxq;
532 : : struct sub_device *sdev;
533 : : uint64_t u64;
534 : : uint8_t i;
535 : : int rc = 0;
536 : : int ret;
537 : :
538 : 0 : ret = fs_lock(dev, 0);
539 [ # # ]: 0 : if (ret != 0)
540 : : return ret;
541 [ # # ]: 0 : if (idx >= dev->data->nb_rx_queues) {
542 : : rc = -EINVAL;
543 : 0 : goto unlock;
544 : : }
545 : 0 : rxq = dev->data->rx_queues[idx];
546 [ # # # # ]: 0 : if (rxq == NULL || rxq->event_fd <= 0) {
547 : : rc = -EINVAL;
548 : 0 : goto unlock;
549 : : }
550 : 0 : rxq->enable_events = 0;
551 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
552 : 0 : ret = rte_eth_dev_rx_intr_disable(PORT_ID(sdev), idx);
553 : : ret = fs_err(sdev, ret);
554 [ # # ]: 0 : if (ret)
555 : : rc = ret;
556 : : }
557 : : /* Clear pending events */
558 [ # # ]: 0 : while (read(rxq->event_fd, &u64, sizeof(uint64_t)) > 0)
559 : : ;
560 : 0 : unlock:
561 : 0 : fs_unlock(dev, 0);
562 [ # # ]: 0 : if (rc)
563 : 0 : rte_errno = -rc;
564 : : return rc;
565 : : }
566 : :
567 : : static void
568 : 0 : fs_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
569 : : {
570 : : struct sub_device *sdev;
571 : : uint8_t i;
572 : 0 : struct txq *txq = dev->data->tx_queues[qid];
573 : :
574 [ # # ]: 0 : if (txq == NULL)
575 : : return;
576 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
577 : : return;
578 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
579 [ # # # # ]: 0 : if (ETH(sdev)->data->tx_queues != NULL &&
580 [ # # ]: 0 : ETH(sdev)->data->tx_queues[txq->qid] != NULL)
581 : 0 : SUBOPS(sdev, tx_queue_release)(ETH(sdev), txq->qid);
582 : : }
583 : 0 : dev->data->tx_queues[txq->qid] = NULL;
584 : 0 : rte_free(txq);
585 : 0 : fs_unlock(dev, 0);
586 : : }
587 : :
588 : : static int
589 : 0 : fs_tx_queue_setup(struct rte_eth_dev *dev,
590 : : uint16_t tx_queue_id,
591 : : uint16_t nb_tx_desc,
592 : : unsigned int socket_id,
593 : : const struct rte_eth_txconf *tx_conf)
594 : : {
595 : : struct sub_device *sdev;
596 : : struct txq *txq;
597 : : uint8_t i;
598 : : int ret;
599 : :
600 : 0 : ret = fs_lock(dev, 0);
601 [ # # ]: 0 : if (ret != 0)
602 : : return ret;
603 [ # # ]: 0 : if (tx_conf->tx_deferred_start) {
604 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
605 [ # # # # ]: 0 : if (SUBOPS(sdev, tx_queue_start) == NULL) {
606 : 0 : ERROR("Tx queue deferred start is not "
607 : : "supported for subdevice %d", i);
608 : 0 : fs_unlock(dev, 0);
609 : 0 : return -EINVAL;
610 : : }
611 : : }
612 : : }
613 : 0 : txq = dev->data->tx_queues[tx_queue_id];
614 [ # # ]: 0 : if (txq != NULL) {
615 : 0 : fs_tx_queue_release(dev, tx_queue_id);
616 : 0 : dev->data->tx_queues[tx_queue_id] = NULL;
617 : : }
618 : 0 : txq = rte_zmalloc("ethdev TX queue",
619 : 0 : sizeof(*txq) +
620 : 0 : sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,
621 : : RTE_CACHE_LINE_SIZE);
622 [ # # ]: 0 : if (txq == NULL) {
623 : 0 : fs_unlock(dev, 0);
624 : 0 : return -ENOMEM;
625 : : }
626 [ # # # # ]: 0 : FOREACH_SUBDEV(sdev, i, dev)
627 [ # # ]: 0 : rte_atomic64_init(&txq->refcnt[i]);
628 : 0 : txq->qid = tx_queue_id;
629 : 0 : txq->socket_id = socket_id;
630 : 0 : txq->info.conf = *tx_conf;
631 : 0 : txq->info.nb_desc = nb_tx_desc;
632 : 0 : txq->priv = PRIV(dev);
633 : 0 : dev->data->tx_queues[tx_queue_id] = txq;
634 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
635 : 0 : ret = rte_eth_tx_queue_setup(PORT_ID(sdev),
636 : : tx_queue_id,
637 : : nb_tx_desc, socket_id,
638 : : tx_conf);
639 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
640 : 0 : ERROR("TX queue setup failed for sub_device %d", i);
641 : 0 : goto free_txq;
642 : : }
643 : : }
644 : 0 : fs_unlock(dev, 0);
645 : 0 : return 0;
646 : : free_txq:
647 : 0 : fs_tx_queue_release(dev, tx_queue_id);
648 : 0 : fs_unlock(dev, 0);
649 : 0 : return ret;
650 : : }
651 : :
652 : : static void
653 : 0 : fs_dev_free_queues(struct rte_eth_dev *dev)
654 : : {
655 : : uint16_t i;
656 : :
657 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
658 : 0 : fs_rx_queue_release(dev, i);
659 : 0 : dev->data->rx_queues[i] = NULL;
660 : : }
661 : 0 : dev->data->nb_rx_queues = 0;
662 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
663 : 0 : fs_tx_queue_release(dev, i);
664 : 0 : dev->data->tx_queues[i] = NULL;
665 : : }
666 : 0 : dev->data->nb_tx_queues = 0;
667 : 0 : }
668 : :
669 : : int
670 : 0 : failsafe_eth_dev_close(struct rte_eth_dev *dev)
671 : : {
672 : : struct sub_device *sdev;
673 : : uint8_t i;
674 : : int err, ret = 0;
675 : :
676 : 0 : ret = fs_lock(dev, 0);
677 [ # # ]: 0 : if (ret != 0)
678 : : return ret;
679 : 0 : failsafe_hotplug_alarm_cancel(dev);
680 [ # # ]: 0 : if (PRIV(dev)->state == DEV_STARTED) {
681 : 0 : ret = dev->dev_ops->dev_stop(dev);
682 [ # # ]: 0 : if (ret != 0) {
683 : 0 : fs_unlock(dev, 0);
684 : 0 : return ret;
685 : : }
686 : : }
687 : 0 : PRIV(dev)->state = DEV_ACTIVE - 1;
688 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
689 : 0 : DEBUG("Closing sub_device %d", i);
690 : 0 : failsafe_eth_dev_unregister_callbacks(sdev);
691 : 0 : err = rte_eth_dev_close(PORT_ID(sdev));
692 [ # # ]: 0 : if (err) {
693 [ # # ]: 0 : ret = ret ? ret : err;
694 : 0 : ERROR("Error while closing sub-device %u",
695 : : PORT_ID(sdev));
696 : : }
697 : 0 : sdev->state = DEV_ACTIVE - 1;
698 : : }
699 : 0 : rte_eth_dev_callback_unregister(RTE_ETH_ALL, RTE_ETH_EVENT_NEW,
700 : : failsafe_eth_new_event_callback, dev);
701 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
702 : 0 : fs_unlock(dev, 0);
703 : 0 : return ret;
704 : : }
705 : 0 : fs_dev_free_queues(dev);
706 : 0 : err = failsafe_eal_uninit(dev);
707 [ # # ]: 0 : if (err) {
708 [ # # ]: 0 : ret = ret ? ret : err;
709 : 0 : ERROR("Error while uninitializing sub-EAL");
710 : : }
711 : 0 : failsafe_args_free(dev);
712 : 0 : rte_free(PRIV(dev)->subs);
713 : 0 : rte_free(PRIV(dev)->mcast_addrs);
714 : : /* mac_addrs must not be freed alone because part of dev_private */
715 : 0 : dev->data->mac_addrs = NULL;
716 : 0 : fs_unlock(dev, 0);
717 : 0 : err = pthread_mutex_destroy(&PRIV(dev)->hotplug_mutex);
718 [ # # ]: 0 : if (err) {
719 [ # # ]: 0 : ret = ret ? ret : err;
720 : 0 : ERROR("Error while destroying hotplug mutex");
721 : : }
722 : : return ret;
723 : : }
724 : :
725 : : static int
726 : 0 : fs_promiscuous_enable(struct rte_eth_dev *dev)
727 : : {
728 : : struct sub_device *sdev;
729 : : uint8_t i;
730 : : int ret = 0;
731 : :
732 : 0 : ret = fs_lock(dev, 0);
733 [ # # ]: 0 : if (ret != 0)
734 : : return ret;
735 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
736 : 0 : ret = rte_eth_promiscuous_enable(PORT_ID(sdev));
737 : : ret = fs_err(sdev, ret);
738 [ # # ]: 0 : if (ret != 0) {
739 : 0 : ERROR("Promiscuous mode enable failed for subdevice %d",
740 : : PORT_ID(sdev));
741 : 0 : break;
742 : : }
743 : : }
744 [ # # ]: 0 : if (ret != 0) {
745 : : /* Rollback in the case of failure */
746 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
747 : 0 : ret = rte_eth_promiscuous_disable(PORT_ID(sdev));
748 : : ret = fs_err(sdev, ret);
749 [ # # ]: 0 : if (ret != 0)
750 : 0 : ERROR("Promiscuous mode disable during rollback failed for subdevice %d",
751 : : PORT_ID(sdev));
752 : : }
753 : : }
754 : 0 : fs_unlock(dev, 0);
755 : :
756 : 0 : return ret;
757 : : }
758 : :
759 : : static int
760 : 0 : fs_promiscuous_disable(struct rte_eth_dev *dev)
761 : : {
762 : : struct sub_device *sdev;
763 : : uint8_t i;
764 : : int ret = 0;
765 : :
766 : 0 : ret = fs_lock(dev, 0);
767 [ # # ]: 0 : if (ret != 0)
768 : : return ret;
769 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
770 : 0 : ret = rte_eth_promiscuous_disable(PORT_ID(sdev));
771 : : ret = fs_err(sdev, ret);
772 [ # # ]: 0 : if (ret != 0) {
773 : 0 : ERROR("Promiscuous mode disable failed for subdevice %d",
774 : : PORT_ID(sdev));
775 : 0 : break;
776 : : }
777 : : }
778 [ # # ]: 0 : if (ret != 0) {
779 : : /* Rollback in the case of failure */
780 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
781 : 0 : ret = rte_eth_promiscuous_enable(PORT_ID(sdev));
782 : : ret = fs_err(sdev, ret);
783 [ # # ]: 0 : if (ret != 0)
784 : 0 : ERROR("Promiscuous mode enable during rollback failed for subdevice %d",
785 : : PORT_ID(sdev));
786 : : }
787 : : }
788 : 0 : fs_unlock(dev, 0);
789 : :
790 : 0 : return ret;
791 : : }
792 : :
793 : : static int
794 : 0 : fs_allmulticast_enable(struct rte_eth_dev *dev)
795 : : {
796 : : struct sub_device *sdev;
797 : : uint8_t i;
798 : : int ret = 0;
799 : :
800 : 0 : ret = fs_lock(dev, 0);
801 [ # # ]: 0 : if (ret != 0)
802 : : return ret;
803 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
804 : 0 : ret = rte_eth_allmulticast_enable(PORT_ID(sdev));
805 : : ret = fs_err(sdev, ret);
806 [ # # ]: 0 : if (ret != 0) {
807 : 0 : ERROR("All-multicast mode enable failed for subdevice %d",
808 : : PORT_ID(sdev));
809 : 0 : break;
810 : : }
811 : : }
812 [ # # ]: 0 : if (ret != 0) {
813 : : /* Rollback in the case of failure */
814 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
815 : 0 : ret = rte_eth_allmulticast_disable(PORT_ID(sdev));
816 : : ret = fs_err(sdev, ret);
817 [ # # ]: 0 : if (ret != 0)
818 : 0 : ERROR("All-multicast mode disable during rollback failed for subdevice %d",
819 : : PORT_ID(sdev));
820 : : }
821 : : }
822 : 0 : fs_unlock(dev, 0);
823 : :
824 : 0 : return ret;
825 : : }
826 : :
827 : : static int
828 : 0 : fs_allmulticast_disable(struct rte_eth_dev *dev)
829 : : {
830 : : struct sub_device *sdev;
831 : : uint8_t i;
832 : : int ret = 0;
833 : :
834 : 0 : ret = fs_lock(dev, 0);
835 [ # # ]: 0 : if (ret != 0)
836 : : return ret;
837 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
838 : 0 : ret = rte_eth_allmulticast_disable(PORT_ID(sdev));
839 : : ret = fs_err(sdev, ret);
840 [ # # ]: 0 : if (ret != 0) {
841 : 0 : ERROR("All-multicast mode disable failed for subdevice %d",
842 : : PORT_ID(sdev));
843 : 0 : break;
844 : : }
845 : : }
846 [ # # ]: 0 : if (ret != 0) {
847 : : /* Rollback in the case of failure */
848 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
849 : 0 : ret = rte_eth_allmulticast_enable(PORT_ID(sdev));
850 : : ret = fs_err(sdev, ret);
851 [ # # ]: 0 : if (ret != 0)
852 : 0 : ERROR("All-multicast mode enable during rollback failed for subdevice %d",
853 : : PORT_ID(sdev));
854 : : }
855 : : }
856 : 0 : fs_unlock(dev, 0);
857 : :
858 : 0 : return ret;
859 : : }
860 : :
861 : : static int
862 : 0 : fs_link_update(struct rte_eth_dev *dev,
863 : : int wait_to_complete)
864 : : {
865 : : struct sub_device *sdev;
866 : : uint8_t i;
867 : : int ret;
868 : :
869 : 0 : ret = fs_lock(dev, 0);
870 [ # # ]: 0 : if (ret != 0)
871 : : return ret;
872 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
873 : 0 : DEBUG("Calling link_update on sub_device %d", i);
874 [ # # ]: 0 : ret = (SUBOPS(sdev, link_update))(ETH(sdev), wait_to_complete);
875 [ # # # # : 0 : if (ret && ret != -1 && sdev->remove == 0 &&
# # ]
876 : 0 : rte_eth_dev_is_removed(PORT_ID(sdev)) == 0) {
877 : 0 : ERROR("Link update failed for sub_device %d with error %d",
878 : : i, ret);
879 : 0 : fs_unlock(dev, 0);
880 : 0 : return ret;
881 : : }
882 : : }
883 [ # # # # ]: 0 : if (TX_SUBDEV(dev)) {
884 : : struct rte_eth_link *l1;
885 : : struct rte_eth_link *l2;
886 : :
887 : 0 : l1 = &dev->data->dev_link;
888 [ # # ]: 0 : l2 = Ð(TX_SUBDEV(dev))->data->dev_link;
889 [ # # ]: 0 : if (memcmp(l1, l2, sizeof(*l1))) {
890 : 0 : *l1 = *l2;
891 : 0 : fs_unlock(dev, 0);
892 : 0 : return 0;
893 : : }
894 : : }
895 : 0 : fs_unlock(dev, 0);
896 : 0 : return -1;
897 : : }
898 : :
899 : : static int
900 : 0 : fs_stats_get(struct rte_eth_dev *dev,
901 : : struct rte_eth_stats *stats)
902 : : {
903 : : struct rte_eth_stats backup;
904 : : struct sub_device *sdev;
905 : : uint8_t i;
906 : : int ret;
907 : :
908 : 0 : ret = fs_lock(dev, 0);
909 [ # # ]: 0 : if (ret != 0)
910 : : return ret;
911 [ # # ]: 0 : rte_memcpy(stats, &PRIV(dev)->stats_accumulator, sizeof(*stats));
912 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
913 [ # # ]: 0 : struct rte_eth_stats *snapshot = &sdev->stats_snapshot.stats;
914 : : uint64_t *timestamp = &sdev->stats_snapshot.timestamp;
915 : :
916 : : rte_memcpy(&backup, snapshot, sizeof(backup));
917 : 0 : ret = rte_eth_stats_get(PORT_ID(sdev), snapshot);
918 [ # # ]: 0 : if (ret) {
919 : : if (!fs_err(sdev, ret)) {
920 : : rte_memcpy(snapshot, &backup, sizeof(backup));
921 : 0 : goto inc;
922 : : }
923 : 0 : ERROR("Operation rte_eth_stats_get failed for sub_device %d with error %d",
924 : : i, ret);
925 : 0 : *timestamp = 0;
926 : 0 : fs_unlock(dev, 0);
927 : 0 : return ret;
928 : : }
929 : 0 : *timestamp = rte_rdtsc();
930 : 0 : inc:
931 : 0 : failsafe_stats_increment(stats, snapshot);
932 : : }
933 : 0 : fs_unlock(dev, 0);
934 : 0 : return 0;
935 : : }
936 : :
937 : : static int
938 : 0 : fs_stats_reset(struct rte_eth_dev *dev)
939 : : {
940 : : struct sub_device *sdev;
941 : : uint8_t i;
942 : : int ret;
943 : :
944 : 0 : ret = fs_lock(dev, 0);
945 [ # # ]: 0 : if (ret != 0)
946 : : return ret;
947 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
948 : 0 : ret = rte_eth_stats_reset(PORT_ID(sdev));
949 [ # # ]: 0 : if (ret) {
950 : 0 : if (!fs_err(sdev, ret))
951 : 0 : continue;
952 : :
953 : 0 : ERROR("Operation rte_eth_stats_reset failed for sub_device %d with error %d",
954 : : i, ret);
955 : 0 : fs_unlock(dev, 0);
956 : 0 : return ret;
957 : : }
958 : 0 : memset(&sdev->stats_snapshot, 0, sizeof(struct rte_eth_stats));
959 : : }
960 : 0 : memset(&PRIV(dev)->stats_accumulator, 0, sizeof(struct rte_eth_stats));
961 : 0 : fs_unlock(dev, 0);
962 : :
963 : 0 : return 0;
964 : : }
965 : :
966 : : static int
967 : 0 : __fs_xstats_count(struct rte_eth_dev *dev)
968 : : {
969 : : struct sub_device *sdev;
970 : : int count = 0;
971 : : uint8_t i;
972 : : int ret;
973 : :
974 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
975 : 0 : ret = rte_eth_xstats_get_names(PORT_ID(sdev), NULL, 0);
976 [ # # ]: 0 : if (ret < 0)
977 : 0 : return ret;
978 : 0 : count += ret;
979 : : }
980 : :
981 : : return count;
982 : : }
983 : :
984 : : static int
985 : 0 : __fs_xstats_get_names(struct rte_eth_dev *dev,
986 : : struct rte_eth_xstat_name *xstats_names,
987 : : unsigned int limit)
988 : : {
989 : : struct sub_device *sdev;
990 : : unsigned int count = 0;
991 : : uint8_t i;
992 : :
993 : : /* Caller only cares about count */
994 [ # # ]: 0 : if (!xstats_names)
995 : 0 : return __fs_xstats_count(dev);
996 : :
997 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
998 : 0 : struct rte_eth_xstat_name *sub_names = xstats_names + count;
999 : : int j, r;
1000 : :
1001 [ # # ]: 0 : if (count >= limit)
1002 : : break;
1003 : :
1004 : 0 : r = rte_eth_xstats_get_names(PORT_ID(sdev),
1005 : : sub_names, limit - count);
1006 [ # # ]: 0 : if (r < 0)
1007 : 0 : return r;
1008 : :
1009 : : /* add subN_ prefix to names */
1010 [ # # ]: 0 : for (j = 0; j < r; j++) {
1011 : 0 : char *xname = sub_names[j].name;
1012 : : char tmp[RTE_ETH_XSTATS_NAME_SIZE];
1013 : :
1014 [ # # ]: 0 : if ((xname[0] == 't' || xname[0] == 'r') &&
1015 [ # # # # ]: 0 : xname[1] == 'x' && xname[2] == '_')
1016 : 0 : snprintf(tmp, sizeof(tmp), "%.3ssub%u_%s",
1017 : : xname, i, xname + 3);
1018 : : else
1019 : 0 : snprintf(tmp, sizeof(tmp), "sub%u_%s",
1020 : : i, xname);
1021 : :
1022 : : strlcpy(xname, tmp, RTE_ETH_XSTATS_NAME_SIZE);
1023 : : }
1024 : 0 : count += r;
1025 : : }
1026 : 0 : return count;
1027 : : }
1028 : :
1029 : : static int
1030 : 0 : fs_xstats_get_names(struct rte_eth_dev *dev,
1031 : : struct rte_eth_xstat_name *xstats_names,
1032 : : unsigned int limit)
1033 : : {
1034 : : int ret;
1035 : :
1036 : 0 : ret = fs_lock(dev, 0);
1037 [ # # ]: 0 : if (ret != 0)
1038 : : return ret;
1039 : 0 : ret = __fs_xstats_get_names(dev, xstats_names, limit);
1040 : 0 : fs_unlock(dev, 0);
1041 : 0 : return ret;
1042 : : }
1043 : :
1044 : : static int
1045 : 0 : __fs_xstats_get(struct rte_eth_dev *dev,
1046 : : struct rte_eth_xstat *xstats,
1047 : : unsigned int n)
1048 : : {
1049 : : unsigned int count = 0;
1050 : : struct sub_device *sdev;
1051 : : uint8_t i;
1052 : : int j, ret;
1053 : :
1054 : 0 : ret = __fs_xstats_count(dev);
1055 : : /*
1056 : : * if error
1057 : : * or caller did not give enough space
1058 : : * or just querying
1059 : : */
1060 [ # # # # ]: 0 : if (ret < 0 || ret > (int)n || xstats == NULL)
1061 : : return ret;
1062 : :
1063 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1064 : 0 : ret = rte_eth_xstats_get(PORT_ID(sdev), xstats, n);
1065 [ # # ]: 0 : if (ret < 0)
1066 : 0 : return ret;
1067 : :
1068 [ # # ]: 0 : if (ret > (int)n)
1069 : 0 : return n + count;
1070 : :
1071 : : /* add offset to id's from sub-device */
1072 [ # # ]: 0 : for (j = 0; j < ret; j++)
1073 : 0 : xstats[j].id += count;
1074 : :
1075 : 0 : xstats += ret;
1076 : 0 : n -= ret;
1077 : 0 : count += ret;
1078 : : }
1079 : :
1080 : 0 : return count;
1081 : : }
1082 : :
1083 : : static int
1084 : 0 : fs_xstats_get(struct rte_eth_dev *dev,
1085 : : struct rte_eth_xstat *xstats,
1086 : : unsigned int n)
1087 : : {
1088 : : int ret;
1089 : :
1090 : 0 : ret = fs_lock(dev, 0);
1091 [ # # ]: 0 : if (ret != 0)
1092 : : return ret;
1093 : 0 : ret = __fs_xstats_get(dev, xstats, n);
1094 : 0 : fs_unlock(dev, 0);
1095 : :
1096 : 0 : return ret;
1097 : : }
1098 : :
1099 : :
1100 : : static int
1101 : 0 : fs_xstats_reset(struct rte_eth_dev *dev)
1102 : : {
1103 : : struct sub_device *sdev;
1104 : : uint8_t i;
1105 : : int r;
1106 : :
1107 : 0 : r = fs_lock(dev, 0);
1108 [ # # ]: 0 : if (r != 0)
1109 : : return r;
1110 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1111 : 0 : r = rte_eth_xstats_reset(PORT_ID(sdev));
1112 [ # # ]: 0 : if (r < 0)
1113 : : break;
1114 : : }
1115 : 0 : fs_unlock(dev, 0);
1116 : :
1117 : 0 : return r;
1118 : : }
1119 : :
1120 : : static void
1121 : : fs_dev_merge_desc_lim(struct rte_eth_desc_lim *to,
1122 : : const struct rte_eth_desc_lim *from)
1123 : : {
1124 : 0 : to->nb_max = RTE_MIN(to->nb_max, from->nb_max);
1125 : 0 : to->nb_min = RTE_MAX(to->nb_min, from->nb_min);
1126 : 0 : to->nb_align = RTE_MAX(to->nb_align, from->nb_align);
1127 : :
1128 : 0 : to->nb_seg_max = RTE_MIN(to->nb_seg_max, from->nb_seg_max);
1129 : 0 : to->nb_mtu_seg_max = RTE_MIN(to->nb_mtu_seg_max, from->nb_mtu_seg_max);
1130 : : }
1131 : :
1132 : : /*
1133 : : * Merge the information from sub-devices.
1134 : : *
1135 : : * The reported values must be the common subset of all sub devices
1136 : : */
1137 : : static void
1138 : 0 : fs_dev_merge_info(struct rte_eth_dev_info *info,
1139 : : const struct rte_eth_dev_info *sinfo)
1140 : : {
1141 : 0 : info->min_mtu = RTE_MAX(info->min_mtu, sinfo->min_mtu);
1142 : 0 : info->max_mtu = RTE_MIN(info->max_mtu, sinfo->max_mtu);
1143 : 0 : info->max_rx_pktlen = RTE_MIN(info->max_rx_pktlen, sinfo->max_rx_pktlen);
1144 : 0 : info->max_rx_queues = RTE_MIN(info->max_rx_queues, sinfo->max_rx_queues);
1145 : 0 : info->max_tx_queues = RTE_MIN(info->max_tx_queues, sinfo->max_tx_queues);
1146 : 0 : info->max_mac_addrs = RTE_MIN(info->max_mac_addrs, sinfo->max_mac_addrs);
1147 : 0 : info->max_hash_mac_addrs = RTE_MIN(info->max_hash_mac_addrs,
1148 : : sinfo->max_hash_mac_addrs);
1149 : 0 : info->max_vmdq_pools = RTE_MIN(info->max_vmdq_pools, sinfo->max_vmdq_pools);
1150 : 0 : info->max_vfs = RTE_MIN(info->max_vfs, sinfo->max_vfs);
1151 : :
1152 : : fs_dev_merge_desc_lim(&info->rx_desc_lim, &sinfo->rx_desc_lim);
1153 : : fs_dev_merge_desc_lim(&info->tx_desc_lim, &sinfo->tx_desc_lim);
1154 : :
1155 : 0 : info->rx_offload_capa &= sinfo->rx_offload_capa;
1156 : 0 : info->tx_offload_capa &= sinfo->tx_offload_capa;
1157 : 0 : info->rx_queue_offload_capa &= sinfo->rx_queue_offload_capa;
1158 : 0 : info->tx_queue_offload_capa &= sinfo->tx_queue_offload_capa;
1159 : 0 : info->flow_type_rss_offloads &= sinfo->flow_type_rss_offloads;
1160 : :
1161 : : /*
1162 : : * RETA size is a GCD of RETA sizes indicated by sub-devices.
1163 : : * Each of these sizes is a power of 2, so use the lower one.
1164 : : */
1165 : 0 : info->reta_size = RTE_MIN(info->reta_size, sinfo->reta_size);
1166 : :
1167 : 0 : info->hash_key_size = RTE_MIN(info->hash_key_size,
1168 : : sinfo->hash_key_size);
1169 : 0 : }
1170 : :
1171 : : /**
1172 : : * Fail-safe dev_infos_get rules:
1173 : : *
1174 : : * No sub_device:
1175 : : * Numerables:
1176 : : * Use the maximum possible values for any field, so as not
1177 : : * to impede any further configuration effort.
1178 : : * Capabilities:
1179 : : * Limits capabilities to those that are understood by the
1180 : : * fail-safe PMD. This understanding stems from the fail-safe
1181 : : * being capable of verifying that the related capability is
1182 : : * expressed within the device configuration (struct rte_eth_conf).
1183 : : *
1184 : : * At least one probed sub_device:
1185 : : * Numerables:
1186 : : * Uses values from the active probed sub_device
1187 : : * The rationale here is that if any sub_device is less capable
1188 : : * (for example concerning the number of queues) than the active
1189 : : * sub_device, then its subsequent configuration will fail.
1190 : : * It is impossible to foresee this failure when the failing sub_device
1191 : : * is supposed to be plugged-in later on, so the configuration process
1192 : : * is the single point of failure and error reporting.
1193 : : * Capabilities:
1194 : : * Uses a logical AND of RX capabilities among
1195 : : * all sub_devices and the default capabilities.
1196 : : * Uses a logical AND of TX capabilities among
1197 : : * the active probed sub_device and the default capabilities.
1198 : : * Uses a logical AND of device capabilities among
1199 : : * all sub_devices and the default capabilities.
1200 : : *
1201 : : */
1202 : : static int
1203 : 0 : fs_dev_infos_get(struct rte_eth_dev *dev,
1204 : : struct rte_eth_dev_info *infos)
1205 : : {
1206 : : struct sub_device *sdev;
1207 : : uint8_t i;
1208 : : int ret;
1209 : :
1210 : : /* Use maximum upper bounds by default */
1211 : 0 : infos->min_mtu = RTE_ETHER_MIN_MTU;
1212 : 0 : infos->max_mtu = UINT16_MAX;
1213 : 0 : infos->max_rx_pktlen = UINT32_MAX;
1214 : 0 : infos->max_rx_queues = RTE_MAX_QUEUES_PER_PORT;
1215 : 0 : infos->max_tx_queues = RTE_MAX_QUEUES_PER_PORT;
1216 : 0 : infos->max_mac_addrs = FAILSAFE_MAX_ETHADDR;
1217 : 0 : infos->max_hash_mac_addrs = UINT32_MAX;
1218 : 0 : infos->max_vfs = UINT16_MAX;
1219 : 0 : infos->max_vmdq_pools = UINT16_MAX;
1220 : 0 : infos->reta_size = UINT16_MAX;
1221 : 0 : infos->hash_key_size = UINT8_MAX;
1222 : :
1223 : : /*
1224 : : * Set of capabilities that can be verified upon
1225 : : * configuring a sub-device.
1226 : : */
1227 : 0 : infos->rx_offload_capa =
1228 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
1229 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
1230 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
1231 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
1232 : : RTE_ETH_RX_OFFLOAD_TCP_LRO |
1233 : : RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
1234 : : RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
1235 : : RTE_ETH_RX_OFFLOAD_MACSEC_STRIP |
1236 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
1237 : : RTE_ETH_RX_OFFLOAD_VLAN_EXTEND |
1238 : : RTE_ETH_RX_OFFLOAD_SCATTER |
1239 : : RTE_ETH_RX_OFFLOAD_TIMESTAMP |
1240 : : RTE_ETH_RX_OFFLOAD_SECURITY |
1241 : : RTE_ETH_RX_OFFLOAD_RSS_HASH;
1242 : :
1243 : 0 : infos->rx_queue_offload_capa =
1244 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
1245 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
1246 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
1247 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
1248 : : RTE_ETH_RX_OFFLOAD_TCP_LRO |
1249 : : RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
1250 : : RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
1251 : : RTE_ETH_RX_OFFLOAD_MACSEC_STRIP |
1252 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
1253 : : RTE_ETH_RX_OFFLOAD_VLAN_EXTEND |
1254 : : RTE_ETH_RX_OFFLOAD_SCATTER |
1255 : : RTE_ETH_RX_OFFLOAD_TIMESTAMP |
1256 : : RTE_ETH_RX_OFFLOAD_SECURITY |
1257 : : RTE_ETH_RX_OFFLOAD_RSS_HASH;
1258 : :
1259 : 0 : infos->tx_offload_capa =
1260 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
1261 : : RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
1262 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
1263 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
1264 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
1265 : : RTE_ETH_TX_OFFLOAD_TCP_TSO;
1266 : :
1267 : 0 : infos->flow_type_rss_offloads =
1268 : : RTE_ETH_RSS_IP |
1269 : : RTE_ETH_RSS_UDP |
1270 : : RTE_ETH_RSS_TCP;
1271 : 0 : infos->dev_capa =
1272 : : RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
1273 : : RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
1274 : : infos->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
1275 : :
1276 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
1277 : : struct rte_eth_dev_info sub_info;
1278 : :
1279 : 0 : ret = rte_eth_dev_info_get(PORT_ID(sdev), &sub_info);
1280 : : ret = fs_err(sdev, ret);
1281 [ # # ]: 0 : if (ret != 0)
1282 : 0 : return ret;
1283 : :
1284 : 0 : fs_dev_merge_info(infos, &sub_info);
1285 : : }
1286 : :
1287 : : return 0;
1288 : : }
1289 : :
1290 : : static const uint32_t *
1291 : 0 : fs_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
1292 : : {
1293 : : struct sub_device *sdev;
1294 : : struct rte_eth_dev *edev;
1295 : : const uint32_t *ret;
1296 : :
1297 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
1298 : : return NULL;
1299 [ # # # # ]: 0 : sdev = TX_SUBDEV(dev);
1300 : : if (sdev == NULL) {
1301 : : ret = NULL;
1302 : 0 : goto unlock;
1303 : : }
1304 [ # # ]: 0 : edev = ETH(sdev);
1305 : : /* ENOTSUP: counts as no supported ptypes */
1306 [ # # ]: 0 : if (SUBOPS(sdev, dev_supported_ptypes_get) == NULL) {
1307 : : ret = NULL;
1308 : 0 : goto unlock;
1309 : : }
1310 : : /*
1311 : : * The API does not permit to do a clean AND of all ptypes,
1312 : : * It is also incomplete by design and we do not really care
1313 : : * to have a best possible value in this context.
1314 : : * We just return the ptypes of the device of highest
1315 : : * priority, usually the PREFERRED device.
1316 : : */
1317 : 0 : ret = SUBOPS(sdev, dev_supported_ptypes_get)(edev, no_of_elements);
1318 : 0 : unlock:
1319 : 0 : fs_unlock(dev, 0);
1320 : 0 : return ret;
1321 : : }
1322 : :
1323 : : static int
1324 : 0 : fs_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
1325 : : {
1326 : : struct sub_device *sdev;
1327 : : uint8_t i;
1328 : : int ret;
1329 : :
1330 : 0 : ret = fs_lock(dev, 0);
1331 [ # # ]: 0 : if (ret != 0)
1332 : : return ret;
1333 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1334 : 0 : DEBUG("Calling rte_eth_dev_set_mtu on sub_device %d", i);
1335 : 0 : ret = rte_eth_dev_set_mtu(PORT_ID(sdev), mtu);
1336 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1337 : 0 : ERROR("Operation rte_eth_dev_set_mtu failed for sub_device %d with error %d",
1338 : : i, ret);
1339 : 0 : fs_unlock(dev, 0);
1340 : 0 : return ret;
1341 : : }
1342 : : }
1343 : 0 : fs_unlock(dev, 0);
1344 : 0 : return 0;
1345 : : }
1346 : :
1347 : : static int
1348 : 0 : fs_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
1349 : : {
1350 : : struct sub_device *sdev;
1351 : : uint8_t i;
1352 : : int ret;
1353 : :
1354 : 0 : ret = fs_lock(dev, 0);
1355 [ # # ]: 0 : if (ret != 0)
1356 : : return ret;
1357 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1358 : 0 : DEBUG("Calling rte_eth_dev_vlan_filter on sub_device %d", i);
1359 : 0 : ret = rte_eth_dev_vlan_filter(PORT_ID(sdev), vlan_id, on);
1360 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1361 : 0 : ERROR("Operation rte_eth_dev_vlan_filter failed for sub_device %d"
1362 : : " with error %d", i, ret);
1363 : 0 : fs_unlock(dev, 0);
1364 : 0 : return ret;
1365 : : }
1366 : : }
1367 : 0 : fs_unlock(dev, 0);
1368 : 0 : return 0;
1369 : : }
1370 : :
1371 : : static int
1372 : 0 : fs_flow_ctrl_get(struct rte_eth_dev *dev,
1373 : : struct rte_eth_fc_conf *fc_conf)
1374 : : {
1375 : : struct sub_device *sdev;
1376 : : int ret;
1377 : :
1378 : 0 : ret = fs_lock(dev, 0);
1379 [ # # ]: 0 : if (ret != 0)
1380 : : return ret;
1381 [ # # # # ]: 0 : sdev = TX_SUBDEV(dev);
1382 : : if (sdev == NULL) {
1383 : : ret = 0;
1384 : 0 : goto unlock;
1385 : : }
1386 [ # # # # ]: 0 : if (SUBOPS(sdev, flow_ctrl_get) == NULL) {
1387 : : ret = -ENOTSUP;
1388 : 0 : goto unlock;
1389 : : }
1390 : 0 : ret = SUBOPS(sdev, flow_ctrl_get)(ETH(sdev), fc_conf);
1391 : 0 : unlock:
1392 : 0 : fs_unlock(dev, 0);
1393 : 0 : return ret;
1394 : : }
1395 : :
1396 : : static int
1397 : 0 : fs_flow_ctrl_set(struct rte_eth_dev *dev,
1398 : : struct rte_eth_fc_conf *fc_conf)
1399 : : {
1400 : : struct sub_device *sdev;
1401 : : uint8_t i;
1402 : : int ret;
1403 : :
1404 : 0 : ret = fs_lock(dev, 0);
1405 [ # # ]: 0 : if (ret != 0)
1406 : : return ret;
1407 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1408 : 0 : DEBUG("Calling rte_eth_dev_flow_ctrl_set on sub_device %d", i);
1409 : 0 : ret = rte_eth_dev_flow_ctrl_set(PORT_ID(sdev), fc_conf);
1410 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1411 : 0 : ERROR("Operation rte_eth_dev_flow_ctrl_set failed for sub_device %d"
1412 : : " with error %d", i, ret);
1413 : 0 : fs_unlock(dev, 0);
1414 : 0 : return ret;
1415 : : }
1416 : : }
1417 : 0 : fs_unlock(dev, 0);
1418 : 0 : return 0;
1419 : : }
1420 : :
1421 : : static void
1422 : 0 : fs_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
1423 : : {
1424 : : struct sub_device *sdev;
1425 : : uint8_t i;
1426 : :
1427 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
1428 : : return;
1429 : : /* No check: already done within the rte_eth_dev_mac_addr_remove
1430 : : * call for the fail-safe device.
1431 : : */
1432 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)
1433 : 0 : rte_eth_dev_mac_addr_remove(PORT_ID(sdev),
1434 : 0 : &dev->data->mac_addrs[index]);
1435 : 0 : PRIV(dev)->mac_addr_pool[index] = 0;
1436 : 0 : fs_unlock(dev, 0);
1437 : : }
1438 : :
1439 : : static int
1440 : 0 : fs_mac_addr_add(struct rte_eth_dev *dev,
1441 : : struct rte_ether_addr *mac_addr,
1442 : : uint32_t index,
1443 : : uint32_t vmdq)
1444 : : {
1445 : : struct sub_device *sdev;
1446 : : int ret;
1447 : : uint8_t i;
1448 : :
1449 : : RTE_ASSERT(index < FAILSAFE_MAX_ETHADDR);
1450 : 0 : ret = fs_lock(dev, 0);
1451 [ # # ]: 0 : if (ret != 0)
1452 : : return ret;
1453 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1454 : 0 : ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), mac_addr, vmdq);
1455 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1456 : 0 : ERROR("Operation rte_eth_dev_mac_addr_add failed for sub_device %"
1457 : : PRIu8 " with error %d", i, ret);
1458 : 0 : fs_unlock(dev, 0);
1459 : 0 : return ret;
1460 : : }
1461 : : }
1462 [ # # ]: 0 : if (index >= PRIV(dev)->nb_mac_addr) {
1463 : 0 : DEBUG("Growing mac_addrs array");
1464 : 0 : PRIV(dev)->nb_mac_addr = index;
1465 : : }
1466 : 0 : PRIV(dev)->mac_addr_pool[index] = vmdq;
1467 : 0 : fs_unlock(dev, 0);
1468 : 0 : return 0;
1469 : : }
1470 : :
1471 : : static int
1472 : 0 : fs_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
1473 : : {
1474 : : struct sub_device *sdev;
1475 : : uint8_t i;
1476 : : int ret;
1477 : :
1478 : 0 : ret = fs_lock(dev, 0);
1479 [ # # ]: 0 : if (ret != 0)
1480 : : return ret;
1481 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1482 : 0 : ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), mac_addr);
1483 : : ret = fs_err(sdev, ret);
1484 [ # # ]: 0 : if (ret) {
1485 : 0 : ERROR("Operation rte_eth_dev_mac_addr_set failed for sub_device %d with error %d",
1486 : : i, ret);
1487 : 0 : fs_unlock(dev, 0);
1488 : 0 : return ret;
1489 : : }
1490 : : }
1491 : 0 : fs_unlock(dev, 0);
1492 : :
1493 : 0 : return 0;
1494 : : }
1495 : :
1496 : : static int
1497 : 0 : fs_set_mc_addr_list(struct rte_eth_dev *dev,
1498 : : struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr)
1499 : : {
1500 : : struct sub_device *sdev;
1501 : : uint8_t i;
1502 : : int ret;
1503 : : void *mcast_addrs;
1504 : :
1505 : 0 : ret = fs_lock(dev, 0);
1506 [ # # ]: 0 : if (ret != 0)
1507 : : return ret;
1508 : :
1509 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1510 : 0 : ret = rte_eth_dev_set_mc_addr_list(PORT_ID(sdev),
1511 : : mc_addr_set, nb_mc_addr);
1512 [ # # ]: 0 : if (ret != 0) {
1513 : 0 : ERROR("Operation rte_eth_dev_set_mc_addr_list failed for sub_device %d with error %d",
1514 : : i, ret);
1515 : 0 : goto rollback;
1516 : : }
1517 : : }
1518 : :
1519 : 0 : mcast_addrs = rte_realloc(PRIV(dev)->mcast_addrs,
1520 : : nb_mc_addr * sizeof(PRIV(dev)->mcast_addrs[0]), 0);
1521 [ # # ]: 0 : if (mcast_addrs == NULL && nb_mc_addr > 0) {
1522 : : ret = -ENOMEM;
1523 : 0 : goto rollback;
1524 : : }
1525 : : rte_memcpy(mcast_addrs, mc_addr_set,
1526 : : nb_mc_addr * sizeof(PRIV(dev)->mcast_addrs[0]));
1527 : 0 : PRIV(dev)->nb_mcast_addr = nb_mc_addr;
1528 : 0 : PRIV(dev)->mcast_addrs = mcast_addrs;
1529 : :
1530 : 0 : fs_unlock(dev, 0);
1531 : 0 : return 0;
1532 : :
1533 : 0 : rollback:
1534 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1535 : 0 : int rc = rte_eth_dev_set_mc_addr_list(PORT_ID(sdev),
1536 : 0 : PRIV(dev)->mcast_addrs, PRIV(dev)->nb_mcast_addr);
1537 [ # # ]: 0 : if (rc != 0) {
1538 : 0 : ERROR("Multicast MAC address list rollback for sub_device %d failed with error %d",
1539 : : i, rc);
1540 : : }
1541 : : }
1542 : :
1543 : 0 : fs_unlock(dev, 0);
1544 : 0 : return ret;
1545 : : }
1546 : :
1547 : : static int
1548 : 0 : fs_rss_hash_update(struct rte_eth_dev *dev,
1549 : : struct rte_eth_rss_conf *rss_conf)
1550 : : {
1551 : : struct sub_device *sdev;
1552 : : uint8_t i;
1553 : : int ret;
1554 : :
1555 : 0 : ret = fs_lock(dev, 0);
1556 [ # # ]: 0 : if (ret != 0)
1557 : : return ret;
1558 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1559 : 0 : ret = rte_eth_dev_rss_hash_update(PORT_ID(sdev), rss_conf);
1560 : : ret = fs_err(sdev, ret);
1561 [ # # ]: 0 : if (ret) {
1562 : 0 : ERROR("Operation rte_eth_dev_rss_hash_update"
1563 : : " failed for sub_device %d with error %d",
1564 : : i, ret);
1565 : 0 : fs_unlock(dev, 0);
1566 : 0 : return ret;
1567 : : }
1568 : : }
1569 : 0 : fs_unlock(dev, 0);
1570 : :
1571 : 0 : return 0;
1572 : : }
1573 : :
1574 : : static int
1575 : 0 : fs_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
1576 : : const struct rte_flow_ops **ops)
1577 : : {
1578 : 0 : *ops = &fs_flow_ops;
1579 : 0 : return 0;
1580 : : }
1581 : :
1582 : : const struct eth_dev_ops failsafe_ops = {
1583 : : .dev_configure = fs_dev_configure,
1584 : : .dev_start = fs_dev_start,
1585 : : .dev_stop = fs_dev_stop,
1586 : : .dev_set_link_down = fs_dev_set_link_down,
1587 : : .dev_set_link_up = fs_dev_set_link_up,
1588 : : .dev_close = failsafe_eth_dev_close,
1589 : : .promiscuous_enable = fs_promiscuous_enable,
1590 : : .promiscuous_disable = fs_promiscuous_disable,
1591 : : .allmulticast_enable = fs_allmulticast_enable,
1592 : : .allmulticast_disable = fs_allmulticast_disable,
1593 : : .link_update = fs_link_update,
1594 : : .stats_get = fs_stats_get,
1595 : : .stats_reset = fs_stats_reset,
1596 : : .xstats_get = fs_xstats_get,
1597 : : .xstats_get_names = fs_xstats_get_names,
1598 : : .xstats_reset = fs_xstats_reset,
1599 : : .dev_infos_get = fs_dev_infos_get,
1600 : : .dev_supported_ptypes_get = fs_dev_supported_ptypes_get,
1601 : : .mtu_set = fs_mtu_set,
1602 : : .vlan_filter_set = fs_vlan_filter_set,
1603 : : .rx_queue_start = fs_rx_queue_start,
1604 : : .rx_queue_stop = fs_rx_queue_stop,
1605 : : .tx_queue_start = fs_tx_queue_start,
1606 : : .tx_queue_stop = fs_tx_queue_stop,
1607 : : .rx_queue_setup = fs_rx_queue_setup,
1608 : : .tx_queue_setup = fs_tx_queue_setup,
1609 : : .rx_queue_release = fs_rx_queue_release,
1610 : : .tx_queue_release = fs_tx_queue_release,
1611 : : .rx_queue_intr_enable = fs_rx_intr_enable,
1612 : : .rx_queue_intr_disable = fs_rx_intr_disable,
1613 : : .flow_ctrl_get = fs_flow_ctrl_get,
1614 : : .flow_ctrl_set = fs_flow_ctrl_set,
1615 : : .mac_addr_remove = fs_mac_addr_remove,
1616 : : .mac_addr_add = fs_mac_addr_add,
1617 : : .mac_addr_set = fs_mac_addr_set,
1618 : : .set_mc_addr_list = fs_set_mc_addr_list,
1619 : : .rss_hash_update = fs_rss_hash_update,
1620 : : .flow_ops_get = fs_flow_ops_get,
1621 : : };
|