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 : : {
851 : : union sfc_pkts_bytes queue_stats;
852 : : uint16_t i;
853 : :
854 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
855 : 0 : struct sfc_repr_rxq *rxq = dev->data->rx_queues[i];
856 : :
857 : : sfc_pkts_bytes_get(&rxq->stats.packets_bytes,
858 : : &queue_stats);
859 : :
860 : 0 : stats->ipackets += queue_stats.pkts;
861 : 0 : stats->ibytes += queue_stats.bytes;
862 : : }
863 : :
864 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
865 : 0 : struct sfc_repr_txq *txq = dev->data->tx_queues[i];
866 : :
867 : : sfc_pkts_bytes_get(&txq->stats.packets_bytes,
868 : : &queue_stats);
869 : :
870 : 0 : stats->opackets += queue_stats.pkts;
871 : 0 : stats->obytes += queue_stats.bytes;
872 : : }
873 : :
874 : 0 : return 0;
875 : : }
876 : :
877 : : static int
878 : 0 : sfc_repr_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
879 : : uint16_t *transfer_proxy_port,
880 : : struct rte_flow_error *error)
881 : : {
882 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
883 : :
884 : 0 : return rte_flow_pick_transfer_proxy(srs->pf_port_id,
885 : : transfer_proxy_port, error);
886 : : }
887 : :
888 : : const struct rte_flow_ops sfc_repr_flow_ops = {
889 : : .pick_transfer_proxy = sfc_repr_flow_pick_transfer_proxy,
890 : : };
891 : :
892 : : static int
893 : 0 : sfc_repr_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
894 : : const struct rte_flow_ops **ops)
895 : : {
896 : 0 : *ops = &sfc_repr_flow_ops;
897 : 0 : return 0;
898 : : }
899 : :
900 : : static const struct eth_dev_ops sfc_repr_dev_ops = {
901 : : .dev_configure = sfc_repr_dev_configure,
902 : : .dev_start = sfc_repr_dev_start,
903 : : .dev_stop = sfc_repr_dev_stop,
904 : : .dev_close = sfc_repr_dev_close,
905 : : .dev_infos_get = sfc_repr_dev_infos_get,
906 : : .link_update = sfc_repr_dev_link_update,
907 : : .mac_addr_set = sfc_repr_mac_addr_set,
908 : : .stats_get = sfc_repr_stats_get,
909 : : .rx_queue_setup = sfc_repr_rx_queue_setup,
910 : : .rx_queue_release = sfc_repr_rx_queue_release,
911 : : .tx_queue_setup = sfc_repr_tx_queue_setup,
912 : : .tx_queue_release = sfc_repr_tx_queue_release,
913 : : .flow_ops_get = sfc_repr_dev_flow_ops_get,
914 : : };
915 : :
916 : :
917 : : struct sfc_repr_init_data {
918 : : uint16_t pf_port_id;
919 : : uint16_t switch_domain_id;
920 : : efx_mport_sel_t mport_sel;
921 : : efx_pcie_interface_t intf;
922 : : uint16_t pf;
923 : : uint16_t vf;
924 : : unsigned int max_pdu;
925 : : };
926 : :
927 : : static int
928 : : sfc_repr_assign_mae_switch_port(uint16_t switch_domain_id,
929 : : const struct sfc_mae_switch_port_request *req,
930 : : uint16_t *switch_port_id)
931 : : {
932 : : int rc;
933 : :
934 : 0 : rc = sfc_mae_assign_switch_port(switch_domain_id, req, switch_port_id);
935 : :
936 : : SFC_ASSERT(rc >= 0);
937 : 0 : return -rc;
938 : : }
939 : :
940 : : static int
941 : 0 : sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
942 : : {
943 : : const struct sfc_repr_init_data *repr_data = init_params;
944 : : struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
945 : : struct sfc_mae_switch_port_request switch_port_request;
946 : : efx_mport_sel_t ethdev_mport_sel;
947 : : efx_mport_id_t proxy_mport_id;
948 : : struct sfc_repr *sr;
949 : : int ret;
950 : :
951 : : /*
952 : : * For each representor, a driver-internal flow has to be installed
953 : : * in order to direct traffic coming from the represented entity to
954 : : * the "representor proxy". Such internal flows need to find ethdev
955 : : * mport by ethdev ID of the representors in question to specify in
956 : : * delivery action. So set the representor ethdev's mport to that
957 : : * of the "representor proxy" in below switch port request.
958 : : */
959 : 0 : sfc_repr_proxy_mport_alias_get(repr_data->pf_port_id, &proxy_mport_id);
960 : :
961 : 0 : ret = efx_mae_mport_by_id(&proxy_mport_id, ðdev_mport_sel);
962 [ # # ]: 0 : if (ret != 0) {
963 : 0 : SFC_GENERIC_LOG(ERR,
964 : : "%s() failed to get repr proxy mport by ID", __func__);
965 : 0 : goto fail_get_selector;
966 : : }
967 : :
968 : : memset(&switch_port_request, 0, sizeof(switch_port_request));
969 : 0 : switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
970 : 0 : switch_port_request.ethdev_mportp = ðdev_mport_sel;
971 : 0 : switch_port_request.entity_mportp = &repr_data->mport_sel;
972 : 0 : switch_port_request.ethdev_port_id = dev->data->port_id;
973 : 0 : switch_port_request.port_data.repr.intf = repr_data->intf;
974 : 0 : switch_port_request.port_data.repr.pf = repr_data->pf;
975 : 0 : switch_port_request.port_data.repr.vf = repr_data->vf;
976 : :
977 : 0 : ret = sfc_repr_assign_mae_switch_port(repr_data->switch_domain_id,
978 : : &switch_port_request,
979 : : &srs->switch_port_id);
980 [ # # ]: 0 : if (ret != 0) {
981 : 0 : SFC_GENERIC_LOG(ERR,
982 : : "%s() failed to assign MAE switch port (domain id %u)",
983 : : __func__, repr_data->switch_domain_id);
984 : 0 : goto fail_mae_assign_switch_port;
985 : : }
986 : :
987 : 0 : ret = sfc_repr_proxy_add_port(repr_data->pf_port_id,
988 : 0 : srs->switch_port_id, dev->data->port_id,
989 : 0 : &repr_data->mport_sel, repr_data->intf,
990 : 0 : repr_data->pf, repr_data->vf);
991 [ # # ]: 0 : if (ret != 0) {
992 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed to add repr proxy port",
993 : : __func__);
994 : : SFC_ASSERT(ret > 0);
995 : 0 : ret = -ret;
996 : 0 : goto fail_create_port;
997 : : }
998 : :
999 : : /*
1000 : : * Allocate process private data from heap, since it should not
1001 : : * be located in shared memory allocated using rte_malloc() API.
1002 : : */
1003 : 0 : sr = calloc(1, sizeof(*sr));
1004 [ # # ]: 0 : if (sr == NULL) {
1005 : : ret = -ENOMEM;
1006 : 0 : goto fail_alloc_sr;
1007 : : }
1008 : :
1009 : : sfc_repr_lock_init(sr);
1010 : 0 : sfc_repr_lock(sr);
1011 : :
1012 : 0 : dev->process_private = sr;
1013 : :
1014 : 0 : srs->pf_port_id = repr_data->pf_port_id;
1015 : 0 : srs->repr_id = srs->switch_port_id;
1016 : 0 : srs->switch_domain_id = repr_data->switch_domain_id;
1017 : 0 : srs->max_pdu = repr_data->max_pdu;
1018 : :
1019 : 0 : dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
1020 : 0 : dev->data->representor_id = srs->repr_id;
1021 : 0 : dev->data->backer_port_id = srs->pf_port_id;
1022 : :
1023 : 0 : dev->data->mac_addrs = rte_zmalloc("sfcr", RTE_ETHER_ADDR_LEN, 0);
1024 [ # # ]: 0 : if (dev->data->mac_addrs == NULL) {
1025 : : ret = -ENOMEM;
1026 : 0 : goto fail_mac_addrs;
1027 : : }
1028 : :
1029 : 0 : rte_eth_random_addr(dev->data->mac_addrs[0].addr_bytes);
1030 : :
1031 : 0 : ret = sfc_repr_proxy_repr_entity_mac_addr_set(repr_data->pf_port_id,
1032 : 0 : srs->repr_id,
1033 : 0 : &dev->data->mac_addrs[0]);
1034 [ # # ]: 0 : if (ret != 0) {
1035 : 0 : ret = -ret;
1036 : 0 : goto fail_mac_addr_set;
1037 : : }
1038 : :
1039 : 0 : dev->rx_pkt_burst = sfc_repr_rx_burst;
1040 : 0 : dev->tx_pkt_burst = sfc_repr_tx_burst;
1041 : 0 : dev->dev_ops = &sfc_repr_dev_ops;
1042 : :
1043 : 0 : sr->state = SFC_ETHDEV_INITIALIZED;
1044 : : sfc_repr_unlock(sr);
1045 : :
1046 : 0 : return 0;
1047 : :
1048 : : fail_mac_addr_set:
1049 : 0 : fail_mac_addrs:
1050 : : sfc_repr_unlock(sr);
1051 : 0 : free(sr);
1052 : :
1053 : 0 : fail_alloc_sr:
1054 : 0 : (void)sfc_repr_proxy_del_port(repr_data->pf_port_id,
1055 : 0 : srs->switch_port_id);
1056 : :
1057 : 0 : fail_create_port:
1058 : 0 : fail_mae_assign_switch_port:
1059 : 0 : fail_get_selector:
1060 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
1061 : 0 : return ret;
1062 : : }
1063 : :
1064 : : int
1065 : 0 : sfc_repr_create(struct rte_eth_dev *parent,
1066 : : struct sfc_repr_entity_info *entity,
1067 : : uint16_t switch_domain_id,
1068 : : unsigned int max_pdu,
1069 : : const efx_mport_sel_t *mport_sel)
1070 : : {
1071 : : struct sfc_repr_init_data repr_data;
1072 : : char name[RTE_ETH_NAME_MAX_LEN];
1073 : : int controller;
1074 : : int ret;
1075 : : int rc;
1076 : : struct rte_eth_dev *dev;
1077 : :
1078 : 0 : controller = -1;
1079 : 0 : rc = sfc_mae_switch_domain_get_controller(switch_domain_id,
1080 : : entity->intf, &controller);
1081 [ # # ]: 0 : if (rc != 0) {
1082 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed to get DPDK controller for %d",
1083 : : __func__, entity->intf);
1084 : 0 : return -rc;
1085 : : }
1086 : :
1087 [ # # # ]: 0 : switch (entity->type) {
1088 : 0 : case RTE_ETH_REPRESENTOR_VF:
1089 : 0 : ret = snprintf(name, sizeof(name), "net_%s_representor_c%upf%uvf%u",
1090 : 0 : parent->device->name, controller, entity->pf,
1091 : 0 : entity->vf);
1092 : 0 : break;
1093 : 0 : case RTE_ETH_REPRESENTOR_PF:
1094 : 0 : ret = snprintf(name, sizeof(name), "net_%s_representor_c%upf%u",
1095 : 0 : parent->device->name, controller, entity->pf);
1096 : 0 : break;
1097 : : default:
1098 : : return -ENOTSUP;
1099 : : }
1100 : :
1101 [ # # ]: 0 : if (ret >= (int)sizeof(name)) {
1102 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed name too long", __func__);
1103 : 0 : return -ENAMETOOLONG;
1104 : : }
1105 : :
1106 : 0 : dev = rte_eth_dev_allocated(name);
1107 [ # # ]: 0 : if (dev == NULL) {
1108 : : memset(&repr_data, 0, sizeof(repr_data));
1109 : 0 : repr_data.pf_port_id = parent->data->port_id;
1110 : 0 : repr_data.switch_domain_id = switch_domain_id;
1111 : 0 : repr_data.mport_sel = *mport_sel;
1112 : 0 : repr_data.intf = entity->intf;
1113 : 0 : repr_data.pf = entity->pf;
1114 : 0 : repr_data.vf = entity->vf;
1115 : 0 : repr_data.max_pdu = max_pdu;
1116 : :
1117 : 0 : ret = rte_eth_dev_create(parent->device, name,
1118 : : sizeof(struct sfc_repr_shared),
1119 : : NULL, NULL,
1120 : : sfc_repr_eth_dev_init, &repr_data);
1121 [ # # ]: 0 : if (ret != 0) {
1122 : 0 : SFC_GENERIC_LOG(ERR, "%s() failed to create device",
1123 : : __func__);
1124 : 0 : return ret;
1125 : : }
1126 : : }
1127 : :
1128 : : return 0;
1129 : : }
|