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