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 : : struct eth_queue_stats *qstats __rte_unused)
903 : : {
904 : : struct rte_eth_stats backup;
905 : : struct sub_device *sdev;
906 : : uint8_t i;
907 : : int ret;
908 : :
909 : 0 : ret = fs_lock(dev, 0);
910 [ # # ]: 0 : if (ret != 0)
911 : : return ret;
912 [ # # ]: 0 : rte_memcpy(stats, &PRIV(dev)->stats_accumulator, sizeof(*stats));
913 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
914 [ # # ]: 0 : struct rte_eth_stats *snapshot = &sdev->stats_snapshot.stats;
915 : : uint64_t *timestamp = &sdev->stats_snapshot.timestamp;
916 : :
917 : : rte_memcpy(&backup, snapshot, sizeof(backup));
918 : 0 : ret = rte_eth_stats_get(PORT_ID(sdev), snapshot);
919 [ # # ]: 0 : if (ret) {
920 : : if (!fs_err(sdev, ret)) {
921 : : rte_memcpy(snapshot, &backup, sizeof(backup));
922 : 0 : goto inc;
923 : : }
924 : 0 : ERROR("Operation rte_eth_stats_get failed for sub_device %d with error %d",
925 : : i, ret);
926 : 0 : *timestamp = 0;
927 : 0 : fs_unlock(dev, 0);
928 : 0 : return ret;
929 : : }
930 : 0 : *timestamp = rte_rdtsc();
931 : 0 : inc:
932 : 0 : failsafe_stats_increment(stats, snapshot);
933 : : }
934 : 0 : fs_unlock(dev, 0);
935 : 0 : return 0;
936 : : }
937 : :
938 : : static int
939 : 0 : fs_stats_reset(struct rte_eth_dev *dev)
940 : : {
941 : : struct sub_device *sdev;
942 : : uint8_t i;
943 : : int ret;
944 : :
945 : 0 : ret = fs_lock(dev, 0);
946 [ # # ]: 0 : if (ret != 0)
947 : : return ret;
948 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
949 : 0 : ret = rte_eth_stats_reset(PORT_ID(sdev));
950 [ # # ]: 0 : if (ret) {
951 : 0 : if (!fs_err(sdev, ret))
952 : 0 : continue;
953 : :
954 : 0 : ERROR("Operation rte_eth_stats_reset failed for sub_device %d with error %d",
955 : : i, ret);
956 : 0 : fs_unlock(dev, 0);
957 : 0 : return ret;
958 : : }
959 : 0 : memset(&sdev->stats_snapshot, 0, sizeof(struct rte_eth_stats));
960 : : }
961 : 0 : memset(&PRIV(dev)->stats_accumulator, 0, sizeof(struct rte_eth_stats));
962 : 0 : fs_unlock(dev, 0);
963 : :
964 : 0 : return 0;
965 : : }
966 : :
967 : : static int
968 : 0 : __fs_xstats_count(struct rte_eth_dev *dev)
969 : : {
970 : : struct sub_device *sdev;
971 : : int count = 0;
972 : : uint8_t i;
973 : : int ret;
974 : :
975 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
976 : 0 : ret = rte_eth_xstats_get_names(PORT_ID(sdev), NULL, 0);
977 [ # # ]: 0 : if (ret < 0)
978 : 0 : return ret;
979 : 0 : count += ret;
980 : : }
981 : :
982 : : return count;
983 : : }
984 : :
985 : : static int
986 : 0 : __fs_xstats_get_names(struct rte_eth_dev *dev,
987 : : struct rte_eth_xstat_name *xstats_names,
988 : : unsigned int limit)
989 : : {
990 : : struct sub_device *sdev;
991 : : unsigned int count = 0;
992 : : uint8_t i;
993 : :
994 : : /* Caller only cares about count */
995 [ # # ]: 0 : if (!xstats_names)
996 : 0 : return __fs_xstats_count(dev);
997 : :
998 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
999 : 0 : struct rte_eth_xstat_name *sub_names = xstats_names + count;
1000 : : int j, r;
1001 : :
1002 [ # # ]: 0 : if (count >= limit)
1003 : : break;
1004 : :
1005 : 0 : r = rte_eth_xstats_get_names(PORT_ID(sdev),
1006 : : sub_names, limit - count);
1007 [ # # ]: 0 : if (r < 0)
1008 : 0 : return r;
1009 : :
1010 : : /* add subN_ prefix to names */
1011 [ # # ]: 0 : for (j = 0; j < r; j++) {
1012 : 0 : char *xname = sub_names[j].name;
1013 : : char tmp[RTE_ETH_XSTATS_NAME_SIZE];
1014 : :
1015 [ # # ]: 0 : if ((xname[0] == 't' || xname[0] == 'r') &&
1016 [ # # # # ]: 0 : xname[1] == 'x' && xname[2] == '_')
1017 : 0 : snprintf(tmp, sizeof(tmp), "%.3ssub%u_%s",
1018 : : xname, i, xname + 3);
1019 : : else
1020 : 0 : snprintf(tmp, sizeof(tmp), "sub%u_%s",
1021 : : i, xname);
1022 : :
1023 : : strlcpy(xname, tmp, RTE_ETH_XSTATS_NAME_SIZE);
1024 : : }
1025 : 0 : count += r;
1026 : : }
1027 : 0 : return count;
1028 : : }
1029 : :
1030 : : static int
1031 : 0 : fs_xstats_get_names(struct rte_eth_dev *dev,
1032 : : struct rte_eth_xstat_name *xstats_names,
1033 : : unsigned int limit)
1034 : : {
1035 : : int ret;
1036 : :
1037 : 0 : ret = fs_lock(dev, 0);
1038 [ # # ]: 0 : if (ret != 0)
1039 : : return ret;
1040 : 0 : ret = __fs_xstats_get_names(dev, xstats_names, limit);
1041 : 0 : fs_unlock(dev, 0);
1042 : 0 : return ret;
1043 : : }
1044 : :
1045 : : static int
1046 : 0 : __fs_xstats_get(struct rte_eth_dev *dev,
1047 : : struct rte_eth_xstat *xstats,
1048 : : unsigned int n)
1049 : : {
1050 : : unsigned int count = 0;
1051 : : struct sub_device *sdev;
1052 : : uint8_t i;
1053 : : int j, ret;
1054 : :
1055 : 0 : ret = __fs_xstats_count(dev);
1056 : : /*
1057 : : * if error
1058 : : * or caller did not give enough space
1059 : : * or just querying
1060 : : */
1061 [ # # # # ]: 0 : if (ret < 0 || ret > (int)n || xstats == NULL)
1062 : : return ret;
1063 : :
1064 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1065 : 0 : ret = rte_eth_xstats_get(PORT_ID(sdev), xstats, n);
1066 [ # # ]: 0 : if (ret < 0)
1067 : 0 : return ret;
1068 : :
1069 [ # # ]: 0 : if (ret > (int)n)
1070 : 0 : return n + count;
1071 : :
1072 : : /* add offset to id's from sub-device */
1073 [ # # ]: 0 : for (j = 0; j < ret; j++)
1074 : 0 : xstats[j].id += count;
1075 : :
1076 : 0 : xstats += ret;
1077 : 0 : n -= ret;
1078 : 0 : count += ret;
1079 : : }
1080 : :
1081 : 0 : return count;
1082 : : }
1083 : :
1084 : : static int
1085 : 0 : fs_xstats_get(struct rte_eth_dev *dev,
1086 : : struct rte_eth_xstat *xstats,
1087 : : unsigned int n)
1088 : : {
1089 : : int ret;
1090 : :
1091 : 0 : ret = fs_lock(dev, 0);
1092 [ # # ]: 0 : if (ret != 0)
1093 : : return ret;
1094 : 0 : ret = __fs_xstats_get(dev, xstats, n);
1095 : 0 : fs_unlock(dev, 0);
1096 : :
1097 : 0 : return ret;
1098 : : }
1099 : :
1100 : :
1101 : : static int
1102 : 0 : fs_xstats_reset(struct rte_eth_dev *dev)
1103 : : {
1104 : : struct sub_device *sdev;
1105 : : uint8_t i;
1106 : : int r;
1107 : :
1108 : 0 : r = fs_lock(dev, 0);
1109 [ # # ]: 0 : if (r != 0)
1110 : : return r;
1111 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1112 : 0 : r = rte_eth_xstats_reset(PORT_ID(sdev));
1113 [ # # ]: 0 : if (r < 0)
1114 : : break;
1115 : : }
1116 : 0 : fs_unlock(dev, 0);
1117 : :
1118 : 0 : return r;
1119 : : }
1120 : :
1121 : : static void
1122 : : fs_dev_merge_desc_lim(struct rte_eth_desc_lim *to,
1123 : : const struct rte_eth_desc_lim *from)
1124 : : {
1125 : 0 : to->nb_max = RTE_MIN(to->nb_max, from->nb_max);
1126 : 0 : to->nb_min = RTE_MAX(to->nb_min, from->nb_min);
1127 : 0 : to->nb_align = RTE_MAX(to->nb_align, from->nb_align);
1128 : :
1129 : 0 : to->nb_seg_max = RTE_MIN(to->nb_seg_max, from->nb_seg_max);
1130 : 0 : to->nb_mtu_seg_max = RTE_MIN(to->nb_mtu_seg_max, from->nb_mtu_seg_max);
1131 : : }
1132 : :
1133 : : /*
1134 : : * Merge the information from sub-devices.
1135 : : *
1136 : : * The reported values must be the common subset of all sub devices
1137 : : */
1138 : : static void
1139 : 0 : fs_dev_merge_info(struct rte_eth_dev_info *info,
1140 : : const struct rte_eth_dev_info *sinfo)
1141 : : {
1142 : 0 : info->min_mtu = RTE_MAX(info->min_mtu, sinfo->min_mtu);
1143 : 0 : info->max_mtu = RTE_MIN(info->max_mtu, sinfo->max_mtu);
1144 : 0 : info->max_rx_pktlen = RTE_MIN(info->max_rx_pktlen, sinfo->max_rx_pktlen);
1145 : 0 : info->max_rx_queues = RTE_MIN(info->max_rx_queues, sinfo->max_rx_queues);
1146 : 0 : info->max_tx_queues = RTE_MIN(info->max_tx_queues, sinfo->max_tx_queues);
1147 : 0 : info->max_mac_addrs = RTE_MIN(info->max_mac_addrs, sinfo->max_mac_addrs);
1148 : 0 : info->max_hash_mac_addrs = RTE_MIN(info->max_hash_mac_addrs,
1149 : : sinfo->max_hash_mac_addrs);
1150 : 0 : info->max_vmdq_pools = RTE_MIN(info->max_vmdq_pools, sinfo->max_vmdq_pools);
1151 : 0 : info->max_vfs = RTE_MIN(info->max_vfs, sinfo->max_vfs);
1152 : :
1153 : : fs_dev_merge_desc_lim(&info->rx_desc_lim, &sinfo->rx_desc_lim);
1154 : : fs_dev_merge_desc_lim(&info->tx_desc_lim, &sinfo->tx_desc_lim);
1155 : :
1156 : 0 : info->rx_offload_capa &= sinfo->rx_offload_capa;
1157 : 0 : info->tx_offload_capa &= sinfo->tx_offload_capa;
1158 : 0 : info->rx_queue_offload_capa &= sinfo->rx_queue_offload_capa;
1159 : 0 : info->tx_queue_offload_capa &= sinfo->tx_queue_offload_capa;
1160 : 0 : info->flow_type_rss_offloads &= sinfo->flow_type_rss_offloads;
1161 : :
1162 : : /*
1163 : : * RETA size is a GCD of RETA sizes indicated by sub-devices.
1164 : : * Each of these sizes is a power of 2, so use the lower one.
1165 : : */
1166 : 0 : info->reta_size = RTE_MIN(info->reta_size, sinfo->reta_size);
1167 : :
1168 : 0 : info->hash_key_size = RTE_MIN(info->hash_key_size,
1169 : : sinfo->hash_key_size);
1170 : 0 : }
1171 : :
1172 : : /**
1173 : : * Fail-safe dev_infos_get rules:
1174 : : *
1175 : : * No sub_device:
1176 : : * Numerables:
1177 : : * Use the maximum possible values for any field, so as not
1178 : : * to impede any further configuration effort.
1179 : : * Capabilities:
1180 : : * Limits capabilities to those that are understood by the
1181 : : * fail-safe PMD. This understanding stems from the fail-safe
1182 : : * being capable of verifying that the related capability is
1183 : : * expressed within the device configuration (struct rte_eth_conf).
1184 : : *
1185 : : * At least one probed sub_device:
1186 : : * Numerables:
1187 : : * Uses values from the active probed sub_device
1188 : : * The rationale here is that if any sub_device is less capable
1189 : : * (for example concerning the number of queues) than the active
1190 : : * sub_device, then its subsequent configuration will fail.
1191 : : * It is impossible to foresee this failure when the failing sub_device
1192 : : * is supposed to be plugged-in later on, so the configuration process
1193 : : * is the single point of failure and error reporting.
1194 : : * Capabilities:
1195 : : * Uses a logical AND of RX capabilities among
1196 : : * all sub_devices and the default capabilities.
1197 : : * Uses a logical AND of TX capabilities among
1198 : : * the active probed sub_device and the default capabilities.
1199 : : * Uses a logical AND of device capabilities among
1200 : : * all sub_devices and the default capabilities.
1201 : : *
1202 : : */
1203 : : static int
1204 : 0 : fs_dev_infos_get(struct rte_eth_dev *dev,
1205 : : struct rte_eth_dev_info *infos)
1206 : : {
1207 : : struct sub_device *sdev;
1208 : : uint8_t i;
1209 : : int ret;
1210 : :
1211 : : /* Use maximum upper bounds by default */
1212 : 0 : infos->min_mtu = RTE_ETHER_MIN_MTU;
1213 : 0 : infos->max_mtu = UINT16_MAX;
1214 : 0 : infos->max_rx_pktlen = UINT32_MAX;
1215 : 0 : infos->max_rx_queues = RTE_MAX_QUEUES_PER_PORT;
1216 : 0 : infos->max_tx_queues = RTE_MAX_QUEUES_PER_PORT;
1217 : 0 : infos->max_mac_addrs = FAILSAFE_MAX_ETHADDR;
1218 : 0 : infos->max_hash_mac_addrs = UINT32_MAX;
1219 : 0 : infos->max_vfs = UINT16_MAX;
1220 : 0 : infos->max_vmdq_pools = UINT16_MAX;
1221 : 0 : infos->reta_size = UINT16_MAX;
1222 : 0 : infos->hash_key_size = UINT8_MAX;
1223 : :
1224 : : /*
1225 : : * Set of capabilities that can be verified upon
1226 : : * configuring a sub-device.
1227 : : */
1228 : 0 : infos->rx_offload_capa =
1229 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
1230 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
1231 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
1232 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
1233 : : RTE_ETH_RX_OFFLOAD_TCP_LRO |
1234 : : RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
1235 : : RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
1236 : : RTE_ETH_RX_OFFLOAD_MACSEC_STRIP |
1237 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
1238 : : RTE_ETH_RX_OFFLOAD_VLAN_EXTEND |
1239 : : RTE_ETH_RX_OFFLOAD_SCATTER |
1240 : : RTE_ETH_RX_OFFLOAD_TIMESTAMP |
1241 : : RTE_ETH_RX_OFFLOAD_SECURITY |
1242 : : RTE_ETH_RX_OFFLOAD_RSS_HASH;
1243 : :
1244 : 0 : infos->rx_queue_offload_capa =
1245 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
1246 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
1247 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
1248 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
1249 : : RTE_ETH_RX_OFFLOAD_TCP_LRO |
1250 : : RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
1251 : : RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
1252 : : RTE_ETH_RX_OFFLOAD_MACSEC_STRIP |
1253 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
1254 : : RTE_ETH_RX_OFFLOAD_VLAN_EXTEND |
1255 : : RTE_ETH_RX_OFFLOAD_SCATTER |
1256 : : RTE_ETH_RX_OFFLOAD_TIMESTAMP |
1257 : : RTE_ETH_RX_OFFLOAD_SECURITY |
1258 : : RTE_ETH_RX_OFFLOAD_RSS_HASH;
1259 : :
1260 : 0 : infos->tx_offload_capa =
1261 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
1262 : : RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
1263 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
1264 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
1265 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
1266 : : RTE_ETH_TX_OFFLOAD_TCP_TSO;
1267 : :
1268 : 0 : infos->flow_type_rss_offloads =
1269 : : RTE_ETH_RSS_IP |
1270 : : RTE_ETH_RSS_UDP |
1271 : : RTE_ETH_RSS_TCP;
1272 : 0 : infos->dev_capa =
1273 : : RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
1274 : : RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
1275 : : infos->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
1276 : :
1277 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
1278 : : struct rte_eth_dev_info sub_info;
1279 : :
1280 : 0 : ret = rte_eth_dev_info_get(PORT_ID(sdev), &sub_info);
1281 : : ret = fs_err(sdev, ret);
1282 [ # # ]: 0 : if (ret != 0)
1283 : 0 : return ret;
1284 : :
1285 : 0 : fs_dev_merge_info(infos, &sub_info);
1286 : : }
1287 : :
1288 : : return 0;
1289 : : }
1290 : :
1291 : : static const uint32_t *
1292 : 0 : fs_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
1293 : : {
1294 : : struct sub_device *sdev;
1295 : : struct rte_eth_dev *edev;
1296 : : const uint32_t *ret;
1297 : :
1298 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
1299 : : return NULL;
1300 [ # # # # ]: 0 : sdev = TX_SUBDEV(dev);
1301 : : if (sdev == NULL) {
1302 : : ret = NULL;
1303 : 0 : goto unlock;
1304 : : }
1305 [ # # ]: 0 : edev = ETH(sdev);
1306 : : /* ENOTSUP: counts as no supported ptypes */
1307 [ # # ]: 0 : if (SUBOPS(sdev, dev_supported_ptypes_get) == NULL) {
1308 : : ret = NULL;
1309 : 0 : goto unlock;
1310 : : }
1311 : : /*
1312 : : * The API does not permit to do a clean AND of all ptypes,
1313 : : * It is also incomplete by design and we do not really care
1314 : : * to have a best possible value in this context.
1315 : : * We just return the ptypes of the device of highest
1316 : : * priority, usually the PREFERRED device.
1317 : : */
1318 : 0 : ret = SUBOPS(sdev, dev_supported_ptypes_get)(edev, no_of_elements);
1319 : 0 : unlock:
1320 : 0 : fs_unlock(dev, 0);
1321 : 0 : return ret;
1322 : : }
1323 : :
1324 : : static int
1325 : 0 : fs_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
1326 : : {
1327 : : struct sub_device *sdev;
1328 : : uint8_t i;
1329 : : int ret;
1330 : :
1331 : 0 : ret = fs_lock(dev, 0);
1332 [ # # ]: 0 : if (ret != 0)
1333 : : return ret;
1334 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1335 : 0 : DEBUG("Calling rte_eth_dev_set_mtu on sub_device %d", i);
1336 : 0 : ret = rte_eth_dev_set_mtu(PORT_ID(sdev), mtu);
1337 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1338 : 0 : ERROR("Operation rte_eth_dev_set_mtu failed for sub_device %d with error %d",
1339 : : i, ret);
1340 : 0 : fs_unlock(dev, 0);
1341 : 0 : return ret;
1342 : : }
1343 : : }
1344 : 0 : fs_unlock(dev, 0);
1345 : 0 : return 0;
1346 : : }
1347 : :
1348 : : static int
1349 : 0 : fs_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
1350 : : {
1351 : : struct sub_device *sdev;
1352 : : uint8_t i;
1353 : : int ret;
1354 : :
1355 : 0 : ret = fs_lock(dev, 0);
1356 [ # # ]: 0 : if (ret != 0)
1357 : : return ret;
1358 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1359 : 0 : DEBUG("Calling rte_eth_dev_vlan_filter on sub_device %d", i);
1360 : 0 : ret = rte_eth_dev_vlan_filter(PORT_ID(sdev), vlan_id, on);
1361 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1362 : 0 : ERROR("Operation rte_eth_dev_vlan_filter failed for sub_device %d"
1363 : : " with error %d", i, ret);
1364 : 0 : fs_unlock(dev, 0);
1365 : 0 : return ret;
1366 : : }
1367 : : }
1368 : 0 : fs_unlock(dev, 0);
1369 : 0 : return 0;
1370 : : }
1371 : :
1372 : : static int
1373 : 0 : fs_flow_ctrl_get(struct rte_eth_dev *dev,
1374 : : struct rte_eth_fc_conf *fc_conf)
1375 : : {
1376 : : struct sub_device *sdev;
1377 : : int ret;
1378 : :
1379 : 0 : ret = fs_lock(dev, 0);
1380 [ # # ]: 0 : if (ret != 0)
1381 : : return ret;
1382 [ # # # # ]: 0 : sdev = TX_SUBDEV(dev);
1383 : : if (sdev == NULL) {
1384 : : ret = 0;
1385 : 0 : goto unlock;
1386 : : }
1387 [ # # # # ]: 0 : if (SUBOPS(sdev, flow_ctrl_get) == NULL) {
1388 : : ret = -ENOTSUP;
1389 : 0 : goto unlock;
1390 : : }
1391 : 0 : ret = SUBOPS(sdev, flow_ctrl_get)(ETH(sdev), fc_conf);
1392 : 0 : unlock:
1393 : 0 : fs_unlock(dev, 0);
1394 : 0 : return ret;
1395 : : }
1396 : :
1397 : : static int
1398 : 0 : fs_flow_ctrl_set(struct rte_eth_dev *dev,
1399 : : struct rte_eth_fc_conf *fc_conf)
1400 : : {
1401 : : struct sub_device *sdev;
1402 : : uint8_t i;
1403 : : int ret;
1404 : :
1405 : 0 : ret = fs_lock(dev, 0);
1406 [ # # ]: 0 : if (ret != 0)
1407 : : return ret;
1408 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1409 : 0 : DEBUG("Calling rte_eth_dev_flow_ctrl_set on sub_device %d", i);
1410 : 0 : ret = rte_eth_dev_flow_ctrl_set(PORT_ID(sdev), fc_conf);
1411 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1412 : 0 : ERROR("Operation rte_eth_dev_flow_ctrl_set failed for sub_device %d"
1413 : : " with error %d", i, ret);
1414 : 0 : fs_unlock(dev, 0);
1415 : 0 : return ret;
1416 : : }
1417 : : }
1418 : 0 : fs_unlock(dev, 0);
1419 : 0 : return 0;
1420 : : }
1421 : :
1422 : : static void
1423 : 0 : fs_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
1424 : : {
1425 : : struct sub_device *sdev;
1426 : : uint8_t i;
1427 : :
1428 [ # # ]: 0 : if (fs_lock(dev, 0) != 0)
1429 : : return;
1430 : : /* No check: already done within the rte_eth_dev_mac_addr_remove
1431 : : * call for the fail-safe device.
1432 : : */
1433 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)
1434 : 0 : rte_eth_dev_mac_addr_remove(PORT_ID(sdev),
1435 : 0 : &dev->data->mac_addrs[index]);
1436 : 0 : PRIV(dev)->mac_addr_pool[index] = 0;
1437 : 0 : fs_unlock(dev, 0);
1438 : : }
1439 : :
1440 : : static int
1441 : 0 : fs_mac_addr_add(struct rte_eth_dev *dev,
1442 : : struct rte_ether_addr *mac_addr,
1443 : : uint32_t index,
1444 : : uint32_t vmdq)
1445 : : {
1446 : : struct sub_device *sdev;
1447 : : int ret;
1448 : : uint8_t i;
1449 : :
1450 : : RTE_ASSERT(index < FAILSAFE_MAX_ETHADDR);
1451 : 0 : ret = fs_lock(dev, 0);
1452 [ # # ]: 0 : if (ret != 0)
1453 : : return ret;
1454 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1455 : 0 : ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), mac_addr, vmdq);
1456 [ # # ]: 0 : if ((ret = fs_err(sdev, ret))) {
1457 : 0 : ERROR("Operation rte_eth_dev_mac_addr_add failed for sub_device %"
1458 : : PRIu8 " with error %d", i, ret);
1459 : 0 : fs_unlock(dev, 0);
1460 : 0 : return ret;
1461 : : }
1462 : : }
1463 [ # # ]: 0 : if (index >= PRIV(dev)->nb_mac_addr) {
1464 : 0 : DEBUG("Growing mac_addrs array");
1465 : 0 : PRIV(dev)->nb_mac_addr = index;
1466 : : }
1467 : 0 : PRIV(dev)->mac_addr_pool[index] = vmdq;
1468 : 0 : fs_unlock(dev, 0);
1469 : 0 : return 0;
1470 : : }
1471 : :
1472 : : static int
1473 : 0 : fs_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
1474 : : {
1475 : : struct sub_device *sdev;
1476 : : uint8_t i;
1477 : : int ret;
1478 : :
1479 : 0 : ret = fs_lock(dev, 0);
1480 [ # # ]: 0 : if (ret != 0)
1481 : : return ret;
1482 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1483 : 0 : ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), mac_addr);
1484 : : ret = fs_err(sdev, ret);
1485 [ # # ]: 0 : if (ret) {
1486 : 0 : ERROR("Operation rte_eth_dev_mac_addr_set failed for sub_device %d with error %d",
1487 : : i, ret);
1488 : 0 : fs_unlock(dev, 0);
1489 : 0 : return ret;
1490 : : }
1491 : : }
1492 : 0 : fs_unlock(dev, 0);
1493 : :
1494 : 0 : return 0;
1495 : : }
1496 : :
1497 : : static int
1498 : 0 : fs_set_mc_addr_list(struct rte_eth_dev *dev,
1499 : : struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr)
1500 : : {
1501 : : struct sub_device *sdev;
1502 : : uint8_t i;
1503 : : int ret;
1504 : : void *mcast_addrs;
1505 : :
1506 : 0 : ret = fs_lock(dev, 0);
1507 [ # # ]: 0 : if (ret != 0)
1508 : : return ret;
1509 : :
1510 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1511 : 0 : ret = rte_eth_dev_set_mc_addr_list(PORT_ID(sdev),
1512 : : mc_addr_set, nb_mc_addr);
1513 [ # # ]: 0 : if (ret != 0) {
1514 : 0 : ERROR("Operation rte_eth_dev_set_mc_addr_list failed for sub_device %d with error %d",
1515 : : i, ret);
1516 : 0 : goto rollback;
1517 : : }
1518 : : }
1519 : :
1520 : 0 : mcast_addrs = rte_realloc(PRIV(dev)->mcast_addrs,
1521 : : nb_mc_addr * sizeof(PRIV(dev)->mcast_addrs[0]), 0);
1522 [ # # ]: 0 : if (mcast_addrs == NULL && nb_mc_addr > 0) {
1523 : : ret = -ENOMEM;
1524 : 0 : goto rollback;
1525 : : }
1526 : : rte_memcpy(mcast_addrs, mc_addr_set,
1527 : : nb_mc_addr * sizeof(PRIV(dev)->mcast_addrs[0]));
1528 : 0 : PRIV(dev)->nb_mcast_addr = nb_mc_addr;
1529 : 0 : PRIV(dev)->mcast_addrs = mcast_addrs;
1530 : :
1531 : 0 : fs_unlock(dev, 0);
1532 : 0 : return 0;
1533 : :
1534 : 0 : rollback:
1535 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1536 : 0 : int rc = rte_eth_dev_set_mc_addr_list(PORT_ID(sdev),
1537 : 0 : PRIV(dev)->mcast_addrs, PRIV(dev)->nb_mcast_addr);
1538 [ # # ]: 0 : if (rc != 0) {
1539 : 0 : ERROR("Multicast MAC address list rollback for sub_device %d failed with error %d",
1540 : : i, rc);
1541 : : }
1542 : : }
1543 : :
1544 : 0 : fs_unlock(dev, 0);
1545 : 0 : return ret;
1546 : : }
1547 : :
1548 : : static int
1549 : 0 : fs_rss_hash_update(struct rte_eth_dev *dev,
1550 : : struct rte_eth_rss_conf *rss_conf)
1551 : : {
1552 : : struct sub_device *sdev;
1553 : : uint8_t i;
1554 : : int ret;
1555 : :
1556 : 0 : ret = fs_lock(dev, 0);
1557 [ # # ]: 0 : if (ret != 0)
1558 : : return ret;
1559 [ # # ]: 0 : FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
1560 : 0 : ret = rte_eth_dev_rss_hash_update(PORT_ID(sdev), rss_conf);
1561 : : ret = fs_err(sdev, ret);
1562 [ # # ]: 0 : if (ret) {
1563 : 0 : ERROR("Operation rte_eth_dev_rss_hash_update"
1564 : : " failed for sub_device %d with error %d",
1565 : : i, ret);
1566 : 0 : fs_unlock(dev, 0);
1567 : 0 : return ret;
1568 : : }
1569 : : }
1570 : 0 : fs_unlock(dev, 0);
1571 : :
1572 : 0 : return 0;
1573 : : }
1574 : :
1575 : : static int
1576 : 0 : fs_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
1577 : : const struct rte_flow_ops **ops)
1578 : : {
1579 : 0 : *ops = &fs_flow_ops;
1580 : 0 : return 0;
1581 : : }
1582 : :
1583 : : const struct eth_dev_ops failsafe_ops = {
1584 : : .dev_configure = fs_dev_configure,
1585 : : .dev_start = fs_dev_start,
1586 : : .dev_stop = fs_dev_stop,
1587 : : .dev_set_link_down = fs_dev_set_link_down,
1588 : : .dev_set_link_up = fs_dev_set_link_up,
1589 : : .dev_close = failsafe_eth_dev_close,
1590 : : .promiscuous_enable = fs_promiscuous_enable,
1591 : : .promiscuous_disable = fs_promiscuous_disable,
1592 : : .allmulticast_enable = fs_allmulticast_enable,
1593 : : .allmulticast_disable = fs_allmulticast_disable,
1594 : : .link_update = fs_link_update,
1595 : : .stats_get = fs_stats_get,
1596 : : .stats_reset = fs_stats_reset,
1597 : : .xstats_get = fs_xstats_get,
1598 : : .xstats_get_names = fs_xstats_get_names,
1599 : : .xstats_reset = fs_xstats_reset,
1600 : : .dev_infos_get = fs_dev_infos_get,
1601 : : .dev_supported_ptypes_get = fs_dev_supported_ptypes_get,
1602 : : .mtu_set = fs_mtu_set,
1603 : : .vlan_filter_set = fs_vlan_filter_set,
1604 : : .rx_queue_start = fs_rx_queue_start,
1605 : : .rx_queue_stop = fs_rx_queue_stop,
1606 : : .tx_queue_start = fs_tx_queue_start,
1607 : : .tx_queue_stop = fs_tx_queue_stop,
1608 : : .rx_queue_setup = fs_rx_queue_setup,
1609 : : .tx_queue_setup = fs_tx_queue_setup,
1610 : : .rx_queue_release = fs_rx_queue_release,
1611 : : .tx_queue_release = fs_tx_queue_release,
1612 : : .rx_queue_intr_enable = fs_rx_intr_enable,
1613 : : .rx_queue_intr_disable = fs_rx_intr_disable,
1614 : : .flow_ctrl_get = fs_flow_ctrl_get,
1615 : : .flow_ctrl_set = fs_flow_ctrl_set,
1616 : : .mac_addr_remove = fs_mac_addr_remove,
1617 : : .mac_addr_add = fs_mac_addr_add,
1618 : : .mac_addr_set = fs_mac_addr_set,
1619 : : .set_mc_addr_list = fs_set_mc_addr_list,
1620 : : .rss_hash_update = fs_rss_hash_update,
1621 : : .flow_ops_get = fs_flow_ops_get,
1622 : : };
|