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