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