net/sfc: implement representor Tx
[dpdk.git] / drivers / net / sfc / sfc_repr_proxy.c
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 <rte_service.h>
11 #include <rte_service_component.h>
12
13 #include "sfc_log.h"
14 #include "sfc_service.h"
15 #include "sfc_repr_proxy.h"
16 #include "sfc_repr_proxy_api.h"
17 #include "sfc.h"
18 #include "sfc_ev.h"
19 #include "sfc_rx.h"
20 #include "sfc_tx.h"
21
22 /**
23  * Amount of time to wait for the representor proxy routine (which is
24  * running on a service core) to handle a request sent via mbox.
25  */
26 #define SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS     1000
27
28 /**
29  * Amount of time to wait for the representor proxy routine (which is
30  * running on a service core) to terminate after service core is stopped.
31  */
32 #define SFC_REPR_PROXY_ROUTINE_TERMINATE_TIMEOUT_MS     10000
33
34 static struct sfc_repr_proxy *
35 sfc_repr_proxy_by_adapter(struct sfc_adapter *sa)
36 {
37         return &sa->repr_proxy;
38 }
39
40 static struct sfc_adapter *
41 sfc_get_adapter_by_pf_port_id(uint16_t pf_port_id)
42 {
43         struct rte_eth_dev *dev;
44         struct sfc_adapter *sa;
45
46         SFC_ASSERT(pf_port_id < RTE_MAX_ETHPORTS);
47
48         dev = &rte_eth_devices[pf_port_id];
49         sa = sfc_adapter_by_eth_dev(dev);
50
51         sfc_adapter_lock(sa);
52
53         return sa;
54 }
55
56 static void
57 sfc_put_adapter(struct sfc_adapter *sa)
58 {
59         sfc_adapter_unlock(sa);
60 }
61
62 static struct sfc_repr_proxy_port *
63 sfc_repr_proxy_find_port(struct sfc_repr_proxy *rp, uint16_t repr_id)
64 {
65         struct sfc_repr_proxy_port *port;
66
67         TAILQ_FOREACH(port, &rp->ports, entries) {
68                 if (port->repr_id == repr_id)
69                         return port;
70         }
71
72         return NULL;
73 }
74
75 static int
76 sfc_repr_proxy_mbox_send(struct sfc_repr_proxy_mbox *mbox,
77                          struct sfc_repr_proxy_port *port,
78                          enum sfc_repr_proxy_mbox_op op)
79 {
80         const unsigned int wait_ms = SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS;
81         unsigned int i;
82
83         mbox->op = op;
84         mbox->port = port;
85         mbox->ack = false;
86
87         /*
88          * Release ordering enforces marker set after data is populated.
89          * Paired with acquire ordering in sfc_repr_proxy_mbox_handle().
90          */
91         __atomic_store_n(&mbox->write_marker, true, __ATOMIC_RELEASE);
92
93         /*
94          * Wait for the representor routine to process the request.
95          * Give up on timeout.
96          */
97         for (i = 0; i < wait_ms; i++) {
98                 /*
99                  * Paired with release ordering in sfc_repr_proxy_mbox_handle()
100                  * on acknowledge write.
101                  */
102                 if (__atomic_load_n(&mbox->ack, __ATOMIC_ACQUIRE))
103                         break;
104
105                 rte_delay_ms(1);
106         }
107
108         if (i == wait_ms) {
109                 SFC_GENERIC_LOG(ERR,
110                         "%s() failed to wait for representor proxy routine ack",
111                         __func__);
112                 return ETIMEDOUT;
113         }
114
115         return 0;
116 }
117
118 static void
119 sfc_repr_proxy_mbox_handle(struct sfc_repr_proxy *rp)
120 {
121         struct sfc_repr_proxy_mbox *mbox = &rp->mbox;
122
123         /*
124          * Paired with release ordering in sfc_repr_proxy_mbox_send()
125          * on marker set.
126          */
127         if (!__atomic_load_n(&mbox->write_marker, __ATOMIC_ACQUIRE))
128                 return;
129
130         mbox->write_marker = false;
131
132         switch (mbox->op) {
133         case SFC_REPR_PROXY_MBOX_ADD_PORT:
134                 TAILQ_INSERT_TAIL(&rp->ports, mbox->port, entries);
135                 break;
136         case SFC_REPR_PROXY_MBOX_DEL_PORT:
137                 TAILQ_REMOVE(&rp->ports, mbox->port, entries);
138                 break;
139         case SFC_REPR_PROXY_MBOX_START_PORT:
140                 mbox->port->started = true;
141                 break;
142         case SFC_REPR_PROXY_MBOX_STOP_PORT:
143                 mbox->port->started = false;
144                 break;
145         default:
146                 SFC_ASSERT(0);
147                 return;
148         }
149
150         /*
151          * Paired with acquire ordering in sfc_repr_proxy_mbox_send()
152          * on acknowledge read.
153          */
154         __atomic_store_n(&mbox->ack, true, __ATOMIC_RELEASE);
155 }
156
157 static void
158 sfc_repr_proxy_handle_tx(struct sfc_repr_proxy_dp_txq *rp_txq,
159                          struct sfc_repr_proxy_txq *repr_txq)
160 {
161         /*
162          * With multiple representor proxy queues configured it is
163          * possible that not all of the corresponding representor
164          * queues were created. Skip the queues that do not exist.
165          */
166         if (repr_txq->ring == NULL)
167                 return;
168
169         if (rp_txq->available < RTE_DIM(rp_txq->tx_pkts)) {
170                 rp_txq->available +=
171                         rte_ring_sc_dequeue_burst(repr_txq->ring,
172                                 (void **)(&rp_txq->tx_pkts[rp_txq->available]),
173                                 RTE_DIM(rp_txq->tx_pkts) - rp_txq->available,
174                                 NULL);
175
176                 if (rp_txq->available == rp_txq->transmitted)
177                         return;
178         }
179
180         rp_txq->transmitted += rp_txq->pkt_burst(rp_txq->dp,
181                                 &rp_txq->tx_pkts[rp_txq->transmitted],
182                                 rp_txq->available - rp_txq->transmitted);
183
184         if (rp_txq->available == rp_txq->transmitted) {
185                 rp_txq->available = 0;
186                 rp_txq->transmitted = 0;
187         }
188 }
189
190 static int32_t
191 sfc_repr_proxy_routine(void *arg)
192 {
193         struct sfc_repr_proxy_port *port;
194         struct sfc_repr_proxy *rp = arg;
195         unsigned int i;
196
197         sfc_repr_proxy_mbox_handle(rp);
198
199         TAILQ_FOREACH(port, &rp->ports, entries) {
200                 if (!port->started)
201                         continue;
202
203                 for (i = 0; i < rp->nb_txq; i++)
204                         sfc_repr_proxy_handle_tx(&rp->dp_txq[i], &port->txq[i]);
205         }
206
207         return 0;
208 }
209
210 static struct sfc_txq_info *
211 sfc_repr_proxy_txq_info_get(struct sfc_adapter *sa, unsigned int repr_queue_id)
212 {
213         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
214         struct sfc_repr_proxy_dp_txq *dp_txq;
215
216         SFC_ASSERT(repr_queue_id < sfc_repr_nb_txq(sas));
217         dp_txq = &sa->repr_proxy.dp_txq[repr_queue_id];
218
219         return &sas->txq_info[dp_txq->sw_index];
220 }
221
222 static int
223 sfc_repr_proxy_txq_attach(struct sfc_adapter *sa)
224 {
225         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
226         struct sfc_repr_proxy *rp = &sa->repr_proxy;
227         unsigned int i;
228
229         sfc_log_init(sa, "entry");
230
231         for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
232                 sfc_sw_index_t sw_index = sfc_repr_txq_sw_index(sas, i);
233
234                 rp->dp_txq[i].sw_index = sw_index;
235         }
236
237         sfc_log_init(sa, "done");
238
239         return 0;
240 }
241
242 static void
243 sfc_repr_proxy_txq_detach(struct sfc_adapter *sa)
244 {
245         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
246         struct sfc_repr_proxy *rp = &sa->repr_proxy;
247         unsigned int i;
248
249         sfc_log_init(sa, "entry");
250
251         for (i = 0; i < sfc_repr_nb_txq(sas); i++)
252                 rp->dp_txq[i].sw_index = 0;
253
254         sfc_log_init(sa, "done");
255 }
256
257 int
258 sfc_repr_proxy_txq_init(struct sfc_adapter *sa)
259 {
260         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
261         struct sfc_repr_proxy *rp = &sa->repr_proxy;
262         const struct rte_eth_txconf tx_conf = {
263                 .tx_free_thresh = SFC_REPR_PROXY_TXQ_FREE_THRESH,
264         };
265         struct sfc_txq_info *txq_info;
266         unsigned int init_i;
267         unsigned int i;
268         int rc;
269
270         sfc_log_init(sa, "entry");
271
272         if (!sfc_repr_available(sas)) {
273                 sfc_log_init(sa, "representors not supported - skip");
274                 return 0;
275         }
276
277         for (init_i = 0; init_i < sfc_repr_nb_txq(sas); init_i++) {
278                 struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[init_i];
279
280                 txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
281                 if (txq_info->state == SFC_TXQ_INITIALIZED) {
282                         sfc_log_init(sa,
283                                 "representor proxy TxQ %u is already initialized - skip",
284                                 init_i);
285                         continue;
286                 }
287
288                 sfc_tx_qinit_info(sa, txq->sw_index);
289
290                 rc = sfc_tx_qinit(sa, txq->sw_index,
291                                   SFC_REPR_PROXY_TX_DESC_COUNT, sa->socket_id,
292                                   &tx_conf);
293
294                 if (rc != 0) {
295                         sfc_err(sa, "failed to init representor proxy TxQ %u",
296                                 init_i);
297                         goto fail_init;
298                 }
299         }
300
301         sfc_log_init(sa, "done");
302
303         return 0;
304
305 fail_init:
306         for (i = 0; i < init_i; i++) {
307                 struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
308
309                 txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
310                 if (txq_info->state == SFC_TXQ_INITIALIZED)
311                         sfc_tx_qfini(sa, txq->sw_index);
312         }
313         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
314
315         return rc;
316 }
317
318 void
319 sfc_repr_proxy_txq_fini(struct sfc_adapter *sa)
320 {
321         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
322         struct sfc_repr_proxy *rp = &sa->repr_proxy;
323         struct sfc_txq_info *txq_info;
324         unsigned int i;
325
326         sfc_log_init(sa, "entry");
327
328         if (!sfc_repr_available(sas)) {
329                 sfc_log_init(sa, "representors not supported - skip");
330                 return;
331         }
332
333         for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
334                 struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
335
336                 txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
337                 if (txq_info->state != SFC_TXQ_INITIALIZED) {
338                         sfc_log_init(sa,
339                                 "representor proxy TxQ %u is already finalized - skip",
340                                 i);
341                         continue;
342                 }
343
344                 sfc_tx_qfini(sa, txq->sw_index);
345         }
346
347         sfc_log_init(sa, "done");
348 }
349
350 static int
351 sfc_repr_proxy_txq_start(struct sfc_adapter *sa)
352 {
353         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
354         struct sfc_repr_proxy *rp = &sa->repr_proxy;
355         unsigned int i;
356
357         sfc_log_init(sa, "entry");
358
359         for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
360                 struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
361
362                 txq->dp = sfc_repr_proxy_txq_info_get(sa, i)->dp;
363                 txq->pkt_burst = sa->eth_dev->tx_pkt_burst;
364                 txq->available = 0;
365                 txq->transmitted = 0;
366         }
367
368         sfc_log_init(sa, "done");
369
370         return 0;
371 }
372
373 static void
374 sfc_repr_proxy_txq_stop(struct sfc_adapter *sa)
375 {
376         sfc_log_init(sa, "entry");
377         sfc_log_init(sa, "done");
378 }
379
380 static int
381 sfc_repr_proxy_rxq_attach(struct sfc_adapter *sa)
382 {
383         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
384         struct sfc_repr_proxy *rp = &sa->repr_proxy;
385         unsigned int i;
386
387         sfc_log_init(sa, "entry");
388
389         for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
390                 sfc_sw_index_t sw_index = sfc_repr_rxq_sw_index(sas, i);
391
392                 rp->dp_rxq[i].sw_index = sw_index;
393         }
394
395         sfc_log_init(sa, "done");
396
397         return 0;
398 }
399
400 static void
401 sfc_repr_proxy_rxq_detach(struct sfc_adapter *sa)
402 {
403         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
404         struct sfc_repr_proxy *rp = &sa->repr_proxy;
405         unsigned int i;
406
407         sfc_log_init(sa, "entry");
408
409         for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
410                 rp->dp_rxq[i].sw_index = 0;
411
412         sfc_log_init(sa, "done");
413 }
414
415 static int
416 sfc_repr_proxy_rxq_init(struct sfc_adapter *sa,
417                         struct sfc_repr_proxy_dp_rxq *rxq)
418 {
419         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
420         uint16_t nb_rx_desc = SFC_REPR_PROXY_RX_DESC_COUNT;
421         struct sfc_rxq_info *rxq_info;
422         struct rte_eth_rxconf rxconf = {
423                 .rx_free_thresh = SFC_REPR_PROXY_RXQ_REFILL_LEVEL,
424                 .rx_drop_en = 1,
425         };
426         int rc;
427
428         sfc_log_init(sa, "entry");
429
430         rxq_info = &sas->rxq_info[rxq->sw_index];
431         if (rxq_info->state & SFC_RXQ_INITIALIZED) {
432                 sfc_log_init(sa, "RxQ is already initialized - skip");
433                 return 0;
434         }
435
436         nb_rx_desc = RTE_MIN(nb_rx_desc, sa->rxq_max_entries);
437         nb_rx_desc = RTE_MAX(nb_rx_desc, sa->rxq_min_entries);
438
439         rc = sfc_rx_qinit_info(sa, rxq->sw_index, EFX_RXQ_FLAG_INGRESS_MPORT);
440         if (rc != 0) {
441                 sfc_err(sa, "failed to init representor proxy RxQ info");
442                 goto fail_repr_rxq_init_info;
443         }
444
445         rc = sfc_rx_qinit(sa, rxq->sw_index, nb_rx_desc, sa->socket_id, &rxconf,
446                           rxq->mp);
447         if (rc != 0) {
448                 sfc_err(sa, "failed to init representor proxy RxQ");
449                 goto fail_repr_rxq_init;
450         }
451
452         sfc_log_init(sa, "done");
453
454         return 0;
455
456 fail_repr_rxq_init:
457 fail_repr_rxq_init_info:
458         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
459
460         return rc;
461 }
462
463 static void
464 sfc_repr_proxy_rxq_fini(struct sfc_adapter *sa)
465 {
466         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
467         struct sfc_repr_proxy *rp = &sa->repr_proxy;
468         struct sfc_rxq_info *rxq_info;
469         unsigned int i;
470
471         sfc_log_init(sa, "entry");
472
473         if (!sfc_repr_available(sas)) {
474                 sfc_log_init(sa, "representors not supported - skip");
475                 return;
476         }
477
478         for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
479                 struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
480
481                 rxq_info = &sas->rxq_info[rxq->sw_index];
482                 if (rxq_info->state != SFC_RXQ_INITIALIZED) {
483                         sfc_log_init(sa,
484                                 "representor RxQ %u is already finalized - skip",
485                                 i);
486                         continue;
487                 }
488
489                 sfc_rx_qfini(sa, rxq->sw_index);
490         }
491
492         sfc_log_init(sa, "done");
493 }
494
495 static void
496 sfc_repr_proxy_rxq_stop(struct sfc_adapter *sa)
497 {
498         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
499         unsigned int i;
500
501         sfc_log_init(sa, "entry");
502
503         for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
504                 sfc_rx_qstop(sa, sa->repr_proxy.dp_rxq[i].sw_index);
505
506         sfc_repr_proxy_rxq_fini(sa);
507
508         sfc_log_init(sa, "done");
509 }
510
511 static int
512 sfc_repr_proxy_rxq_start(struct sfc_adapter *sa)
513 {
514         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
515         struct sfc_repr_proxy *rp = &sa->repr_proxy;
516         unsigned int i;
517         int rc;
518
519         sfc_log_init(sa, "entry");
520
521         if (!sfc_repr_available(sas)) {
522                 sfc_log_init(sa, "representors not supported - skip");
523                 return 0;
524         }
525
526         for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
527                 struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
528
529                 rc = sfc_repr_proxy_rxq_init(sa, rxq);
530                 if (rc != 0) {
531                         sfc_err(sa, "failed to init representor proxy RxQ %u",
532                                 i);
533                         goto fail_init;
534                 }
535
536                 rc = sfc_rx_qstart(sa, rxq->sw_index);
537                 if (rc != 0) {
538                         sfc_err(sa, "failed to start representor proxy RxQ %u",
539                                 i);
540                         goto fail_start;
541                 }
542         }
543
544         sfc_log_init(sa, "done");
545
546         return 0;
547
548 fail_start:
549 fail_init:
550         sfc_repr_proxy_rxq_stop(sa);
551         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
552         return rc;
553 }
554
555 static int
556 sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,
557                                struct sfc_repr_proxy_port *port)
558 {
559         struct sfc_repr_proxy *rp = &sa->repr_proxy;
560         efx_mport_sel_t mport_alias_selector;
561         efx_mport_sel_t mport_vf_selector;
562         struct sfc_mae_rule *mae_rule;
563         int rc;
564
565         sfc_log_init(sa, "entry");
566
567         rc = efx_mae_mport_by_id(&port->egress_mport,
568                                  &mport_vf_selector);
569         if (rc != 0) {
570                 sfc_err(sa, "failed to get VF mport for repr %u",
571                         port->repr_id);
572                 goto fail_get_vf;
573         }
574
575         rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
576         if (rc != 0) {
577                 sfc_err(sa, "failed to get mport selector for repr %u",
578                         port->repr_id);
579                 goto fail_get_alias;
580         }
581
582         rc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,
583                                                   &mport_alias_selector, -1,
584                                                   &mae_rule);
585         if (rc != 0) {
586                 sfc_err(sa, "failed to insert MAE rule for repr %u",
587                         port->repr_id);
588                 goto fail_rule_add;
589         }
590
591         port->mae_rule = mae_rule;
592
593         sfc_log_init(sa, "done");
594
595         return 0;
596
597 fail_rule_add:
598 fail_get_alias:
599 fail_get_vf:
600         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
601         return rc;
602 }
603
604 static void
605 sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,
606                                struct sfc_repr_proxy_port *port)
607 {
608         struct sfc_mae_rule *mae_rule = port->mae_rule;
609
610         sfc_mae_rule_del(sa, mae_rule);
611 }
612
613 static int
614 sfc_repr_proxy_mport_filter_insert(struct sfc_adapter *sa)
615 {
616         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
617         struct sfc_repr_proxy *rp = &sa->repr_proxy;
618         struct sfc_rxq *rxq_ctrl;
619         struct sfc_repr_proxy_filter *filter = &rp->mport_filter;
620         efx_mport_sel_t mport_alias_selector;
621         static const efx_filter_match_flags_t flags[RTE_DIM(filter->specs)] = {
622                 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST,
623                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST };
624         unsigned int i;
625         int rc;
626
627         sfc_log_init(sa, "entry");
628
629         if (sfc_repr_nb_rxq(sas) == 1) {
630                 rxq_ctrl = &sa->rxq_ctrl[rp->dp_rxq[0].sw_index];
631         } else {
632                 sfc_err(sa, "multiple representor proxy RxQs not supported");
633                 rc = ENOTSUP;
634                 goto fail_multiple_queues;
635         }
636
637         rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
638         if (rc != 0) {
639                 sfc_err(sa, "failed to get repr proxy mport by ID");
640                 goto fail_get_selector;
641         }
642
643         memset(filter->specs, 0, sizeof(filter->specs));
644         for (i = 0; i < RTE_DIM(filter->specs); i++) {
645                 filter->specs[i].efs_priority = EFX_FILTER_PRI_MANUAL;
646                 filter->specs[i].efs_flags = EFX_FILTER_FLAG_RX;
647                 filter->specs[i].efs_dmaq_id = rxq_ctrl->hw_index;
648                 filter->specs[i].efs_match_flags = flags[i] |
649                                 EFX_FILTER_MATCH_MPORT;
650                 filter->specs[i].efs_ingress_mport = mport_alias_selector.sel;
651
652                 rc = efx_filter_insert(sa->nic, &filter->specs[i]);
653                 if (rc != 0) {
654                         sfc_err(sa, "failed to insert repr proxy filter");
655                         goto fail_insert;
656                 }
657         }
658
659         sfc_log_init(sa, "done");
660
661         return 0;
662
663 fail_insert:
664         while (i-- > 0)
665                 efx_filter_remove(sa->nic, &filter->specs[i]);
666
667 fail_get_selector:
668 fail_multiple_queues:
669         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
670         return rc;
671 }
672
673 static void
674 sfc_repr_proxy_mport_filter_remove(struct sfc_adapter *sa)
675 {
676         struct sfc_repr_proxy *rp = &sa->repr_proxy;
677         struct sfc_repr_proxy_filter *filter = &rp->mport_filter;
678         unsigned int i;
679
680         for (i = 0; i < RTE_DIM(filter->specs); i++)
681                 efx_filter_remove(sa->nic, &filter->specs[i]);
682 }
683
684 static int
685 sfc_repr_proxy_port_rule_insert(struct sfc_adapter *sa,
686                                 struct sfc_repr_proxy_port *port)
687 {
688         int rc;
689
690         rc = sfc_repr_proxy_mae_rule_insert(sa, port);
691         if (rc != 0)
692                 goto fail_mae_rule_insert;
693
694         return 0;
695
696 fail_mae_rule_insert:
697         return rc;
698 }
699
700 static void
701 sfc_repr_proxy_port_rule_remove(struct sfc_adapter *sa,
702                                 struct sfc_repr_proxy_port *port)
703 {
704         sfc_repr_proxy_mae_rule_remove(sa, port);
705 }
706
707 static int
708 sfc_repr_proxy_ports_init(struct sfc_adapter *sa)
709 {
710         struct sfc_repr_proxy *rp = &sa->repr_proxy;
711         int rc;
712
713         sfc_log_init(sa, "entry");
714
715         rc = efx_mcdi_mport_alloc_alias(sa->nic, &rp->mport_alias, NULL);
716         if (rc != 0) {
717                 sfc_err(sa, "failed to alloc mport alias: %s",
718                         rte_strerror(rc));
719                 goto fail_alloc_mport_alias;
720         }
721
722         TAILQ_INIT(&rp->ports);
723
724         sfc_log_init(sa, "done");
725
726         return 0;
727
728 fail_alloc_mport_alias:
729
730         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
731         return rc;
732 }
733
734 void
735 sfc_repr_proxy_pre_detach(struct sfc_adapter *sa)
736 {
737         struct sfc_repr_proxy *rp = &sa->repr_proxy;
738         bool close_ports[RTE_MAX_ETHPORTS] = {0};
739         struct sfc_repr_proxy_port *port;
740         unsigned int i;
741
742         SFC_ASSERT(!sfc_adapter_is_locked(sa));
743
744         sfc_adapter_lock(sa);
745
746         if (sfc_repr_available(sfc_sa2shared(sa))) {
747                 TAILQ_FOREACH(port, &rp->ports, entries)
748                         close_ports[port->rte_port_id] = true;
749         } else {
750                 sfc_log_init(sa, "representors not supported - skip");
751         }
752
753         sfc_adapter_unlock(sa);
754
755         for (i = 0; i < RTE_DIM(close_ports); i++) {
756                 if (close_ports[i]) {
757                         rte_eth_dev_stop(i);
758                         rte_eth_dev_close(i);
759                 }
760         }
761 }
762
763 static void
764 sfc_repr_proxy_ports_fini(struct sfc_adapter *sa)
765 {
766         struct sfc_repr_proxy *rp = &sa->repr_proxy;
767
768         efx_mae_mport_free(sa->nic, &rp->mport_alias);
769 }
770
771 int
772 sfc_repr_proxy_attach(struct sfc_adapter *sa)
773 {
774         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
775         struct sfc_repr_proxy *rp = &sa->repr_proxy;
776         struct rte_service_spec service;
777         uint32_t cid;
778         uint32_t sid;
779         int rc;
780
781         sfc_log_init(sa, "entry");
782
783         if (!sfc_repr_available(sas)) {
784                 sfc_log_init(sa, "representors not supported - skip");
785                 return 0;
786         }
787
788         rc = sfc_repr_proxy_rxq_attach(sa);
789         if (rc != 0)
790                 goto fail_rxq_attach;
791
792         rc = sfc_repr_proxy_txq_attach(sa);
793         if (rc != 0)
794                 goto fail_txq_attach;
795
796         rc = sfc_repr_proxy_ports_init(sa);
797         if (rc != 0)
798                 goto fail_ports_init;
799
800         cid = sfc_get_service_lcore(sa->socket_id);
801         if (cid == RTE_MAX_LCORE && sa->socket_id != SOCKET_ID_ANY) {
802                 /* Warn and try to allocate on any NUMA node */
803                 sfc_warn(sa,
804                         "repr proxy: unable to get service lcore at socket %d",
805                         sa->socket_id);
806
807                 cid = sfc_get_service_lcore(SOCKET_ID_ANY);
808         }
809         if (cid == RTE_MAX_LCORE) {
810                 rc = ENOTSUP;
811                 sfc_err(sa, "repr proxy: failed to get service lcore");
812                 goto fail_get_service_lcore;
813         }
814
815         memset(&service, 0, sizeof(service));
816         snprintf(service.name, sizeof(service.name),
817                  "net_sfc_%hu_repr_proxy", sfc_sa2shared(sa)->port_id);
818         service.socket_id = rte_lcore_to_socket_id(cid);
819         service.callback = sfc_repr_proxy_routine;
820         service.callback_userdata = rp;
821
822         rc = rte_service_component_register(&service, &sid);
823         if (rc != 0) {
824                 rc = ENOEXEC;
825                 sfc_err(sa, "repr proxy: failed to register service component");
826                 goto fail_register;
827         }
828
829         rc = rte_service_map_lcore_set(sid, cid, 1);
830         if (rc != 0) {
831                 rc = -rc;
832                 sfc_err(sa, "repr proxy: failed to map lcore");
833                 goto fail_map_lcore;
834         }
835
836         rp->service_core_id = cid;
837         rp->service_id = sid;
838
839         sfc_log_init(sa, "done");
840
841         return 0;
842
843 fail_map_lcore:
844         rte_service_component_unregister(sid);
845
846 fail_register:
847         /*
848          * No need to rollback service lcore get since
849          * it just makes socket_id based search and remembers it.
850          */
851
852 fail_get_service_lcore:
853         sfc_repr_proxy_ports_fini(sa);
854
855 fail_ports_init:
856         sfc_repr_proxy_txq_detach(sa);
857
858 fail_txq_attach:
859         sfc_repr_proxy_rxq_detach(sa);
860
861 fail_rxq_attach:
862         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
863         return rc;
864 }
865
866 void
867 sfc_repr_proxy_detach(struct sfc_adapter *sa)
868 {
869         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
870         struct sfc_repr_proxy *rp = &sa->repr_proxy;
871
872         sfc_log_init(sa, "entry");
873
874         if (!sfc_repr_available(sas)) {
875                 sfc_log_init(sa, "representors not supported - skip");
876                 return;
877         }
878
879         rte_service_map_lcore_set(rp->service_id, rp->service_core_id, 0);
880         rte_service_component_unregister(rp->service_id);
881         sfc_repr_proxy_ports_fini(sa);
882         sfc_repr_proxy_rxq_detach(sa);
883         sfc_repr_proxy_txq_detach(sa);
884
885         sfc_log_init(sa, "done");
886 }
887
888 static int
889 sfc_repr_proxy_do_start_port(struct sfc_adapter *sa,
890                            struct sfc_repr_proxy_port *port)
891 {
892         struct sfc_repr_proxy *rp = &sa->repr_proxy;
893         int rc;
894
895         rc = sfc_repr_proxy_port_rule_insert(sa, port);
896         if (rc != 0)
897                 goto fail_filter_insert;
898
899         if (rp->started) {
900                 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
901                                               SFC_REPR_PROXY_MBOX_START_PORT);
902                 if (rc != 0) {
903                         sfc_err(sa, "failed to start proxy port %u",
904                                 port->repr_id);
905                         goto fail_port_start;
906                 }
907         } else {
908                 port->started = true;
909         }
910
911         return 0;
912
913 fail_port_start:
914         sfc_repr_proxy_port_rule_remove(sa, port);
915 fail_filter_insert:
916         sfc_err(sa, "%s() failed %s", __func__, rte_strerror(rc));
917
918         return rc;
919 }
920
921 static int
922 sfc_repr_proxy_do_stop_port(struct sfc_adapter *sa,
923                           struct sfc_repr_proxy_port *port)
924
925 {
926         struct sfc_repr_proxy *rp = &sa->repr_proxy;
927         int rc;
928
929         if (rp->started) {
930                 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
931                                               SFC_REPR_PROXY_MBOX_STOP_PORT);
932                 if (rc != 0) {
933                         sfc_err(sa, "failed to stop proxy port %u: %s",
934                                 port->repr_id, rte_strerror(rc));
935                         return rc;
936                 }
937         } else {
938                 port->started = false;
939         }
940
941         sfc_repr_proxy_port_rule_remove(sa, port);
942
943         return 0;
944 }
945
946 static bool
947 sfc_repr_proxy_port_enabled(struct sfc_repr_proxy_port *port)
948 {
949         return port->rte_port_id != RTE_MAX_ETHPORTS && port->enabled;
950 }
951
952 static bool
953 sfc_repr_proxy_ports_disabled(struct sfc_repr_proxy *rp)
954 {
955         struct sfc_repr_proxy_port *port;
956
957         TAILQ_FOREACH(port, &rp->ports, entries) {
958                 if (sfc_repr_proxy_port_enabled(port))
959                         return false;
960         }
961
962         return true;
963 }
964
965 int
966 sfc_repr_proxy_start(struct sfc_adapter *sa)
967 {
968         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
969         struct sfc_repr_proxy *rp = &sa->repr_proxy;
970         struct sfc_repr_proxy_port *last_port = NULL;
971         struct sfc_repr_proxy_port *port;
972         int rc;
973
974         sfc_log_init(sa, "entry");
975
976         /* Representor proxy is not started when no representors are started */
977         if (!sfc_repr_available(sas)) {
978                 sfc_log_init(sa, "representors not supported - skip");
979                 return 0;
980         }
981
982         if (sfc_repr_proxy_ports_disabled(rp)) {
983                 sfc_log_init(sa, "no started representor ports - skip");
984                 return 0;
985         }
986
987         rc = sfc_repr_proxy_rxq_start(sa);
988         if (rc != 0)
989                 goto fail_rxq_start;
990
991         rc = sfc_repr_proxy_txq_start(sa);
992         if (rc != 0)
993                 goto fail_txq_start;
994
995         rp->nb_txq = sfc_repr_nb_txq(sas);
996
997         /* Service core may be in "stopped" state, start it */
998         rc = rte_service_lcore_start(rp->service_core_id);
999         if (rc != 0 && rc != -EALREADY) {
1000                 rc = -rc;
1001                 sfc_err(sa, "failed to start service core for %s: %s",
1002                         rte_service_get_name(rp->service_id),
1003                         rte_strerror(rc));
1004                 goto fail_start_core;
1005         }
1006
1007         /* Run the service */
1008         rc = rte_service_component_runstate_set(rp->service_id, 1);
1009         if (rc < 0) {
1010                 rc = -rc;
1011                 sfc_err(sa, "failed to run %s component: %s",
1012                         rte_service_get_name(rp->service_id),
1013                         rte_strerror(rc));
1014                 goto fail_component_runstate_set;
1015         }
1016         rc = rte_service_runstate_set(rp->service_id, 1);
1017         if (rc < 0) {
1018                 rc = -rc;
1019                 sfc_err(sa, "failed to run %s: %s",
1020                         rte_service_get_name(rp->service_id),
1021                         rte_strerror(rc));
1022                 goto fail_runstate_set;
1023         }
1024
1025         TAILQ_FOREACH(port, &rp->ports, entries) {
1026                 if (sfc_repr_proxy_port_enabled(port)) {
1027                         rc = sfc_repr_proxy_do_start_port(sa, port);
1028                         if (rc != 0)
1029                                 goto fail_start_id;
1030
1031                         last_port = port;
1032                 }
1033         }
1034
1035         rc = sfc_repr_proxy_mport_filter_insert(sa);
1036         if (rc != 0)
1037                 goto fail_mport_filter_insert;
1038
1039         rp->started = true;
1040
1041         sfc_log_init(sa, "done");
1042
1043         return 0;
1044
1045 fail_mport_filter_insert:
1046 fail_start_id:
1047         if (last_port != NULL) {
1048                 TAILQ_FOREACH(port, &rp->ports, entries) {
1049                         if (sfc_repr_proxy_port_enabled(port)) {
1050                                 (void)sfc_repr_proxy_do_stop_port(sa, port);
1051                                 if (port == last_port)
1052                                         break;
1053                         }
1054                 }
1055         }
1056
1057         rte_service_runstate_set(rp->service_id, 0);
1058
1059 fail_runstate_set:
1060         rte_service_component_runstate_set(rp->service_id, 0);
1061
1062 fail_component_runstate_set:
1063         /* Service lcore may be shared and we never stop it */
1064
1065 fail_start_core:
1066         sfc_repr_proxy_txq_stop(sa);
1067
1068 fail_txq_start:
1069         sfc_repr_proxy_rxq_stop(sa);
1070
1071 fail_rxq_start:
1072         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
1073         return rc;
1074 }
1075
1076 void
1077 sfc_repr_proxy_stop(struct sfc_adapter *sa)
1078 {
1079         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
1080         struct sfc_repr_proxy *rp = &sa->repr_proxy;
1081         struct sfc_repr_proxy_port *port;
1082         const unsigned int wait_ms_total =
1083                 SFC_REPR_PROXY_ROUTINE_TERMINATE_TIMEOUT_MS;
1084         unsigned int i;
1085         int rc;
1086
1087         sfc_log_init(sa, "entry");
1088
1089         if (!sfc_repr_available(sas)) {
1090                 sfc_log_init(sa, "representors not supported - skip");
1091                 return;
1092         }
1093
1094         if (sfc_repr_proxy_ports_disabled(rp)) {
1095                 sfc_log_init(sa, "no started representor ports - skip");
1096                 return;
1097         }
1098
1099         TAILQ_FOREACH(port, &rp->ports, entries) {
1100                 if (sfc_repr_proxy_port_enabled(port)) {
1101                         rc = sfc_repr_proxy_do_stop_port(sa, port);
1102                         if (rc != 0) {
1103                                 sfc_err(sa,
1104                                         "failed to stop representor proxy port %u: %s",
1105                                         port->repr_id, rte_strerror(rc));
1106                         }
1107                 }
1108         }
1109
1110         sfc_repr_proxy_mport_filter_remove(sa);
1111
1112         rc = rte_service_runstate_set(rp->service_id, 0);
1113         if (rc < 0) {
1114                 sfc_err(sa, "failed to stop %s: %s",
1115                         rte_service_get_name(rp->service_id),
1116                         rte_strerror(-rc));
1117         }
1118
1119         rc = rte_service_component_runstate_set(rp->service_id, 0);
1120         if (rc < 0) {
1121                 sfc_err(sa, "failed to stop %s component: %s",
1122                         rte_service_get_name(rp->service_id),
1123                         rte_strerror(-rc));
1124         }
1125
1126         /* Service lcore may be shared and we never stop it */
1127
1128         /*
1129          * Wait for the representor proxy routine to finish the last iteration.
1130          * Give up on timeout.
1131          */
1132         for (i = 0; i < wait_ms_total; i++) {
1133                 if (rte_service_may_be_active(rp->service_id) == 0)
1134                         break;
1135
1136                 rte_delay_ms(1);
1137         }
1138
1139         sfc_repr_proxy_rxq_stop(sa);
1140         sfc_repr_proxy_txq_stop(sa);
1141
1142         rp->started = false;
1143
1144         sfc_log_init(sa, "done");
1145 }
1146
1147 int
1148 sfc_repr_proxy_add_port(uint16_t pf_port_id, uint16_t repr_id,
1149                         uint16_t rte_port_id, const efx_mport_sel_t *mport_sel)
1150 {
1151         struct sfc_repr_proxy_port *port;
1152         struct sfc_repr_proxy *rp;
1153         struct sfc_adapter *sa;
1154         int rc;
1155
1156         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1157         rp = sfc_repr_proxy_by_adapter(sa);
1158
1159         sfc_log_init(sa, "entry");
1160         TAILQ_FOREACH(port, &rp->ports, entries) {
1161                 if (port->rte_port_id == rte_port_id) {
1162                         rc = EEXIST;
1163                         sfc_err(sa, "%s() failed: port exists", __func__);
1164                         goto fail_port_exists;
1165                 }
1166         }
1167
1168         port = rte_zmalloc("sfc-repr-proxy-port", sizeof(*port),
1169                            sa->socket_id);
1170         if (port == NULL) {
1171                 rc = ENOMEM;
1172                 sfc_err(sa, "failed to alloc memory for proxy port");
1173                 goto fail_alloc_port;
1174         }
1175
1176         rc = efx_mae_mport_id_by_selector(sa->nic, mport_sel,
1177                                           &port->egress_mport);
1178         if (rc != 0) {
1179                 sfc_err(sa,
1180                         "failed get MAE mport id by selector (repr_id %u): %s",
1181                         repr_id, rte_strerror(rc));
1182                 goto fail_mport_id;
1183         }
1184
1185         port->rte_port_id = rte_port_id;
1186         port->repr_id = repr_id;
1187
1188         if (rp->started) {
1189                 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
1190                                               SFC_REPR_PROXY_MBOX_ADD_PORT);
1191                 if (rc != 0) {
1192                         sfc_err(sa, "failed to add proxy port %u",
1193                                 port->repr_id);
1194                         goto fail_port_add;
1195                 }
1196         } else {
1197                 TAILQ_INSERT_TAIL(&rp->ports, port, entries);
1198         }
1199
1200         sfc_log_init(sa, "done");
1201         sfc_put_adapter(sa);
1202
1203         return 0;
1204
1205 fail_port_add:
1206 fail_mport_id:
1207         rte_free(port);
1208 fail_alloc_port:
1209 fail_port_exists:
1210         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
1211         sfc_put_adapter(sa);
1212
1213         return rc;
1214 }
1215
1216 int
1217 sfc_repr_proxy_del_port(uint16_t pf_port_id, uint16_t repr_id)
1218 {
1219         struct sfc_repr_proxy_port *port;
1220         struct sfc_repr_proxy *rp;
1221         struct sfc_adapter *sa;
1222         int rc;
1223
1224         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1225         rp = sfc_repr_proxy_by_adapter(sa);
1226
1227         sfc_log_init(sa, "entry");
1228
1229         port = sfc_repr_proxy_find_port(rp, repr_id);
1230         if (port == NULL) {
1231                 sfc_err(sa, "failed: no such port");
1232                 rc = ENOENT;
1233                 goto fail_no_port;
1234         }
1235
1236         if (rp->started) {
1237                 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
1238                                               SFC_REPR_PROXY_MBOX_DEL_PORT);
1239                 if (rc != 0) {
1240                         sfc_err(sa, "failed to remove proxy port %u",
1241                                 port->repr_id);
1242                         goto fail_port_remove;
1243                 }
1244         } else {
1245                 TAILQ_REMOVE(&rp->ports, port, entries);
1246         }
1247
1248         rte_free(port);
1249
1250         sfc_log_init(sa, "done");
1251
1252         sfc_put_adapter(sa);
1253
1254         return 0;
1255
1256 fail_port_remove:
1257 fail_no_port:
1258         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
1259         sfc_put_adapter(sa);
1260
1261         return rc;
1262 }
1263
1264 int
1265 sfc_repr_proxy_add_rxq(uint16_t pf_port_id, uint16_t repr_id,
1266                        uint16_t queue_id, struct rte_ring *rx_ring,
1267                        struct rte_mempool *mp)
1268 {
1269         struct sfc_repr_proxy_port *port;
1270         struct sfc_repr_proxy_rxq *rxq;
1271         struct sfc_repr_proxy *rp;
1272         struct sfc_adapter *sa;
1273
1274         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1275         rp = sfc_repr_proxy_by_adapter(sa);
1276
1277         sfc_log_init(sa, "entry");
1278
1279         port = sfc_repr_proxy_find_port(rp, repr_id);
1280         if (port == NULL) {
1281                 sfc_err(sa, "%s() failed: no such port", __func__);
1282                 return ENOENT;
1283         }
1284
1285         rxq = &port->rxq[queue_id];
1286         if (rp->dp_rxq[queue_id].mp != NULL && rp->dp_rxq[queue_id].mp != mp) {
1287                 sfc_err(sa, "multiple mempools per queue are not supported");
1288                 sfc_put_adapter(sa);
1289                 return ENOTSUP;
1290         }
1291
1292         rxq->ring = rx_ring;
1293         rxq->mb_pool = mp;
1294         rp->dp_rxq[queue_id].mp = mp;
1295         rp->dp_rxq[queue_id].ref_count++;
1296
1297         sfc_log_init(sa, "done");
1298         sfc_put_adapter(sa);
1299
1300         return 0;
1301 }
1302
1303 void
1304 sfc_repr_proxy_del_rxq(uint16_t pf_port_id, uint16_t repr_id,
1305                        uint16_t queue_id)
1306 {
1307         struct sfc_repr_proxy_port *port;
1308         struct sfc_repr_proxy_rxq *rxq;
1309         struct sfc_repr_proxy *rp;
1310         struct sfc_adapter *sa;
1311
1312         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1313         rp = sfc_repr_proxy_by_adapter(sa);
1314
1315         sfc_log_init(sa, "entry");
1316
1317         port = sfc_repr_proxy_find_port(rp, repr_id);
1318         if (port == NULL) {
1319                 sfc_err(sa, "%s() failed: no such port", __func__);
1320                 return;
1321         }
1322
1323         rxq = &port->rxq[queue_id];
1324
1325         rxq->ring = NULL;
1326         rxq->mb_pool = NULL;
1327         rp->dp_rxq[queue_id].ref_count--;
1328         if (rp->dp_rxq[queue_id].ref_count == 0)
1329                 rp->dp_rxq[queue_id].mp = NULL;
1330
1331         sfc_log_init(sa, "done");
1332         sfc_put_adapter(sa);
1333 }
1334
1335 int
1336 sfc_repr_proxy_add_txq(uint16_t pf_port_id, uint16_t repr_id,
1337                        uint16_t queue_id, struct rte_ring *tx_ring,
1338                        efx_mport_id_t *egress_mport)
1339 {
1340         struct sfc_repr_proxy_port *port;
1341         struct sfc_repr_proxy_txq *txq;
1342         struct sfc_repr_proxy *rp;
1343         struct sfc_adapter *sa;
1344
1345         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1346         rp = sfc_repr_proxy_by_adapter(sa);
1347
1348         sfc_log_init(sa, "entry");
1349
1350         port = sfc_repr_proxy_find_port(rp, repr_id);
1351         if (port == NULL) {
1352                 sfc_err(sa, "%s() failed: no such port", __func__);
1353                 return ENOENT;
1354         }
1355
1356         txq = &port->txq[queue_id];
1357
1358         txq->ring = tx_ring;
1359
1360         *egress_mport = port->egress_mport;
1361
1362         sfc_log_init(sa, "done");
1363         sfc_put_adapter(sa);
1364
1365         return 0;
1366 }
1367
1368 void
1369 sfc_repr_proxy_del_txq(uint16_t pf_port_id, uint16_t repr_id,
1370                        uint16_t queue_id)
1371 {
1372         struct sfc_repr_proxy_port *port;
1373         struct sfc_repr_proxy_txq *txq;
1374         struct sfc_repr_proxy *rp;
1375         struct sfc_adapter *sa;
1376
1377         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1378         rp = sfc_repr_proxy_by_adapter(sa);
1379
1380         sfc_log_init(sa, "entry");
1381
1382         port = sfc_repr_proxy_find_port(rp, repr_id);
1383         if (port == NULL) {
1384                 sfc_err(sa, "%s() failed: no such port", __func__);
1385                 return;
1386         }
1387
1388         txq = &port->txq[queue_id];
1389
1390         txq->ring = NULL;
1391
1392         sfc_log_init(sa, "done");
1393         sfc_put_adapter(sa);
1394 }
1395
1396 int
1397 sfc_repr_proxy_start_repr(uint16_t pf_port_id, uint16_t repr_id)
1398 {
1399         bool proxy_start_required = false;
1400         struct sfc_repr_proxy_port *port;
1401         struct sfc_repr_proxy *rp;
1402         struct sfc_adapter *sa;
1403         int rc;
1404
1405         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1406         rp = sfc_repr_proxy_by_adapter(sa);
1407
1408         sfc_log_init(sa, "entry");
1409
1410         port = sfc_repr_proxy_find_port(rp, repr_id);
1411         if (port == NULL) {
1412                 sfc_err(sa, "%s() failed: no such port", __func__);
1413                 rc = ENOENT;
1414                 goto fail_not_found;
1415         }
1416
1417         if (port->enabled) {
1418                 rc = EALREADY;
1419                 sfc_err(sa, "failed: repr %u proxy port already started",
1420                         repr_id);
1421                 goto fail_already_started;
1422         }
1423
1424         if (sa->state == SFC_ETHDEV_STARTED) {
1425                 if (sfc_repr_proxy_ports_disabled(rp)) {
1426                         proxy_start_required = true;
1427                 } else {
1428                         rc = sfc_repr_proxy_do_start_port(sa, port);
1429                         if (rc != 0) {
1430                                 sfc_err(sa,
1431                                         "failed to start repr %u proxy port",
1432                                         repr_id);
1433                                 goto fail_start_id;
1434                         }
1435                 }
1436         }
1437
1438         port->enabled = true;
1439
1440         if (proxy_start_required) {
1441                 rc = sfc_repr_proxy_start(sa);
1442                 if (rc != 0) {
1443                         sfc_err(sa, "failed to start proxy");
1444                         goto fail_proxy_start;
1445                 }
1446         }
1447
1448         sfc_log_init(sa, "done");
1449         sfc_put_adapter(sa);
1450
1451         return 0;
1452
1453 fail_proxy_start:
1454         port->enabled = false;
1455
1456 fail_start_id:
1457 fail_already_started:
1458 fail_not_found:
1459         sfc_err(sa, "failed to start repr %u proxy port: %s", repr_id,
1460                 rte_strerror(rc));
1461         sfc_put_adapter(sa);
1462
1463         return rc;
1464 }
1465
1466 int
1467 sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id)
1468 {
1469         struct sfc_repr_proxy_port *port;
1470         struct sfc_repr_proxy_port *p;
1471         struct sfc_repr_proxy *rp;
1472         struct sfc_adapter *sa;
1473         int rc;
1474
1475         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1476         rp = sfc_repr_proxy_by_adapter(sa);
1477
1478         sfc_log_init(sa, "entry");
1479
1480         port = sfc_repr_proxy_find_port(rp, repr_id);
1481         if (port == NULL) {
1482                 sfc_err(sa, "%s() failed: no such port", __func__);
1483                 return ENOENT;
1484         }
1485
1486         if (!port->enabled) {
1487                 sfc_log_init(sa, "repr %u proxy port is not started - skip",
1488                              repr_id);
1489                 sfc_put_adapter(sa);
1490                 return 0;
1491         }
1492
1493         if (sa->state == SFC_ETHDEV_STARTED) {
1494                 bool last_enabled = true;
1495
1496                 TAILQ_FOREACH(p, &rp->ports, entries) {
1497                         if (p == port)
1498                                 continue;
1499
1500                         if (sfc_repr_proxy_port_enabled(p)) {
1501                                 last_enabled = false;
1502                                 break;
1503                         }
1504                 }
1505
1506                 rc = 0;
1507                 if (last_enabled)
1508                         sfc_repr_proxy_stop(sa);
1509                 else
1510                         rc = sfc_repr_proxy_do_stop_port(sa, port);
1511
1512                 if (rc != 0) {
1513                         sfc_err(sa,
1514                                 "failed to stop representor proxy TxQ %u: %s",
1515                                 repr_id, rte_strerror(rc));
1516                         sfc_put_adapter(sa);
1517                         return rc;
1518                 }
1519         }
1520
1521         port->enabled = false;
1522
1523         sfc_log_init(sa, "done");
1524         sfc_put_adapter(sa);
1525
1526         return 0;
1527 }