net/sfc: implement representor Rx queue start/stop
[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
21 /**
22  * Amount of time to wait for the representor proxy routine (which is
23  * running on a service core) to handle a request sent via mbox.
24  */
25 #define SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS     1000
26
27 static struct sfc_repr_proxy *
28 sfc_repr_proxy_by_adapter(struct sfc_adapter *sa)
29 {
30         return &sa->repr_proxy;
31 }
32
33 static struct sfc_adapter *
34 sfc_get_adapter_by_pf_port_id(uint16_t pf_port_id)
35 {
36         struct rte_eth_dev *dev;
37         struct sfc_adapter *sa;
38
39         SFC_ASSERT(pf_port_id < RTE_MAX_ETHPORTS);
40
41         dev = &rte_eth_devices[pf_port_id];
42         sa = sfc_adapter_by_eth_dev(dev);
43
44         sfc_adapter_lock(sa);
45
46         return sa;
47 }
48
49 static void
50 sfc_put_adapter(struct sfc_adapter *sa)
51 {
52         sfc_adapter_unlock(sa);
53 }
54
55 static int
56 sfc_repr_proxy_mbox_send(struct sfc_repr_proxy_mbox *mbox,
57                          struct sfc_repr_proxy_port *port,
58                          enum sfc_repr_proxy_mbox_op op)
59 {
60         const unsigned int wait_ms = SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS;
61         unsigned int i;
62
63         mbox->op = op;
64         mbox->port = port;
65         mbox->ack = false;
66
67         /*
68          * Release ordering enforces marker set after data is populated.
69          * Paired with acquire ordering in sfc_repr_proxy_mbox_handle().
70          */
71         __atomic_store_n(&mbox->write_marker, true, __ATOMIC_RELEASE);
72
73         /*
74          * Wait for the representor routine to process the request.
75          * Give up on timeout.
76          */
77         for (i = 0; i < wait_ms; i++) {
78                 /*
79                  * Paired with release ordering in sfc_repr_proxy_mbox_handle()
80                  * on acknowledge write.
81                  */
82                 if (__atomic_load_n(&mbox->ack, __ATOMIC_ACQUIRE))
83                         break;
84
85                 rte_delay_ms(1);
86         }
87
88         if (i == wait_ms) {
89                 SFC_GENERIC_LOG(ERR,
90                         "%s() failed to wait for representor proxy routine ack",
91                         __func__);
92                 return ETIMEDOUT;
93         }
94
95         return 0;
96 }
97
98 static void
99 sfc_repr_proxy_mbox_handle(struct sfc_repr_proxy *rp)
100 {
101         struct sfc_repr_proxy_mbox *mbox = &rp->mbox;
102
103         /*
104          * Paired with release ordering in sfc_repr_proxy_mbox_send()
105          * on marker set.
106          */
107         if (!__atomic_load_n(&mbox->write_marker, __ATOMIC_ACQUIRE))
108                 return;
109
110         mbox->write_marker = false;
111
112         switch (mbox->op) {
113         case SFC_REPR_PROXY_MBOX_ADD_PORT:
114                 TAILQ_INSERT_TAIL(&rp->ports, mbox->port, entries);
115                 break;
116         case SFC_REPR_PROXY_MBOX_DEL_PORT:
117                 TAILQ_REMOVE(&rp->ports, mbox->port, entries);
118                 break;
119         default:
120                 SFC_ASSERT(0);
121                 return;
122         }
123
124         /*
125          * Paired with acquire ordering in sfc_repr_proxy_mbox_send()
126          * on acknowledge read.
127          */
128         __atomic_store_n(&mbox->ack, true, __ATOMIC_RELEASE);
129 }
130
131 static int32_t
132 sfc_repr_proxy_routine(void *arg)
133 {
134         struct sfc_repr_proxy *rp = arg;
135
136         sfc_repr_proxy_mbox_handle(rp);
137
138         return 0;
139 }
140
141 static int
142 sfc_repr_proxy_rxq_attach(struct sfc_adapter *sa)
143 {
144         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
145         struct sfc_repr_proxy *rp = &sa->repr_proxy;
146         unsigned int i;
147
148         sfc_log_init(sa, "entry");
149
150         for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
151                 sfc_sw_index_t sw_index = sfc_repr_rxq_sw_index(sas, i);
152
153                 rp->dp_rxq[i].sw_index = sw_index;
154         }
155
156         sfc_log_init(sa, "done");
157
158         return 0;
159 }
160
161 static void
162 sfc_repr_proxy_rxq_detach(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_rxq(sas); i++)
171                 rp->dp_rxq[i].sw_index = 0;
172
173         sfc_log_init(sa, "done");
174 }
175
176 static int
177 sfc_repr_proxy_rxq_init(struct sfc_adapter *sa,
178                         struct sfc_repr_proxy_dp_rxq *rxq)
179 {
180         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
181         uint16_t nb_rx_desc = SFC_REPR_PROXY_RX_DESC_COUNT;
182         struct sfc_rxq_info *rxq_info;
183         struct rte_eth_rxconf rxconf = {
184                 .rx_free_thresh = SFC_REPR_PROXY_RXQ_REFILL_LEVEL,
185                 .rx_drop_en = 1,
186         };
187         int rc;
188
189         sfc_log_init(sa, "entry");
190
191         rxq_info = &sas->rxq_info[rxq->sw_index];
192         if (rxq_info->state & SFC_RXQ_INITIALIZED) {
193                 sfc_log_init(sa, "RxQ is already initialized - skip");
194                 return 0;
195         }
196
197         nb_rx_desc = RTE_MIN(nb_rx_desc, sa->rxq_max_entries);
198         nb_rx_desc = RTE_MAX(nb_rx_desc, sa->rxq_min_entries);
199
200         rc = sfc_rx_qinit_info(sa, rxq->sw_index, EFX_RXQ_FLAG_INGRESS_MPORT);
201         if (rc != 0) {
202                 sfc_err(sa, "failed to init representor proxy RxQ info");
203                 goto fail_repr_rxq_init_info;
204         }
205
206         rc = sfc_rx_qinit(sa, rxq->sw_index, nb_rx_desc, sa->socket_id, &rxconf,
207                           rxq->mp);
208         if (rc != 0) {
209                 sfc_err(sa, "failed to init representor proxy RxQ");
210                 goto fail_repr_rxq_init;
211         }
212
213         sfc_log_init(sa, "done");
214
215         return 0;
216
217 fail_repr_rxq_init:
218 fail_repr_rxq_init_info:
219         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
220
221         return rc;
222 }
223
224 static void
225 sfc_repr_proxy_rxq_fini(struct sfc_adapter *sa)
226 {
227         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
228         struct sfc_repr_proxy *rp = &sa->repr_proxy;
229         struct sfc_rxq_info *rxq_info;
230         unsigned int i;
231
232         sfc_log_init(sa, "entry");
233
234         if (!sfc_repr_available(sas)) {
235                 sfc_log_init(sa, "representors not supported - skip");
236                 return;
237         }
238
239         for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
240                 struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
241
242                 rxq_info = &sas->rxq_info[rxq->sw_index];
243                 if (rxq_info->state != SFC_RXQ_INITIALIZED) {
244                         sfc_log_init(sa,
245                                 "representor RxQ %u is already finalized - skip",
246                                 i);
247                         continue;
248                 }
249
250                 sfc_rx_qfini(sa, rxq->sw_index);
251         }
252
253         sfc_log_init(sa, "done");
254 }
255
256 static void
257 sfc_repr_proxy_rxq_stop(struct sfc_adapter *sa)
258 {
259         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
260         unsigned int i;
261
262         sfc_log_init(sa, "entry");
263
264         for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
265                 sfc_rx_qstop(sa, sa->repr_proxy.dp_rxq[i].sw_index);
266
267         sfc_repr_proxy_rxq_fini(sa);
268
269         sfc_log_init(sa, "done");
270 }
271
272 static int
273 sfc_repr_proxy_rxq_start(struct sfc_adapter *sa)
274 {
275         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
276         struct sfc_repr_proxy *rp = &sa->repr_proxy;
277         unsigned int i;
278         int rc;
279
280         sfc_log_init(sa, "entry");
281
282         if (!sfc_repr_available(sas)) {
283                 sfc_log_init(sa, "representors not supported - skip");
284                 return 0;
285         }
286
287         for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
288                 struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
289
290                 rc = sfc_repr_proxy_rxq_init(sa, rxq);
291                 if (rc != 0) {
292                         sfc_err(sa, "failed to init representor proxy RxQ %u",
293                                 i);
294                         goto fail_init;
295                 }
296
297                 rc = sfc_rx_qstart(sa, rxq->sw_index);
298                 if (rc != 0) {
299                         sfc_err(sa, "failed to start representor proxy RxQ %u",
300                                 i);
301                         goto fail_start;
302                 }
303         }
304
305         sfc_log_init(sa, "done");
306
307         return 0;
308
309 fail_start:
310 fail_init:
311         sfc_repr_proxy_rxq_stop(sa);
312         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
313         return rc;
314 }
315
316 static int
317 sfc_repr_proxy_ports_init(struct sfc_adapter *sa)
318 {
319         struct sfc_repr_proxy *rp = &sa->repr_proxy;
320         int rc;
321
322         sfc_log_init(sa, "entry");
323
324         rc = efx_mcdi_mport_alloc_alias(sa->nic, &rp->mport_alias, NULL);
325         if (rc != 0) {
326                 sfc_err(sa, "failed to alloc mport alias: %s",
327                         rte_strerror(rc));
328                 goto fail_alloc_mport_alias;
329         }
330
331         TAILQ_INIT(&rp->ports);
332
333         sfc_log_init(sa, "done");
334
335         return 0;
336
337 fail_alloc_mport_alias:
338
339         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
340         return rc;
341 }
342
343 void
344 sfc_repr_proxy_pre_detach(struct sfc_adapter *sa)
345 {
346         struct sfc_repr_proxy *rp = &sa->repr_proxy;
347         bool close_ports[RTE_MAX_ETHPORTS] = {0};
348         struct sfc_repr_proxy_port *port;
349         unsigned int i;
350
351         SFC_ASSERT(!sfc_adapter_is_locked(sa));
352
353         sfc_adapter_lock(sa);
354
355         if (sfc_repr_available(sfc_sa2shared(sa))) {
356                 TAILQ_FOREACH(port, &rp->ports, entries)
357                         close_ports[port->rte_port_id] = true;
358         } else {
359                 sfc_log_init(sa, "representors not supported - skip");
360         }
361
362         sfc_adapter_unlock(sa);
363
364         for (i = 0; i < RTE_DIM(close_ports); i++) {
365                 if (close_ports[i]) {
366                         rte_eth_dev_stop(i);
367                         rte_eth_dev_close(i);
368                 }
369         }
370 }
371
372 static void
373 sfc_repr_proxy_ports_fini(struct sfc_adapter *sa)
374 {
375         struct sfc_repr_proxy *rp = &sa->repr_proxy;
376
377         efx_mae_mport_free(sa->nic, &rp->mport_alias);
378 }
379
380 int
381 sfc_repr_proxy_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         struct rte_service_spec service;
386         uint32_t cid;
387         uint32_t sid;
388         int rc;
389
390         sfc_log_init(sa, "entry");
391
392         if (!sfc_repr_available(sas)) {
393                 sfc_log_init(sa, "representors not supported - skip");
394                 return 0;
395         }
396
397         rc = sfc_repr_proxy_rxq_attach(sa);
398         if (rc != 0)
399                 goto fail_rxq_attach;
400
401         rc = sfc_repr_proxy_ports_init(sa);
402         if (rc != 0)
403                 goto fail_ports_init;
404
405         cid = sfc_get_service_lcore(sa->socket_id);
406         if (cid == RTE_MAX_LCORE && sa->socket_id != SOCKET_ID_ANY) {
407                 /* Warn and try to allocate on any NUMA node */
408                 sfc_warn(sa,
409                         "repr proxy: unable to get service lcore at socket %d",
410                         sa->socket_id);
411
412                 cid = sfc_get_service_lcore(SOCKET_ID_ANY);
413         }
414         if (cid == RTE_MAX_LCORE) {
415                 rc = ENOTSUP;
416                 sfc_err(sa, "repr proxy: failed to get service lcore");
417                 goto fail_get_service_lcore;
418         }
419
420         memset(&service, 0, sizeof(service));
421         snprintf(service.name, sizeof(service.name),
422                  "net_sfc_%hu_repr_proxy", sfc_sa2shared(sa)->port_id);
423         service.socket_id = rte_lcore_to_socket_id(cid);
424         service.callback = sfc_repr_proxy_routine;
425         service.callback_userdata = rp;
426
427         rc = rte_service_component_register(&service, &sid);
428         if (rc != 0) {
429                 rc = ENOEXEC;
430                 sfc_err(sa, "repr proxy: failed to register service component");
431                 goto fail_register;
432         }
433
434         rc = rte_service_map_lcore_set(sid, cid, 1);
435         if (rc != 0) {
436                 rc = -rc;
437                 sfc_err(sa, "repr proxy: failed to map lcore");
438                 goto fail_map_lcore;
439         }
440
441         rp->service_core_id = cid;
442         rp->service_id = sid;
443
444         sfc_log_init(sa, "done");
445
446         return 0;
447
448 fail_map_lcore:
449         rte_service_component_unregister(sid);
450
451 fail_register:
452         /*
453          * No need to rollback service lcore get since
454          * it just makes socket_id based search and remembers it.
455          */
456
457 fail_get_service_lcore:
458         sfc_repr_proxy_ports_fini(sa);
459
460 fail_ports_init:
461         sfc_repr_proxy_rxq_detach(sa);
462
463 fail_rxq_attach:
464         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
465         return rc;
466 }
467
468 void
469 sfc_repr_proxy_detach(struct sfc_adapter *sa)
470 {
471         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
472         struct sfc_repr_proxy *rp = &sa->repr_proxy;
473
474         sfc_log_init(sa, "entry");
475
476         if (!sfc_repr_available(sas)) {
477                 sfc_log_init(sa, "representors not supported - skip");
478                 return;
479         }
480
481         rte_service_map_lcore_set(rp->service_id, rp->service_core_id, 0);
482         rte_service_component_unregister(rp->service_id);
483         sfc_repr_proxy_ports_fini(sa);
484         sfc_repr_proxy_rxq_detach(sa);
485
486         sfc_log_init(sa, "done");
487 }
488
489 int
490 sfc_repr_proxy_start(struct sfc_adapter *sa)
491 {
492         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
493         struct sfc_repr_proxy *rp = &sa->repr_proxy;
494         int rc;
495
496         sfc_log_init(sa, "entry");
497
498         /*
499          * The condition to start the proxy is insufficient. It will be
500          * complemented with representor port start/stop support.
501          */
502         if (!sfc_repr_available(sas)) {
503                 sfc_log_init(sa, "representors not supported - skip");
504                 return 0;
505         }
506
507         rc = sfc_repr_proxy_rxq_start(sa);
508         if (rc != 0)
509                 goto fail_rxq_start;
510
511         /* Service core may be in "stopped" state, start it */
512         rc = rte_service_lcore_start(rp->service_core_id);
513         if (rc != 0 && rc != -EALREADY) {
514                 rc = -rc;
515                 sfc_err(sa, "failed to start service core for %s: %s",
516                         rte_service_get_name(rp->service_id),
517                         rte_strerror(rc));
518                 goto fail_start_core;
519         }
520
521         /* Run the service */
522         rc = rte_service_component_runstate_set(rp->service_id, 1);
523         if (rc < 0) {
524                 rc = -rc;
525                 sfc_err(sa, "failed to run %s component: %s",
526                         rte_service_get_name(rp->service_id),
527                         rte_strerror(rc));
528                 goto fail_component_runstate_set;
529         }
530         rc = rte_service_runstate_set(rp->service_id, 1);
531         if (rc < 0) {
532                 rc = -rc;
533                 sfc_err(sa, "failed to run %s: %s",
534                         rte_service_get_name(rp->service_id),
535                         rte_strerror(rc));
536                 goto fail_runstate_set;
537         }
538
539         rp->started = true;
540
541         sfc_log_init(sa, "done");
542
543         return 0;
544
545 fail_runstate_set:
546         rte_service_component_runstate_set(rp->service_id, 0);
547
548 fail_component_runstate_set:
549         /* Service lcore may be shared and we never stop it */
550
551 fail_start_core:
552         sfc_repr_proxy_rxq_stop(sa);
553
554 fail_rxq_start:
555         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
556         return rc;
557 }
558
559 void
560 sfc_repr_proxy_stop(struct sfc_adapter *sa)
561 {
562         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
563         struct sfc_repr_proxy *rp = &sa->repr_proxy;
564         int rc;
565
566         sfc_log_init(sa, "entry");
567
568         if (!sfc_repr_available(sas)) {
569                 sfc_log_init(sa, "representors not supported - skip");
570                 return;
571         }
572
573         rc = rte_service_runstate_set(rp->service_id, 0);
574         if (rc < 0) {
575                 sfc_err(sa, "failed to stop %s: %s",
576                         rte_service_get_name(rp->service_id),
577                         rte_strerror(-rc));
578         }
579
580         rc = rte_service_component_runstate_set(rp->service_id, 0);
581         if (rc < 0) {
582                 sfc_err(sa, "failed to stop %s component: %s",
583                         rte_service_get_name(rp->service_id),
584                         rte_strerror(-rc));
585         }
586
587         /* Service lcore may be shared and we never stop it */
588
589         sfc_repr_proxy_rxq_stop(sa);
590
591         rp->started = false;
592
593         sfc_log_init(sa, "done");
594 }
595
596 static struct sfc_repr_proxy_port *
597 sfc_repr_proxy_find_port(struct sfc_repr_proxy *rp, uint16_t repr_id)
598 {
599         struct sfc_repr_proxy_port *port;
600
601         TAILQ_FOREACH(port, &rp->ports, entries) {
602                 if (port->repr_id == repr_id)
603                         return port;
604         }
605
606         return NULL;
607 }
608
609 int
610 sfc_repr_proxy_add_port(uint16_t pf_port_id, uint16_t repr_id,
611                         uint16_t rte_port_id, const efx_mport_sel_t *mport_sel)
612 {
613         struct sfc_repr_proxy_port *port;
614         struct sfc_repr_proxy *rp;
615         struct sfc_adapter *sa;
616         int rc;
617
618         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
619         rp = sfc_repr_proxy_by_adapter(sa);
620
621         sfc_log_init(sa, "entry");
622         TAILQ_FOREACH(port, &rp->ports, entries) {
623                 if (port->rte_port_id == rte_port_id) {
624                         rc = EEXIST;
625                         sfc_err(sa, "%s() failed: port exists", __func__);
626                         goto fail_port_exists;
627                 }
628         }
629
630         port = rte_zmalloc("sfc-repr-proxy-port", sizeof(*port),
631                            sa->socket_id);
632         if (port == NULL) {
633                 rc = ENOMEM;
634                 sfc_err(sa, "failed to alloc memory for proxy port");
635                 goto fail_alloc_port;
636         }
637
638         rc = efx_mae_mport_id_by_selector(sa->nic, mport_sel,
639                                           &port->egress_mport);
640         if (rc != 0) {
641                 sfc_err(sa,
642                         "failed get MAE mport id by selector (repr_id %u): %s",
643                         repr_id, rte_strerror(rc));
644                 goto fail_mport_id;
645         }
646
647         port->rte_port_id = rte_port_id;
648         port->repr_id = repr_id;
649
650         if (rp->started) {
651                 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
652                                               SFC_REPR_PROXY_MBOX_ADD_PORT);
653                 if (rc != 0) {
654                         sfc_err(sa, "failed to add proxy port %u",
655                                 port->repr_id);
656                         goto fail_port_add;
657                 }
658         } else {
659                 TAILQ_INSERT_TAIL(&rp->ports, port, entries);
660         }
661
662         sfc_log_init(sa, "done");
663         sfc_put_adapter(sa);
664
665         return 0;
666
667 fail_port_add:
668 fail_mport_id:
669         rte_free(port);
670 fail_alloc_port:
671 fail_port_exists:
672         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
673         sfc_put_adapter(sa);
674
675         return rc;
676 }
677
678 int
679 sfc_repr_proxy_del_port(uint16_t pf_port_id, uint16_t repr_id)
680 {
681         struct sfc_repr_proxy_port *port;
682         struct sfc_repr_proxy *rp;
683         struct sfc_adapter *sa;
684         int rc;
685
686         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
687         rp = sfc_repr_proxy_by_adapter(sa);
688
689         sfc_log_init(sa, "entry");
690
691         port = sfc_repr_proxy_find_port(rp, repr_id);
692         if (port == NULL) {
693                 sfc_err(sa, "failed: no such port");
694                 rc = ENOENT;
695                 goto fail_no_port;
696         }
697
698         if (rp->started) {
699                 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
700                                               SFC_REPR_PROXY_MBOX_DEL_PORT);
701                 if (rc != 0) {
702                         sfc_err(sa, "failed to remove proxy port %u",
703                                 port->repr_id);
704                         goto fail_port_remove;
705                 }
706         } else {
707                 TAILQ_REMOVE(&rp->ports, port, entries);
708         }
709
710         rte_free(port);
711
712         sfc_log_init(sa, "done");
713
714         sfc_put_adapter(sa);
715
716         return 0;
717
718 fail_port_remove:
719 fail_no_port:
720         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
721         sfc_put_adapter(sa);
722
723         return rc;
724 }
725
726 int
727 sfc_repr_proxy_add_rxq(uint16_t pf_port_id, uint16_t repr_id,
728                        uint16_t queue_id, struct rte_ring *rx_ring,
729                        struct rte_mempool *mp)
730 {
731         struct sfc_repr_proxy_port *port;
732         struct sfc_repr_proxy_rxq *rxq;
733         struct sfc_repr_proxy *rp;
734         struct sfc_adapter *sa;
735
736         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
737         rp = sfc_repr_proxy_by_adapter(sa);
738
739         sfc_log_init(sa, "entry");
740
741         port = sfc_repr_proxy_find_port(rp, repr_id);
742         if (port == NULL) {
743                 sfc_err(sa, "%s() failed: no such port", __func__);
744                 return ENOENT;
745         }
746
747         rxq = &port->rxq[queue_id];
748         if (rp->dp_rxq[queue_id].mp != NULL && rp->dp_rxq[queue_id].mp != mp) {
749                 sfc_err(sa, "multiple mempools per queue are not supported");
750                 sfc_put_adapter(sa);
751                 return ENOTSUP;
752         }
753
754         rxq->ring = rx_ring;
755         rxq->mb_pool = mp;
756         rp->dp_rxq[queue_id].mp = mp;
757         rp->dp_rxq[queue_id].ref_count++;
758
759         sfc_log_init(sa, "done");
760         sfc_put_adapter(sa);
761
762         return 0;
763 }
764
765 void
766 sfc_repr_proxy_del_rxq(uint16_t pf_port_id, uint16_t repr_id,
767                        uint16_t queue_id)
768 {
769         struct sfc_repr_proxy_port *port;
770         struct sfc_repr_proxy_rxq *rxq;
771         struct sfc_repr_proxy *rp;
772         struct sfc_adapter *sa;
773
774         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
775         rp = sfc_repr_proxy_by_adapter(sa);
776
777         sfc_log_init(sa, "entry");
778
779         port = sfc_repr_proxy_find_port(rp, repr_id);
780         if (port == NULL) {
781                 sfc_err(sa, "%s() failed: no such port", __func__);
782                 return;
783         }
784
785         rxq = &port->rxq[queue_id];
786
787         rxq->ring = NULL;
788         rxq->mb_pool = NULL;
789         rp->dp_rxq[queue_id].ref_count--;
790         if (rp->dp_rxq[queue_id].ref_count == 0)
791                 rp->dp_rxq[queue_id].mp = NULL;
792
793         sfc_log_init(sa, "done");
794         sfc_put_adapter(sa);
795 }
796
797 int
798 sfc_repr_proxy_add_txq(uint16_t pf_port_id, uint16_t repr_id,
799                        uint16_t queue_id, struct rte_ring *tx_ring,
800                        efx_mport_id_t *egress_mport)
801 {
802         struct sfc_repr_proxy_port *port;
803         struct sfc_repr_proxy_txq *txq;
804         struct sfc_repr_proxy *rp;
805         struct sfc_adapter *sa;
806
807         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
808         rp = sfc_repr_proxy_by_adapter(sa);
809
810         sfc_log_init(sa, "entry");
811
812         port = sfc_repr_proxy_find_port(rp, repr_id);
813         if (port == NULL) {
814                 sfc_err(sa, "%s() failed: no such port", __func__);
815                 return ENOENT;
816         }
817
818         txq = &port->txq[queue_id];
819
820         txq->ring = tx_ring;
821
822         *egress_mport = port->egress_mport;
823
824         sfc_log_init(sa, "done");
825         sfc_put_adapter(sa);
826
827         return 0;
828 }
829
830 void
831 sfc_repr_proxy_del_txq(uint16_t pf_port_id, uint16_t repr_id,
832                        uint16_t queue_id)
833 {
834         struct sfc_repr_proxy_port *port;
835         struct sfc_repr_proxy_txq *txq;
836         struct sfc_repr_proxy *rp;
837         struct sfc_adapter *sa;
838
839         sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
840         rp = sfc_repr_proxy_by_adapter(sa);
841
842         sfc_log_init(sa, "entry");
843
844         port = sfc_repr_proxy_find_port(rp, repr_id);
845         if (port == NULL) {
846                 sfc_err(sa, "%s() failed: no such port", __func__);
847                 return;
848         }
849
850         txq = &port->txq[queue_id];
851
852         txq->ring = NULL;
853
854         sfc_log_init(sa, "done");
855         sfc_put_adapter(sa);
856 }