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