Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright(c) 2019-2021 Xilinx, Inc.
4 : : * Copyright(c) 2019 Solarflare Communications Inc.
5 : : *
6 : : * This software was jointly developed between OKTET Labs (under contract
7 : : * for Solarflare) and Solarflare Communications, Inc.
8 : : */
9 : :
10 : : #include <stdint.h>
11 : :
12 : : #include <rte_flow_driver.h>
13 : : #include <rte_flow.h>
14 : : #include <rte_mbuf.h>
15 : : #include <rte_ethdev.h>
16 : : #include <rte_malloc.h>
17 : : #include <ethdev_driver.h>
18 : :
19 : : #include "efx.h"
20 : :
21 : : #include "sfc_log.h"
22 : : #include "sfc_debug.h"
23 : : #include "sfc_repr.h"
24 : : #include "sfc_ethdev_state.h"
25 : : #include "sfc_repr_proxy_api.h"
26 : : #include "sfc_switch.h"
27 : : #include "sfc_dp_tx.h"
28 : :
29 : : /** Multi-process shared representor private data */
30 : : struct sfc_repr_shared {
31 : : uint16_t pf_port_id;
32 : : uint16_t repr_id;
33 : : uint16_t switch_domain_id;
34 : : uint16_t switch_port_id;
35 : : };
36 : :
37 : : struct sfc_repr_queue_stats {
38 : : union sfc_pkts_bytes packets_bytes;
39 : : };
40 : :
41 : : struct sfc_repr_rxq {
42 : : /* Datapath members */
43 : : struct rte_ring *ring;
44 : : struct sfc_repr_queue_stats stats;
45 : : };
46 : :
47 : : struct sfc_repr_txq {
48 : : /* Datapath members */
49 : : struct rte_ring *ring;
50 : : efx_mport_id_t egress_mport;
51 : : struct sfc_repr_queue_stats stats;
52 : : };
53 : :
54 : : /** Primary process representor private data */
55 : : struct sfc_repr {
56 : : /**
57 : : * PMD setup and configuration is not thread safe. Since it is not
58 : : * performance sensitive, it is better to guarantee thread-safety
59 : : * and add device level lock. Adapter control operations which
60 : : * change its state should acquire the lock.
61 : : */
62 : : rte_spinlock_t lock;
63 : : enum sfc_ethdev_state state;
64 : : };
65 : :
66 : : #define sfcr_err(sr, ...) \
67 : : do { \
68 : : const struct sfc_repr *_sr = (sr); \
69 : : \
70 : : (void)_sr; \
71 : : SFC_GENERIC_LOG(ERR, __VA_ARGS__); \
72 : : } while (0)
73 : :
74 : : #define sfcr_warn(sr, ...) \
75 : : do { \
76 : : const struct sfc_repr *_sr = (sr); \
77 : : \
78 : : (void)_sr; \
79 : : SFC_GENERIC_LOG(WARNING, __VA_ARGS__); \
80 : : } while (0)
81 : :
82 : : #define sfcr_info(sr, ...) \
83 : : do { \
84 : : const struct sfc_repr *_sr = (sr); \
85 : : \
86 : : (void)_sr; \
87 : : SFC_GENERIC_LOG(INFO, \
88 : : RTE_FMT("%s() " \
89 : : RTE_FMT_HEAD(__VA_ARGS__ ,), \
90 : : __func__, \
91 : : RTE_FMT_TAIL(__VA_ARGS__ ,))); \
92 : : } while (0)
93 : :
94 : : static inline struct sfc_repr_shared *
95 : : sfc_repr_shared_by_eth_dev(struct rte_eth_dev *eth_dev)
96 : : {
97 : 0 : struct sfc_repr_shared *srs = eth_dev->data->dev_private;
98 : :
99 : : return srs;
100 : : }
101 : :
102 : : static inline struct sfc_repr *
103 : : sfc_repr_by_eth_dev(struct rte_eth_dev *eth_dev)
104 : : {
105 : 0 : struct sfc_repr *sr = eth_dev->process_private;
106 : :
107 : : return sr;
108 : : }
109 : :
110 : : /*
111 : : * Add wrapper functions to acquire/release lock to be able to remove or
112 : : * change the lock in one place.
113 : : */
114 : :
115 : : #define sfc_repr_lock_init(sr) rte_spinlock_init(&(sr)->lock)
116 : : #define sfc_repr_lock_is_locked(sr) rte_spinlock_is_locked(&(sr)->lock)
117 : : #define sfc_repr_lock(sr) rte_spinlock_lock(&(sr)->lock)
118 : : #define sfc_repr_unlock(sr) rte_spinlock_unlock(&(sr)->lock)
119 : : #define sfc_repr_lock_fini(sr) RTE_SET_USED(sr)
120 : :
121 : : static void
122 : : sfc_repr_rx_queue_stop(void *queue)
123 : : {
124 : : struct sfc_repr_rxq *rxq = queue;
125 : :
126 : 0 : if (rxq == NULL)
127 : : return;
128 : :
129 : 0 : rte_ring_reset(rxq->ring);
130 : : }
131 : :
132 : : static void
133 : : sfc_repr_tx_queue_stop(void *queue)
134 : : {
135 : : struct sfc_repr_txq *txq = queue;
136 : :
137 : 0 : if (txq == NULL)
138 : : return;
139 : :
140 : 0 : rte_ring_reset(txq->ring);
141 : : }
142 : :
143 : : static uint16_t
144 : 0 : sfc_repr_rx_burst(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
145 : : {
146 : : struct sfc_repr_rxq *rxq = rx_queue;
147 : : void **objs = (void *)&rx_pkts[0];
148 : : unsigned int n_rx;
149 : :
150 : : /* mbufs port is already filled correctly by representors proxy */
151 : 0 : n_rx = rte_ring_sc_dequeue_burst(rxq->ring, objs, nb_pkts, NULL);
152 : :
153 : : if (n_rx > 0) {
154 : : unsigned int n_bytes = 0;
155 : : unsigned int i = 0;
156 : :
157 : : do {
158 : 0 : n_bytes += rx_pkts[i]->pkt_len;
159 [ # # ]: 0 : } while (++i < n_rx);
160 : :
161 : 0 : sfc_pkts_bytes_add(&rxq->stats.packets_bytes, n_rx, n_bytes);
162 : : }
163 : :
164 : 0 : return n_rx;
165 : : }
166 : :
167 : : static uint16_t
168 : 0 : sfc_repr_tx_burst(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
169 : : {
170 : : struct sfc_repr_txq *txq = tx_queue;
171 : : unsigned int n_bytes = 0;
172 : : unsigned int n_tx;
173 : : void **objs;
174 : : uint16_t i;
175 : :
176 : : /*
177 : : * mbuf is likely cache-hot. Set flag and egress m-port here instead of
178 : : * doing that in representors proxy. Also, it should help to avoid
179 : : * cache bounce. Moreover, potentially, it allows to use one
180 : : * multi-producer single-consumer ring for all representors.
181 : : *
182 : : * The only potential problem is doing so many times if enqueue
183 : : * fails and sender retries.
184 : : */
185 [ # # ]: 0 : for (i = 0; i < nb_pkts; ++i) {
186 : 0 : struct rte_mbuf *m = tx_pkts[i];
187 : :
188 : 0 : m->ol_flags |= sfc_dp_mport_override;
189 : 0 : *RTE_MBUF_DYNFIELD(m, sfc_dp_mport_offset,
190 : 0 : efx_mport_id_t *) = txq->egress_mport;
191 : 0 : n_bytes += tx_pkts[i]->pkt_len;
192 : : }
193 : :
194 : : objs = (void *)&tx_pkts[0];
195 : 0 : n_tx = rte_ring_sp_enqueue_burst(txq->ring, objs, nb_pkts, NULL);
196 : :
197 : : /*
198 : : * Remove m-port override flag from packets that were not enqueued
199 : : * Setting the flag only for enqueued packets after the burst is
200 : : * not possible since the ownership of enqueued packets is
201 : : * transferred to representor proxy. The same logic applies to
202 : : * counting the enqueued packets' bytes.
203 : : */
204 [ # # ]: 0 : for (i = n_tx; i < nb_pkts; ++i) {
205 : 0 : struct rte_mbuf *m = tx_pkts[i];
206 : :
207 : 0 : m->ol_flags &= ~sfc_dp_mport_override;
208 : 0 : n_bytes -= m->pkt_len;
209 : : }
210 : :
211 : 0 : sfc_pkts_bytes_add(&txq->stats.packets_bytes, n_tx, n_bytes);
212 : :
213 : 0 : return n_tx;
214 : : }
215 : :
216 : : static int
217 : 0 : sfc_repr_start(struct rte_eth_dev *dev)
218 : : {
219 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
220 : : struct sfc_repr_shared *srs;
221 : : int ret;
222 : :
223 : 0 : sfcr_info(sr, "entry");
224 : :
225 : : SFC_ASSERT(sfc_repr_lock_is_locked(sr));
226 : :
227 [ # # # ]: 0 : switch (sr->state) {
228 : : case SFC_ETHDEV_CONFIGURED:
229 : : break;
230 : 0 : case SFC_ETHDEV_STARTED:
231 : 0 : sfcr_info(sr, "already started");
232 : 0 : return 0;
233 : 0 : default:
234 : : ret = -EINVAL;
235 : 0 : goto fail_bad_state;
236 : : }
237 : :
238 : 0 : sr->state = SFC_ETHDEV_STARTING;
239 : :
240 : : srs = sfc_repr_shared_by_eth_dev(dev);
241 : 0 : ret = sfc_repr_proxy_start_repr(srs->pf_port_id, srs->repr_id);
242 [ # # ]: 0 : if (ret != 0) {
243 : : SFC_ASSERT(ret > 0);
244 : 0 : ret = -ret;
245 : 0 : goto fail_start;
246 : : }
247 : :
248 : 0 : sr->state = SFC_ETHDEV_STARTED;
249 : :
250 : 0 : sfcr_info(sr, "done");
251 : :
252 : 0 : return 0;
253 : :
254 : : fail_start:
255 : 0 : sr->state = SFC_ETHDEV_CONFIGURED;
256 : :
257 : 0 : fail_bad_state:
258 : 0 : sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret));
259 : 0 : return ret;
260 : : }
261 : :
262 : : static int
263 : 0 : sfc_repr_dev_start(struct rte_eth_dev *dev)
264 : : {
265 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
266 : : uint16_t i;
267 : : int ret;
268 : :
269 : 0 : sfcr_info(sr, "entry");
270 : :
271 : 0 : sfc_repr_lock(sr);
272 : 0 : ret = sfc_repr_start(dev);
273 : : sfc_repr_unlock(sr);
274 : :
275 [ # # ]: 0 : if (ret != 0)
276 : 0 : goto fail_start;
277 : :
278 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
279 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
280 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
281 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
282 : :
283 : 0 : sfcr_info(sr, "done");
284 : :
285 : 0 : return 0;
286 : :
287 : : fail_start:
288 : 0 : sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret));
289 : 0 : return ret;
290 : : }
291 : :
292 : : static int
293 : 0 : sfc_repr_stop(struct rte_eth_dev *dev)
294 : : {
295 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
296 : : struct sfc_repr_shared *srs;
297 : : unsigned int i;
298 : : int ret;
299 : :
300 : 0 : sfcr_info(sr, "entry");
301 : :
302 : : SFC_ASSERT(sfc_repr_lock_is_locked(sr));
303 : :
304 [ # # # ]: 0 : switch (sr->state) {
305 : : case SFC_ETHDEV_STARTED:
306 : : break;
307 : 0 : case SFC_ETHDEV_CONFIGURED:
308 : 0 : sfcr_info(sr, "already stopped");
309 : 0 : return 0;
310 : 0 : default:
311 : 0 : sfcr_err(sr, "stop in unexpected state %u", sr->state);
312 : : SFC_ASSERT(B_FALSE);
313 : : ret = -EINVAL;
314 : 0 : goto fail_bad_state;
315 : : }
316 : :
317 : : srs = sfc_repr_shared_by_eth_dev(dev);
318 : 0 : ret = sfc_repr_proxy_stop_repr(srs->pf_port_id, srs->repr_id);
319 [ # # ]: 0 : if (ret != 0) {
320 : : SFC_ASSERT(ret > 0);
321 : 0 : ret = -ret;
322 : 0 : goto fail_stop;
323 : : }
324 : :
325 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
326 [ # # ]: 0 : sfc_repr_rx_queue_stop(dev->data->rx_queues[i]);
327 : :
328 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
329 [ # # ]: 0 : sfc_repr_tx_queue_stop(dev->data->tx_queues[i]);
330 : :
331 : 0 : sr->state = SFC_ETHDEV_CONFIGURED;
332 : 0 : sfcr_info(sr, "done");
333 : :
334 : 0 : return 0;
335 : :
336 : : fail_bad_state:
337 : 0 : fail_stop:
338 : 0 : sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret));
339 : :
340 : 0 : return ret;
341 : : }
342 : :
343 : : static int
344 : 0 : sfc_repr_dev_stop(struct rte_eth_dev *dev)
345 : : {
346 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
347 : : uint16_t i;
348 : : int ret;
349 : :
350 : 0 : sfcr_info(sr, "entry");
351 : :
352 : 0 : sfc_repr_lock(sr);
353 : :
354 : 0 : ret = sfc_repr_stop(dev);
355 [ # # ]: 0 : if (ret != 0) {
356 : 0 : sfcr_err(sr, "%s() failed to stop representor", __func__);
357 : 0 : goto fail_stop;
358 : : }
359 : :
360 : : sfc_repr_unlock(sr);
361 : :
362 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
363 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
364 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
365 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
366 : :
367 : 0 : sfcr_info(sr, "done");
368 : :
369 : 0 : return 0;
370 : :
371 : : fail_stop:
372 : : sfc_repr_unlock(sr);
373 : :
374 : 0 : sfcr_err(sr, "%s() failed %s", __func__, rte_strerror(-ret));
375 : :
376 : 0 : return ret;
377 : : }
378 : :
379 : : static int
380 : 0 : sfc_repr_check_conf(struct sfc_repr *sr, uint16_t nb_rx_queues,
381 : : const struct rte_eth_conf *conf)
382 : : {
383 : : const struct rte_eth_rss_conf *rss_conf;
384 : : int ret = 0;
385 : :
386 : 0 : sfcr_info(sr, "entry");
387 : :
388 [ # # ]: 0 : if (conf->link_speeds != 0) {
389 : 0 : sfcr_err(sr, "specific link speeds not supported");
390 : : ret = -EINVAL;
391 : : }
392 : :
393 [ # # # ]: 0 : switch (conf->rxmode.mq_mode) {
394 : 0 : case RTE_ETH_MQ_RX_RSS:
395 [ # # ]: 0 : if (nb_rx_queues != 1) {
396 : 0 : sfcr_err(sr, "Rx RSS is not supported with %u queues",
397 : : nb_rx_queues);
398 : : ret = -EINVAL;
399 : 0 : break;
400 : : }
401 : :
402 : : rss_conf = &conf->rx_adv_conf.rss_conf;
403 [ # # # # ]: 0 : if (rss_conf->rss_key != NULL || rss_conf->rss_key_len != 0 ||
404 [ # # ]: 0 : rss_conf->rss_hf != 0) {
405 : 0 : sfcr_err(sr, "Rx RSS configuration is not supported");
406 : : ret = -EINVAL;
407 : : }
408 : : break;
409 : : case RTE_ETH_MQ_RX_NONE:
410 : : break;
411 : 0 : default:
412 : 0 : sfcr_err(sr, "Rx mode MQ modes other than RSS not supported");
413 : : ret = -EINVAL;
414 : 0 : break;
415 : : }
416 : :
417 [ # # ]: 0 : if (conf->txmode.mq_mode != RTE_ETH_MQ_TX_NONE) {
418 : 0 : sfcr_err(sr, "Tx mode MQ modes not supported");
419 : : ret = -EINVAL;
420 : : }
421 : :
422 [ # # ]: 0 : if (conf->lpbk_mode != 0) {
423 : 0 : sfcr_err(sr, "loopback not supported");
424 : : ret = -EINVAL;
425 : : }
426 : :
427 [ # # ]: 0 : if (conf->dcb_capability_en != 0) {
428 : 0 : sfcr_err(sr, "priority-based flow control not supported");
429 : : ret = -EINVAL;
430 : : }
431 : :
432 [ # # ]: 0 : if (conf->intr_conf.lsc != 0) {
433 : 0 : sfcr_err(sr, "link status change interrupt not supported");
434 : : ret = -EINVAL;
435 : : }
436 : :
437 [ # # ]: 0 : if (conf->intr_conf.rxq != 0) {
438 : 0 : sfcr_err(sr, "receive queue interrupt not supported");
439 : : ret = -EINVAL;
440 : : }
441 : :
442 [ # # ]: 0 : if (conf->intr_conf.rmv != 0) {
443 : 0 : sfcr_err(sr, "remove interrupt not supported");
444 : : ret = -EINVAL;
445 : : }
446 : :
447 : 0 : sfcr_info(sr, "done %d", ret);
448 : :
449 : 0 : return ret;
450 : : }
451 : :
452 : :
453 : : static int
454 : 0 : sfc_repr_configure(struct sfc_repr *sr, uint16_t nb_rx_queues,
455 : : const struct rte_eth_conf *conf)
456 : : {
457 : : int ret;
458 : :
459 : 0 : sfcr_info(sr, "entry");
460 : :
461 : : SFC_ASSERT(sfc_repr_lock_is_locked(sr));
462 : :
463 : 0 : ret = sfc_repr_check_conf(sr, nb_rx_queues, conf);
464 [ # # ]: 0 : if (ret != 0)
465 : 0 : goto fail_check_conf;
466 : :
467 : 0 : sr->state = SFC_ETHDEV_CONFIGURED;
468 : :
469 : 0 : sfcr_info(sr, "done");
470 : :
471 : 0 : return 0;
472 : :
473 : : fail_check_conf:
474 : 0 : sfcr_info(sr, "failed %s", rte_strerror(-ret));
475 : 0 : return ret;
476 : : }
477 : :
478 : : static int
479 : 0 : sfc_repr_dev_configure(struct rte_eth_dev *dev)
480 : : {
481 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
482 : 0 : struct rte_eth_dev_data *dev_data = dev->data;
483 : : int ret;
484 : :
485 : 0 : sfcr_info(sr, "entry n_rxq=%u n_txq=%u",
486 : : dev_data->nb_rx_queues, dev_data->nb_tx_queues);
487 : :
488 : 0 : sfc_repr_lock(sr);
489 [ # # ]: 0 : switch (sr->state) {
490 : 0 : case SFC_ETHDEV_CONFIGURED:
491 : : /* FALLTHROUGH */
492 : : case SFC_ETHDEV_INITIALIZED:
493 : 0 : ret = sfc_repr_configure(sr, dev_data->nb_rx_queues,
494 : 0 : &dev_data->dev_conf);
495 : 0 : break;
496 : 0 : default:
497 : 0 : sfcr_err(sr, "unexpected adapter state %u to configure",
498 : : sr->state);
499 : : ret = -EINVAL;
500 : 0 : break;
501 : : }
502 : : sfc_repr_unlock(sr);
503 : :
504 : 0 : sfcr_info(sr, "done %s", rte_strerror(-ret));
505 : :
506 : 0 : return ret;
507 : : }
508 : :
509 : : static int
510 : 0 : sfc_repr_dev_infos_get(struct rte_eth_dev *dev,
511 : : struct rte_eth_dev_info *dev_info)
512 : : {
513 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
514 : :
515 : 0 : dev_info->device = dev->device;
516 : :
517 : 0 : dev_info->max_rx_pktlen = EFX_MAC_PDU_MAX;
518 : 0 : dev_info->max_rx_queues = SFC_REPR_RXQ_MAX;
519 : 0 : dev_info->max_tx_queues = SFC_REPR_TXQ_MAX;
520 : 0 : dev_info->default_rxconf.rx_drop_en = 1;
521 : 0 : dev_info->switch_info.domain_id = srs->switch_domain_id;
522 : 0 : dev_info->switch_info.port_id = srs->switch_port_id;
523 : :
524 : 0 : return 0;
525 : : }
526 : :
527 : : static int
528 : 0 : sfc_repr_dev_link_update(struct rte_eth_dev *dev,
529 : : __rte_unused int wait_to_complete)
530 : : {
531 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
532 : : struct rte_eth_link link;
533 : :
534 [ # # ]: 0 : if (sr->state != SFC_ETHDEV_STARTED) {
535 : 0 : sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, &link);
536 : : } else {
537 : : memset(&link, 0, sizeof(link));
538 : 0 : link.link_status = RTE_ETH_LINK_UP;
539 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
540 : : }
541 : :
542 : 0 : return rte_eth_linkstatus_set(dev, &link);
543 : : }
544 : :
545 : : static int
546 : 0 : sfc_repr_ring_create(uint16_t pf_port_id, uint16_t repr_id,
547 : : const char *type_name, uint16_t qid, uint16_t nb_desc,
548 : : unsigned int socket_id, struct rte_ring **ring)
549 : : {
550 : : char ring_name[RTE_RING_NAMESIZE];
551 : : int ret;
552 : :
553 [ # # ]: 0 : ret = snprintf(ring_name, sizeof(ring_name), "sfc_%u_repr_%u_%sq%u",
554 : : pf_port_id, repr_id, type_name, qid);
555 [ # # ]: 0 : if (ret >= (int)sizeof(ring_name))
556 : : return -ENAMETOOLONG;
557 : :
558 : : /*
559 : : * Single producer/consumer rings are used since the API for Tx/Rx
560 : : * packet burst for representors are guaranteed to be called from
561 : : * a single thread, and the user of the other end (representor proxy)
562 : : * is also single-threaded.
563 : : */
564 : 0 : *ring = rte_ring_create(ring_name, nb_desc, socket_id,
565 : : RING_F_SP_ENQ | RING_F_SC_DEQ);
566 [ # # ]: 0 : if (*ring == NULL)
567 : 0 : return -rte_errno;
568 : :
569 : : return 0;
570 : : }
571 : :
572 : : static int
573 : 0 : sfc_repr_rx_qcheck_conf(struct sfc_repr *sr,
574 : : const struct rte_eth_rxconf *rx_conf)
575 : : {
576 : : int ret = 0;
577 : :
578 : 0 : sfcr_info(sr, "entry");
579 : :
580 : 0 : if (rx_conf->rx_thresh.pthresh != 0 ||
581 [ # # ]: 0 : rx_conf->rx_thresh.hthresh != 0 ||
582 : : rx_conf->rx_thresh.wthresh != 0) {
583 : 0 : sfcr_warn(sr,
584 : : "RxQ prefetch/host/writeback thresholds are not supported");
585 : : }
586 : :
587 [ # # ]: 0 : if (rx_conf->rx_free_thresh != 0)
588 : 0 : sfcr_warn(sr, "RxQ free threshold is not supported");
589 : :
590 [ # # ]: 0 : if (rx_conf->rx_drop_en == 0)
591 : 0 : sfcr_warn(sr, "RxQ drop disable is not supported");
592 : :
593 [ # # ]: 0 : if (rx_conf->rx_deferred_start) {
594 : 0 : sfcr_err(sr, "Deferred start is not supported");
595 : : ret = -EINVAL;
596 : : }
597 : :
598 : 0 : sfcr_info(sr, "done: %s", rte_strerror(-ret));
599 : :
600 : 0 : return ret;
601 : : }
602 : :
603 : : static int
604 : 0 : sfc_repr_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
605 : : uint16_t nb_rx_desc, unsigned int socket_id,
606 : : __rte_unused const struct rte_eth_rxconf *rx_conf,
607 : : struct rte_mempool *mb_pool)
608 : : {
609 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
610 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
611 : : struct sfc_repr_rxq *rxq;
612 : : int ret;
613 : :
614 : 0 : sfcr_info(sr, "entry");
615 : :
616 : 0 : ret = sfc_repr_rx_qcheck_conf(sr, rx_conf);
617 [ # # ]: 0 : if (ret != 0)
618 : 0 : goto fail_check_conf;
619 : :
620 : : ret = -ENOMEM;
621 : 0 : rxq = rte_zmalloc_socket("sfc-repr-rxq", sizeof(*rxq),
622 : : RTE_CACHE_LINE_SIZE, socket_id);
623 [ # # ]: 0 : if (rxq == NULL) {
624 : 0 : sfcr_err(sr, "%s() failed to alloc RxQ", __func__);
625 : 0 : goto fail_rxq_alloc;
626 : : }
627 : :
628 : 0 : ret = sfc_repr_ring_create(srs->pf_port_id, srs->repr_id,
629 : : "rx", rx_queue_id, nb_rx_desc,
630 : : socket_id, &rxq->ring);
631 [ # # ]: 0 : if (ret != 0) {
632 : 0 : sfcr_err(sr, "%s() failed to create ring", __func__);
633 : 0 : goto fail_ring_create;
634 : : }
635 : :
636 : 0 : ret = sfc_repr_proxy_add_rxq(srs->pf_port_id, srs->repr_id,
637 : : rx_queue_id, rxq->ring, mb_pool);
638 [ # # ]: 0 : if (ret != 0) {
639 : : SFC_ASSERT(ret > 0);
640 : 0 : ret = -ret;
641 : 0 : sfcr_err(sr, "%s() failed to add proxy RxQ", __func__);
642 : 0 : goto fail_proxy_add_rxq;
643 : : }
644 : :
645 : 0 : dev->data->rx_queues[rx_queue_id] = rxq;
646 : :
647 : 0 : sfcr_info(sr, "done");
648 : :
649 : 0 : return 0;
650 : :
651 : : fail_proxy_add_rxq:
652 : 0 : rte_ring_free(rxq->ring);
653 : :
654 : 0 : fail_ring_create:
655 : 0 : rte_free(rxq);
656 : :
657 : 0 : fail_rxq_alloc:
658 : 0 : fail_check_conf:
659 : 0 : sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret));
660 : 0 : return ret;
661 : : }
662 : :
663 : : static void
664 : 0 : sfc_repr_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id)
665 : : {
666 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
667 : 0 : struct sfc_repr_rxq *rxq = dev->data->rx_queues[rx_queue_id];
668 : :
669 : 0 : sfc_repr_proxy_del_rxq(srs->pf_port_id, srs->repr_id, rx_queue_id);
670 : 0 : rte_ring_free(rxq->ring);
671 : 0 : rte_free(rxq);
672 : 0 : }
673 : :
674 : : static int
675 : 0 : sfc_repr_tx_qcheck_conf(struct sfc_repr *sr,
676 : : const struct rte_eth_txconf *tx_conf)
677 : : {
678 : : int ret = 0;
679 : :
680 : 0 : sfcr_info(sr, "entry");
681 : :
682 [ # # ]: 0 : if (tx_conf->tx_rs_thresh != 0)
683 : 0 : sfcr_warn(sr, "RS bit in transmit descriptor is not supported");
684 : :
685 [ # # ]: 0 : if (tx_conf->tx_free_thresh != 0)
686 : 0 : sfcr_warn(sr, "TxQ free threshold is not supported");
687 : :
688 : 0 : if (tx_conf->tx_thresh.pthresh != 0 ||
689 [ # # ]: 0 : tx_conf->tx_thresh.hthresh != 0 ||
690 : : tx_conf->tx_thresh.wthresh != 0) {
691 : 0 : sfcr_warn(sr,
692 : : "prefetch/host/writeback thresholds are not supported");
693 : : }
694 : :
695 [ # # ]: 0 : if (tx_conf->tx_deferred_start) {
696 : 0 : sfcr_err(sr, "Deferred start is not supported");
697 : : ret = -EINVAL;
698 : : }
699 : :
700 : 0 : sfcr_info(sr, "done: %s", rte_strerror(-ret));
701 : :
702 : 0 : return ret;
703 : : }
704 : :
705 : : static int
706 : 0 : sfc_repr_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
707 : : uint16_t nb_tx_desc, unsigned int socket_id,
708 : : const struct rte_eth_txconf *tx_conf)
709 : : {
710 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
711 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
712 : : struct sfc_repr_txq *txq;
713 : : int ret;
714 : :
715 : 0 : sfcr_info(sr, "entry");
716 : :
717 : 0 : ret = sfc_repr_tx_qcheck_conf(sr, tx_conf);
718 [ # # ]: 0 : if (ret != 0)
719 : 0 : goto fail_check_conf;
720 : :
721 : : ret = -ENOMEM;
722 : 0 : txq = rte_zmalloc_socket("sfc-repr-txq", sizeof(*txq),
723 : : RTE_CACHE_LINE_SIZE, socket_id);
724 [ # # ]: 0 : if (txq == NULL)
725 : 0 : goto fail_txq_alloc;
726 : :
727 : 0 : ret = sfc_repr_ring_create(srs->pf_port_id, srs->repr_id,
728 : : "tx", tx_queue_id, nb_tx_desc,
729 : : socket_id, &txq->ring);
730 [ # # ]: 0 : if (ret != 0)
731 : 0 : goto fail_ring_create;
732 : :
733 : 0 : ret = sfc_repr_proxy_add_txq(srs->pf_port_id, srs->repr_id,
734 : : tx_queue_id, txq->ring,
735 : : &txq->egress_mport);
736 [ # # ]: 0 : if (ret != 0)
737 : 0 : goto fail_proxy_add_txq;
738 : :
739 : 0 : dev->data->tx_queues[tx_queue_id] = txq;
740 : :
741 : 0 : sfcr_info(sr, "done");
742 : :
743 : 0 : return 0;
744 : :
745 : : fail_proxy_add_txq:
746 : 0 : rte_ring_free(txq->ring);
747 : :
748 : 0 : fail_ring_create:
749 : 0 : rte_free(txq);
750 : :
751 : 0 : fail_txq_alloc:
752 : 0 : fail_check_conf:
753 : 0 : sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret));
754 : 0 : return ret;
755 : : }
756 : :
757 : : static void
758 : 0 : sfc_repr_tx_queue_release(struct rte_eth_dev *dev, uint16_t tx_queue_id)
759 : : {
760 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
761 : 0 : struct sfc_repr_txq *txq = dev->data->tx_queues[tx_queue_id];
762 : :
763 : 0 : sfc_repr_proxy_del_txq(srs->pf_port_id, srs->repr_id, tx_queue_id);
764 : 0 : rte_ring_free(txq->ring);
765 : 0 : rte_free(txq);
766 : 0 : }
767 : :
768 : : static void
769 : : sfc_repr_close(struct sfc_repr *sr)
770 : : {
771 : : SFC_ASSERT(sfc_repr_lock_is_locked(sr));
772 : : SFC_ASSERT(sr->state == SFC_ETHDEV_CONFIGURED);
773 : :
774 : 0 : sr->state = SFC_ETHDEV_INITIALIZED;
775 : 0 : }
776 : :
777 : : static int
778 : 0 : sfc_repr_dev_close(struct rte_eth_dev *dev)
779 : : {
780 : : struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
781 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
782 : : unsigned int i;
783 : :
784 : 0 : sfcr_info(sr, "entry");
785 : :
786 : 0 : sfc_repr_lock(sr);
787 [ # # # # ]: 0 : switch (sr->state) {
788 : 0 : case SFC_ETHDEV_STARTED:
789 : 0 : sfc_repr_stop(dev);
790 : : SFC_ASSERT(sr->state == SFC_ETHDEV_CONFIGURED);
791 : : /* FALLTHROUGH */
792 : 0 : case SFC_ETHDEV_CONFIGURED:
793 : : sfc_repr_close(sr);
794 : : SFC_ASSERT(sr->state == SFC_ETHDEV_INITIALIZED);
795 : : /* FALLTHROUGH */
796 : : case SFC_ETHDEV_INITIALIZED:
797 : : break;
798 : 0 : default:
799 : 0 : sfcr_err(sr, "unexpected adapter state %u on close", sr->state);
800 : 0 : break;
801 : : }
802 : :
803 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
804 : 0 : sfc_repr_rx_queue_release(dev, i);
805 : 0 : dev->data->rx_queues[i] = NULL;
806 : : }
807 : :
808 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
809 : 0 : sfc_repr_tx_queue_release(dev, i);
810 : 0 : dev->data->tx_queues[i] = NULL;
811 : : }
812 : :
813 : : /*
814 : : * Cleanup all resources.
815 : : * Rollback primary process sfc_repr_eth_dev_init() below.
816 : : */
817 : :
818 : 0 : (void)sfc_repr_proxy_del_port(srs->pf_port_id, srs->repr_id);
819 : :
820 : 0 : sfc_mae_clear_switch_port(srs->switch_domain_id, srs->switch_port_id);
821 : :
822 : 0 : dev->rx_pkt_burst = NULL;
823 : 0 : dev->tx_pkt_burst = NULL;
824 : 0 : dev->dev_ops = NULL;
825 : :
826 : : sfc_repr_unlock(sr);
827 : : sfc_repr_lock_fini(sr);
828 : :
829 : 0 : sfcr_info(sr, "done");
830 : :
831 : 0 : free(sr);
832 : :
833 : 0 : return 0;
834 : : }
835 : :
836 : : static int
837 : 0 : sfc_repr_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
838 : : {
839 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
840 : : int ret;
841 : :
842 : 0 : ret = sfc_repr_proxy_repr_entity_mac_addr_set(srs->pf_port_id,
843 : 0 : srs->repr_id, mac_addr);
844 : 0 : return -ret;
845 : : }
846 : :
847 : : static int
848 : 0 : sfc_repr_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
849 : : {
850 : : union sfc_pkts_bytes queue_stats;
851 : : uint16_t i;
852 : :
853 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
854 : 0 : struct sfc_repr_rxq *rxq = dev->data->rx_queues[i];
855 : :
856 : : sfc_pkts_bytes_get(&rxq->stats.packets_bytes,
857 : : &queue_stats);
858 : :
859 : 0 : stats->ipackets += queue_stats.pkts;
860 : 0 : stats->ibytes += queue_stats.bytes;
861 : : }
862 : :
863 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
864 : 0 : struct sfc_repr_txq *txq = dev->data->tx_queues[i];
865 : :
866 : : sfc_pkts_bytes_get(&txq->stats.packets_bytes,
867 : : &queue_stats);
868 : :
869 : 0 : stats->opackets += queue_stats.pkts;
870 : 0 : stats->obytes += queue_stats.bytes;
871 : : }
872 : :
873 : 0 : return 0;
874 : : }
875 : :
876 : : static int
877 : 0 : sfc_repr_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
878 : : uint16_t *transfer_proxy_port,
879 : : struct rte_flow_error *error)
880 : : {
881 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
882 : :
883 : 0 : return rte_flow_pick_transfer_proxy(srs->pf_port_id,
884 : : transfer_proxy_port, error);
885 : : }
886 : :
887 : : const struct rte_flow_ops sfc_repr_flow_ops = {
888 : : .pick_transfer_proxy = sfc_repr_flow_pick_transfer_proxy,
889 : : };
890 : :
891 : : static int
892 : 0 : sfc_repr_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
893 : : const struct rte_flow_ops **ops)
894 : : {
895 : 0 : *ops = &sfc_repr_flow_ops;
896 : 0 : return 0;
897 : : }
898 : :
899 : : static const struct eth_dev_ops sfc_repr_dev_ops = {
900 : : .dev_configure = sfc_repr_dev_configure,
901 : : .dev_start = sfc_repr_dev_start,
902 : : .dev_stop = sfc_repr_dev_stop,
903 : : .dev_close = sfc_repr_dev_close,
904 : : .dev_infos_get = sfc_repr_dev_infos_get,
905 : : .link_update = sfc_repr_dev_link_update,
906 : : .mac_addr_set = sfc_repr_mac_addr_set,
907 : : .stats_get = sfc_repr_stats_get,
908 : : .rx_queue_setup = sfc_repr_rx_queue_setup,
909 : : .rx_queue_release = sfc_repr_rx_queue_release,
910 : : .tx_queue_setup = sfc_repr_tx_queue_setup,
911 : : .tx_queue_release = sfc_repr_tx_queue_release,
912 : : .flow_ops_get = sfc_repr_dev_flow_ops_get,
913 : : };
914 : :
915 : :
916 : : struct sfc_repr_init_data {
917 : : uint16_t pf_port_id;
918 : : uint16_t switch_domain_id;
919 : : efx_mport_sel_t mport_sel;
920 : : efx_pcie_interface_t intf;
921 : : uint16_t pf;
922 : : uint16_t vf;
923 : : };
924 : :
925 : : static int
926 : : sfc_repr_assign_mae_switch_port(uint16_t switch_domain_id,
927 : : const struct sfc_mae_switch_port_request *req,
928 : : uint16_t *switch_port_id)
929 : : {
930 : : int rc;
931 : :
932 : 0 : rc = sfc_mae_assign_switch_port(switch_domain_id, req, switch_port_id);
933 : :
934 : : SFC_ASSERT(rc >= 0);
935 : 0 : return -rc;
936 : : }
937 : :
938 : : static int
939 : 0 : sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
940 : : {
941 : : const struct sfc_repr_init_data *repr_data = init_params;
942 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
943 : : struct sfc_mae_switch_port_request switch_port_request;
944 : : efx_mport_sel_t ethdev_mport_sel;
945 : : efx_mport_id_t proxy_mport_id;
946 : : struct sfc_repr *sr;
947 : : int ret;
948 : :
949 : : /*
950 : : * For each representor, a driver-internal flow has to be installed
951 : : * in order to direct traffic coming from the represented entity to
952 : : * the "representor proxy". Such internal flows need to find ethdev
953 : : * mport by ethdev ID of the representors in question to specify in
954 : : * delivery action. So set the representor ethdev's mport to that
955 : : * of the "representor proxy" in below switch port request.
956 : : */
957 : 0 : sfc_repr_proxy_mport_alias_get(repr_data->pf_port_id, &proxy_mport_id);
958 : :
959 : 0 : ret = efx_mae_mport_by_id(&proxy_mport_id, ðdev_mport_sel);
960 [ # # ]: 0 : if (ret != 0) {
961 : 0 : SFC_GENERIC_LOG(ERR,
962 : : "%s() failed to get repr proxy mport by ID", __func__);
963 : 0 : goto fail_get_selector;
964 : : }
965 : :
966 : : memset(&switch_port_request, 0, sizeof(switch_port_request));
967 : 0 : switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
968 : 0 : switch_port_request.ethdev_mportp = ðdev_mport_sel;
969 : 0 : switch_port_request.entity_mportp = &repr_data->mport_sel;
970 : 0 : switch_port_request.ethdev_port_id = dev->data->port_id;
971 : 0 : switch_port_request.port_data.repr.intf = repr_data->intf;
972 : 0 : switch_port_request.port_data.repr.pf = repr_data->pf;
973 : 0 : switch_port_request.port_data.repr.vf = repr_data->vf;
974 : :
975 : 0 : ret = sfc_repr_assign_mae_switch_port(repr_data->switch_domain_id,
976 : : &switch_port_request,
977 : : &srs->switch_port_id);
978 [ # # ]: 0 : if (ret != 0) {
979 : 0 : SFC_GENERIC_LOG(ERR,
980 : : "%s() failed to assign MAE switch port (domain id %u)",
981 : : __func__, repr_data->switch_domain_id);
982 : 0 : goto fail_mae_assign_switch_port;
983 : : }
984 : :
985 : 0 : ret = sfc_repr_proxy_add_port(repr_data->pf_port_id,
986 : 0 : srs->switch_port_id, dev->data->port_id,
987 : 0 : &repr_data->mport_sel, repr_data->intf,
988 : 0 : repr_data->pf, repr_data->vf);
989 [ # # ]: 0 : if (ret != 0) {
990 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed to add repr proxy port",
991 : : __func__);
992 : : SFC_ASSERT(ret > 0);
993 : 0 : ret = -ret;
994 : 0 : goto fail_create_port;
995 : : }
996 : :
997 : : /*
998 : : * Allocate process private data from heap, since it should not
999 : : * be located in shared memory allocated using rte_malloc() API.
1000 : : */
1001 : 0 : sr = calloc(1, sizeof(*sr));
1002 [ # # ]: 0 : if (sr == NULL) {
1003 : : ret = -ENOMEM;
1004 : 0 : goto fail_alloc_sr;
1005 : : }
1006 : :
1007 : : sfc_repr_lock_init(sr);
1008 : 0 : sfc_repr_lock(sr);
1009 : :
1010 : 0 : dev->process_private = sr;
1011 : :
1012 : 0 : srs->pf_port_id = repr_data->pf_port_id;
1013 : 0 : srs->repr_id = srs->switch_port_id;
1014 : 0 : srs->switch_domain_id = repr_data->switch_domain_id;
1015 : :
1016 : 0 : dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
1017 : 0 : dev->data->representor_id = srs->repr_id;
1018 : 0 : dev->data->backer_port_id = srs->pf_port_id;
1019 : :
1020 : 0 : dev->data->mac_addrs = rte_zmalloc("sfcr", RTE_ETHER_ADDR_LEN, 0);
1021 [ # # ]: 0 : if (dev->data->mac_addrs == NULL) {
1022 : : ret = -ENOMEM;
1023 : 0 : goto fail_mac_addrs;
1024 : : }
1025 : :
1026 : 0 : rte_eth_random_addr(dev->data->mac_addrs[0].addr_bytes);
1027 : :
1028 : 0 : ret = sfc_repr_proxy_repr_entity_mac_addr_set(repr_data->pf_port_id,
1029 : 0 : srs->repr_id,
1030 : 0 : &dev->data->mac_addrs[0]);
1031 [ # # ]: 0 : if (ret != 0) {
1032 : 0 : ret = -ret;
1033 : 0 : goto fail_mac_addr_set;
1034 : : }
1035 : :
1036 : 0 : dev->rx_pkt_burst = sfc_repr_rx_burst;
1037 : 0 : dev->tx_pkt_burst = sfc_repr_tx_burst;
1038 : 0 : dev->dev_ops = &sfc_repr_dev_ops;
1039 : :
1040 : 0 : sr->state = SFC_ETHDEV_INITIALIZED;
1041 : : sfc_repr_unlock(sr);
1042 : :
1043 : 0 : return 0;
1044 : :
1045 : : fail_mac_addr_set:
1046 : 0 : fail_mac_addrs:
1047 : : sfc_repr_unlock(sr);
1048 : 0 : free(sr);
1049 : :
1050 : 0 : fail_alloc_sr:
1051 : 0 : (void)sfc_repr_proxy_del_port(repr_data->pf_port_id,
1052 : 0 : srs->switch_port_id);
1053 : :
1054 : 0 : fail_create_port:
1055 : 0 : fail_mae_assign_switch_port:
1056 : 0 : fail_get_selector:
1057 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
1058 : 0 : return ret;
1059 : : }
1060 : :
1061 : : int
1062 : 0 : sfc_repr_create(struct rte_eth_dev *parent,
1063 : : struct sfc_repr_entity_info *entity,
1064 : : uint16_t switch_domain_id,
1065 : : const efx_mport_sel_t *mport_sel)
1066 : : {
1067 : : struct sfc_repr_init_data repr_data;
1068 : : char name[RTE_ETH_NAME_MAX_LEN];
1069 : : int controller;
1070 : : int ret;
1071 : : int rc;
1072 : : struct rte_eth_dev *dev;
1073 : :
1074 : 0 : controller = -1;
1075 : 0 : rc = sfc_mae_switch_domain_get_controller(switch_domain_id,
1076 : : entity->intf, &controller);
1077 [ # # ]: 0 : if (rc != 0) {
1078 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed to get DPDK controller for %d",
1079 : : __func__, entity->intf);
1080 : 0 : return -rc;
1081 : : }
1082 : :
1083 [ # # # ]: 0 : switch (entity->type) {
1084 : 0 : case RTE_ETH_REPRESENTOR_VF:
1085 : 0 : ret = snprintf(name, sizeof(name), "net_%s_representor_c%upf%uvf%u",
1086 : 0 : parent->device->name, controller, entity->pf,
1087 : 0 : entity->vf);
1088 : 0 : break;
1089 : 0 : case RTE_ETH_REPRESENTOR_PF:
1090 : 0 : ret = snprintf(name, sizeof(name), "net_%s_representor_c%upf%u",
1091 : 0 : parent->device->name, controller, entity->pf);
1092 : 0 : break;
1093 : : default:
1094 : : return -ENOTSUP;
1095 : : }
1096 : :
1097 [ # # ]: 0 : if (ret >= (int)sizeof(name)) {
1098 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed name too long", __func__);
1099 : 0 : return -ENAMETOOLONG;
1100 : : }
1101 : :
1102 : 0 : dev = rte_eth_dev_allocated(name);
1103 [ # # ]: 0 : if (dev == NULL) {
1104 : : memset(&repr_data, 0, sizeof(repr_data));
1105 : 0 : repr_data.pf_port_id = parent->data->port_id;
1106 : 0 : repr_data.switch_domain_id = switch_domain_id;
1107 : 0 : repr_data.mport_sel = *mport_sel;
1108 : 0 : repr_data.intf = entity->intf;
1109 : 0 : repr_data.pf = entity->pf;
1110 : 0 : repr_data.vf = entity->vf;
1111 : :
1112 : 0 : ret = rte_eth_dev_create(parent->device, name,
1113 : : sizeof(struct sfc_repr_shared),
1114 : : NULL, NULL,
1115 : : sfc_repr_eth_dev_init, &repr_data);
1116 [ # # ]: 0 : if (ret != 0) {
1117 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed to create device",
1118 : : __func__);
1119 : 0 : return ret;
1120 : : }
1121 : : }
1122 : :
1123 : : return 0;
1124 : : }
|