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