1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2019 Solarflare Communications Inc.
6 * This software was jointly developed between OKTET Labs (under contract
7 * for Solarflare) and Solarflare Communications, Inc.
10 #include <rte_service.h>
11 #include <rte_service_component.h>
14 #include "sfc_service.h"
15 #include "sfc_repr_proxy.h"
16 #include "sfc_repr_proxy_api.h"
22 * Amount of time to wait for the representor proxy routine (which is
23 * running on a service core) to handle a request sent via mbox.
25 #define SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS 1000
27 static struct sfc_repr_proxy *
28 sfc_repr_proxy_by_adapter(struct sfc_adapter *sa)
30 return &sa->repr_proxy;
33 static struct sfc_adapter *
34 sfc_get_adapter_by_pf_port_id(uint16_t pf_port_id)
36 struct rte_eth_dev *dev;
37 struct sfc_adapter *sa;
39 SFC_ASSERT(pf_port_id < RTE_MAX_ETHPORTS);
41 dev = &rte_eth_devices[pf_port_id];
42 sa = sfc_adapter_by_eth_dev(dev);
50 sfc_put_adapter(struct sfc_adapter *sa)
52 sfc_adapter_unlock(sa);
56 sfc_repr_proxy_mbox_send(struct sfc_repr_proxy_mbox *mbox,
57 struct sfc_repr_proxy_port *port,
58 enum sfc_repr_proxy_mbox_op op)
60 const unsigned int wait_ms = SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS;
68 * Release ordering enforces marker set after data is populated.
69 * Paired with acquire ordering in sfc_repr_proxy_mbox_handle().
71 __atomic_store_n(&mbox->write_marker, true, __ATOMIC_RELEASE);
74 * Wait for the representor routine to process the request.
77 for (i = 0; i < wait_ms; i++) {
79 * Paired with release ordering in sfc_repr_proxy_mbox_handle()
80 * on acknowledge write.
82 if (__atomic_load_n(&mbox->ack, __ATOMIC_ACQUIRE))
90 "%s() failed to wait for representor proxy routine ack",
99 sfc_repr_proxy_mbox_handle(struct sfc_repr_proxy *rp)
101 struct sfc_repr_proxy_mbox *mbox = &rp->mbox;
104 * Paired with release ordering in sfc_repr_proxy_mbox_send()
107 if (!__atomic_load_n(&mbox->write_marker, __ATOMIC_ACQUIRE))
110 mbox->write_marker = false;
113 case SFC_REPR_PROXY_MBOX_ADD_PORT:
114 TAILQ_INSERT_TAIL(&rp->ports, mbox->port, entries);
116 case SFC_REPR_PROXY_MBOX_DEL_PORT:
117 TAILQ_REMOVE(&rp->ports, mbox->port, entries);
125 * Paired with acquire ordering in sfc_repr_proxy_mbox_send()
126 * on acknowledge read.
128 __atomic_store_n(&mbox->ack, true, __ATOMIC_RELEASE);
132 sfc_repr_proxy_routine(void *arg)
134 struct sfc_repr_proxy *rp = arg;
136 sfc_repr_proxy_mbox_handle(rp);
142 sfc_repr_proxy_rxq_attach(struct sfc_adapter *sa)
144 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
145 struct sfc_repr_proxy *rp = &sa->repr_proxy;
148 sfc_log_init(sa, "entry");
150 for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
151 sfc_sw_index_t sw_index = sfc_repr_rxq_sw_index(sas, i);
153 rp->dp_rxq[i].sw_index = sw_index;
156 sfc_log_init(sa, "done");
162 sfc_repr_proxy_rxq_detach(struct sfc_adapter *sa)
164 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
165 struct sfc_repr_proxy *rp = &sa->repr_proxy;
168 sfc_log_init(sa, "entry");
170 for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
171 rp->dp_rxq[i].sw_index = 0;
173 sfc_log_init(sa, "done");
177 sfc_repr_proxy_rxq_init(struct sfc_adapter *sa,
178 struct sfc_repr_proxy_dp_rxq *rxq)
180 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
181 uint16_t nb_rx_desc = SFC_REPR_PROXY_RX_DESC_COUNT;
182 struct sfc_rxq_info *rxq_info;
183 struct rte_eth_rxconf rxconf = {
184 .rx_free_thresh = SFC_REPR_PROXY_RXQ_REFILL_LEVEL,
189 sfc_log_init(sa, "entry");
191 rxq_info = &sas->rxq_info[rxq->sw_index];
192 if (rxq_info->state & SFC_RXQ_INITIALIZED) {
193 sfc_log_init(sa, "RxQ is already initialized - skip");
197 nb_rx_desc = RTE_MIN(nb_rx_desc, sa->rxq_max_entries);
198 nb_rx_desc = RTE_MAX(nb_rx_desc, sa->rxq_min_entries);
200 rc = sfc_rx_qinit_info(sa, rxq->sw_index, EFX_RXQ_FLAG_INGRESS_MPORT);
202 sfc_err(sa, "failed to init representor proxy RxQ info");
203 goto fail_repr_rxq_init_info;
206 rc = sfc_rx_qinit(sa, rxq->sw_index, nb_rx_desc, sa->socket_id, &rxconf,
209 sfc_err(sa, "failed to init representor proxy RxQ");
210 goto fail_repr_rxq_init;
213 sfc_log_init(sa, "done");
218 fail_repr_rxq_init_info:
219 sfc_log_init(sa, "failed: %s", rte_strerror(rc));
225 sfc_repr_proxy_rxq_fini(struct sfc_adapter *sa)
227 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
228 struct sfc_repr_proxy *rp = &sa->repr_proxy;
229 struct sfc_rxq_info *rxq_info;
232 sfc_log_init(sa, "entry");
234 if (!sfc_repr_available(sas)) {
235 sfc_log_init(sa, "representors not supported - skip");
239 for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
240 struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
242 rxq_info = &sas->rxq_info[rxq->sw_index];
243 if (rxq_info->state != SFC_RXQ_INITIALIZED) {
245 "representor RxQ %u is already finalized - skip",
250 sfc_rx_qfini(sa, rxq->sw_index);
253 sfc_log_init(sa, "done");
257 sfc_repr_proxy_rxq_stop(struct sfc_adapter *sa)
259 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
262 sfc_log_init(sa, "entry");
264 for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
265 sfc_rx_qstop(sa, sa->repr_proxy.dp_rxq[i].sw_index);
267 sfc_repr_proxy_rxq_fini(sa);
269 sfc_log_init(sa, "done");
273 sfc_repr_proxy_rxq_start(struct sfc_adapter *sa)
275 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
276 struct sfc_repr_proxy *rp = &sa->repr_proxy;
280 sfc_log_init(sa, "entry");
282 if (!sfc_repr_available(sas)) {
283 sfc_log_init(sa, "representors not supported - skip");
287 for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
288 struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
290 rc = sfc_repr_proxy_rxq_init(sa, rxq);
292 sfc_err(sa, "failed to init representor proxy RxQ %u",
297 rc = sfc_rx_qstart(sa, rxq->sw_index);
299 sfc_err(sa, "failed to start representor proxy RxQ %u",
305 sfc_log_init(sa, "done");
311 sfc_repr_proxy_rxq_stop(sa);
312 sfc_log_init(sa, "failed: %s", rte_strerror(rc));
317 sfc_repr_proxy_ports_init(struct sfc_adapter *sa)
319 struct sfc_repr_proxy *rp = &sa->repr_proxy;
322 sfc_log_init(sa, "entry");
324 rc = efx_mcdi_mport_alloc_alias(sa->nic, &rp->mport_alias, NULL);
326 sfc_err(sa, "failed to alloc mport alias: %s",
328 goto fail_alloc_mport_alias;
331 TAILQ_INIT(&rp->ports);
333 sfc_log_init(sa, "done");
337 fail_alloc_mport_alias:
339 sfc_log_init(sa, "failed: %s", rte_strerror(rc));
344 sfc_repr_proxy_pre_detach(struct sfc_adapter *sa)
346 struct sfc_repr_proxy *rp = &sa->repr_proxy;
347 bool close_ports[RTE_MAX_ETHPORTS] = {0};
348 struct sfc_repr_proxy_port *port;
351 SFC_ASSERT(!sfc_adapter_is_locked(sa));
353 sfc_adapter_lock(sa);
355 if (sfc_repr_available(sfc_sa2shared(sa))) {
356 TAILQ_FOREACH(port, &rp->ports, entries)
357 close_ports[port->rte_port_id] = true;
359 sfc_log_init(sa, "representors not supported - skip");
362 sfc_adapter_unlock(sa);
364 for (i = 0; i < RTE_DIM(close_ports); i++) {
365 if (close_ports[i]) {
367 rte_eth_dev_close(i);
373 sfc_repr_proxy_ports_fini(struct sfc_adapter *sa)
375 struct sfc_repr_proxy *rp = &sa->repr_proxy;
377 efx_mae_mport_free(sa->nic, &rp->mport_alias);
381 sfc_repr_proxy_attach(struct sfc_adapter *sa)
383 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
384 struct sfc_repr_proxy *rp = &sa->repr_proxy;
385 struct rte_service_spec service;
390 sfc_log_init(sa, "entry");
392 if (!sfc_repr_available(sas)) {
393 sfc_log_init(sa, "representors not supported - skip");
397 rc = sfc_repr_proxy_rxq_attach(sa);
399 goto fail_rxq_attach;
401 rc = sfc_repr_proxy_ports_init(sa);
403 goto fail_ports_init;
405 cid = sfc_get_service_lcore(sa->socket_id);
406 if (cid == RTE_MAX_LCORE && sa->socket_id != SOCKET_ID_ANY) {
407 /* Warn and try to allocate on any NUMA node */
409 "repr proxy: unable to get service lcore at socket %d",
412 cid = sfc_get_service_lcore(SOCKET_ID_ANY);
414 if (cid == RTE_MAX_LCORE) {
416 sfc_err(sa, "repr proxy: failed to get service lcore");
417 goto fail_get_service_lcore;
420 memset(&service, 0, sizeof(service));
421 snprintf(service.name, sizeof(service.name),
422 "net_sfc_%hu_repr_proxy", sfc_sa2shared(sa)->port_id);
423 service.socket_id = rte_lcore_to_socket_id(cid);
424 service.callback = sfc_repr_proxy_routine;
425 service.callback_userdata = rp;
427 rc = rte_service_component_register(&service, &sid);
430 sfc_err(sa, "repr proxy: failed to register service component");
434 rc = rte_service_map_lcore_set(sid, cid, 1);
437 sfc_err(sa, "repr proxy: failed to map lcore");
441 rp->service_core_id = cid;
442 rp->service_id = sid;
444 sfc_log_init(sa, "done");
449 rte_service_component_unregister(sid);
453 * No need to rollback service lcore get since
454 * it just makes socket_id based search and remembers it.
457 fail_get_service_lcore:
458 sfc_repr_proxy_ports_fini(sa);
461 sfc_repr_proxy_rxq_detach(sa);
464 sfc_log_init(sa, "failed: %s", rte_strerror(rc));
469 sfc_repr_proxy_detach(struct sfc_adapter *sa)
471 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
472 struct sfc_repr_proxy *rp = &sa->repr_proxy;
474 sfc_log_init(sa, "entry");
476 if (!sfc_repr_available(sas)) {
477 sfc_log_init(sa, "representors not supported - skip");
481 rte_service_map_lcore_set(rp->service_id, rp->service_core_id, 0);
482 rte_service_component_unregister(rp->service_id);
483 sfc_repr_proxy_ports_fini(sa);
484 sfc_repr_proxy_rxq_detach(sa);
486 sfc_log_init(sa, "done");
490 sfc_repr_proxy_start(struct sfc_adapter *sa)
492 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
493 struct sfc_repr_proxy *rp = &sa->repr_proxy;
496 sfc_log_init(sa, "entry");
499 * The condition to start the proxy is insufficient. It will be
500 * complemented with representor port start/stop support.
502 if (!sfc_repr_available(sas)) {
503 sfc_log_init(sa, "representors not supported - skip");
507 rc = sfc_repr_proxy_rxq_start(sa);
511 /* Service core may be in "stopped" state, start it */
512 rc = rte_service_lcore_start(rp->service_core_id);
513 if (rc != 0 && rc != -EALREADY) {
515 sfc_err(sa, "failed to start service core for %s: %s",
516 rte_service_get_name(rp->service_id),
518 goto fail_start_core;
521 /* Run the service */
522 rc = rte_service_component_runstate_set(rp->service_id, 1);
525 sfc_err(sa, "failed to run %s component: %s",
526 rte_service_get_name(rp->service_id),
528 goto fail_component_runstate_set;
530 rc = rte_service_runstate_set(rp->service_id, 1);
533 sfc_err(sa, "failed to run %s: %s",
534 rte_service_get_name(rp->service_id),
536 goto fail_runstate_set;
541 sfc_log_init(sa, "done");
546 rte_service_component_runstate_set(rp->service_id, 0);
548 fail_component_runstate_set:
549 /* Service lcore may be shared and we never stop it */
552 sfc_repr_proxy_rxq_stop(sa);
555 sfc_log_init(sa, "failed: %s", rte_strerror(rc));
560 sfc_repr_proxy_stop(struct sfc_adapter *sa)
562 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
563 struct sfc_repr_proxy *rp = &sa->repr_proxy;
566 sfc_log_init(sa, "entry");
568 if (!sfc_repr_available(sas)) {
569 sfc_log_init(sa, "representors not supported - skip");
573 rc = rte_service_runstate_set(rp->service_id, 0);
575 sfc_err(sa, "failed to stop %s: %s",
576 rte_service_get_name(rp->service_id),
580 rc = rte_service_component_runstate_set(rp->service_id, 0);
582 sfc_err(sa, "failed to stop %s component: %s",
583 rte_service_get_name(rp->service_id),
587 /* Service lcore may be shared and we never stop it */
589 sfc_repr_proxy_rxq_stop(sa);
593 sfc_log_init(sa, "done");
596 static struct sfc_repr_proxy_port *
597 sfc_repr_proxy_find_port(struct sfc_repr_proxy *rp, uint16_t repr_id)
599 struct sfc_repr_proxy_port *port;
601 TAILQ_FOREACH(port, &rp->ports, entries) {
602 if (port->repr_id == repr_id)
610 sfc_repr_proxy_add_port(uint16_t pf_port_id, uint16_t repr_id,
611 uint16_t rte_port_id, const efx_mport_sel_t *mport_sel)
613 struct sfc_repr_proxy_port *port;
614 struct sfc_repr_proxy *rp;
615 struct sfc_adapter *sa;
618 sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
619 rp = sfc_repr_proxy_by_adapter(sa);
621 sfc_log_init(sa, "entry");
622 TAILQ_FOREACH(port, &rp->ports, entries) {
623 if (port->rte_port_id == rte_port_id) {
625 sfc_err(sa, "%s() failed: port exists", __func__);
626 goto fail_port_exists;
630 port = rte_zmalloc("sfc-repr-proxy-port", sizeof(*port),
634 sfc_err(sa, "failed to alloc memory for proxy port");
635 goto fail_alloc_port;
638 rc = efx_mae_mport_id_by_selector(sa->nic, mport_sel,
639 &port->egress_mport);
642 "failed get MAE mport id by selector (repr_id %u): %s",
643 repr_id, rte_strerror(rc));
647 port->rte_port_id = rte_port_id;
648 port->repr_id = repr_id;
651 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
652 SFC_REPR_PROXY_MBOX_ADD_PORT);
654 sfc_err(sa, "failed to add proxy port %u",
659 TAILQ_INSERT_TAIL(&rp->ports, port, entries);
662 sfc_log_init(sa, "done");
672 sfc_log_init(sa, "failed: %s", rte_strerror(rc));
679 sfc_repr_proxy_del_port(uint16_t pf_port_id, uint16_t repr_id)
681 struct sfc_repr_proxy_port *port;
682 struct sfc_repr_proxy *rp;
683 struct sfc_adapter *sa;
686 sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
687 rp = sfc_repr_proxy_by_adapter(sa);
689 sfc_log_init(sa, "entry");
691 port = sfc_repr_proxy_find_port(rp, repr_id);
693 sfc_err(sa, "failed: no such port");
699 rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
700 SFC_REPR_PROXY_MBOX_DEL_PORT);
702 sfc_err(sa, "failed to remove proxy port %u",
704 goto fail_port_remove;
707 TAILQ_REMOVE(&rp->ports, port, entries);
712 sfc_log_init(sa, "done");
720 sfc_log_init(sa, "failed: %s", rte_strerror(rc));
727 sfc_repr_proxy_add_rxq(uint16_t pf_port_id, uint16_t repr_id,
728 uint16_t queue_id, struct rte_ring *rx_ring,
729 struct rte_mempool *mp)
731 struct sfc_repr_proxy_port *port;
732 struct sfc_repr_proxy_rxq *rxq;
733 struct sfc_repr_proxy *rp;
734 struct sfc_adapter *sa;
736 sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
737 rp = sfc_repr_proxy_by_adapter(sa);
739 sfc_log_init(sa, "entry");
741 port = sfc_repr_proxy_find_port(rp, repr_id);
743 sfc_err(sa, "%s() failed: no such port", __func__);
747 rxq = &port->rxq[queue_id];
748 if (rp->dp_rxq[queue_id].mp != NULL && rp->dp_rxq[queue_id].mp != mp) {
749 sfc_err(sa, "multiple mempools per queue are not supported");
756 rp->dp_rxq[queue_id].mp = mp;
757 rp->dp_rxq[queue_id].ref_count++;
759 sfc_log_init(sa, "done");
766 sfc_repr_proxy_del_rxq(uint16_t pf_port_id, uint16_t repr_id,
769 struct sfc_repr_proxy_port *port;
770 struct sfc_repr_proxy_rxq *rxq;
771 struct sfc_repr_proxy *rp;
772 struct sfc_adapter *sa;
774 sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
775 rp = sfc_repr_proxy_by_adapter(sa);
777 sfc_log_init(sa, "entry");
779 port = sfc_repr_proxy_find_port(rp, repr_id);
781 sfc_err(sa, "%s() failed: no such port", __func__);
785 rxq = &port->rxq[queue_id];
789 rp->dp_rxq[queue_id].ref_count--;
790 if (rp->dp_rxq[queue_id].ref_count == 0)
791 rp->dp_rxq[queue_id].mp = NULL;
793 sfc_log_init(sa, "done");
798 sfc_repr_proxy_add_txq(uint16_t pf_port_id, uint16_t repr_id,
799 uint16_t queue_id, struct rte_ring *tx_ring,
800 efx_mport_id_t *egress_mport)
802 struct sfc_repr_proxy_port *port;
803 struct sfc_repr_proxy_txq *txq;
804 struct sfc_repr_proxy *rp;
805 struct sfc_adapter *sa;
807 sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
808 rp = sfc_repr_proxy_by_adapter(sa);
810 sfc_log_init(sa, "entry");
812 port = sfc_repr_proxy_find_port(rp, repr_id);
814 sfc_err(sa, "%s() failed: no such port", __func__);
818 txq = &port->txq[queue_id];
822 *egress_mport = port->egress_mport;
824 sfc_log_init(sa, "done");
831 sfc_repr_proxy_del_txq(uint16_t pf_port_id, uint16_t repr_id,
834 struct sfc_repr_proxy_port *port;
835 struct sfc_repr_proxy_txq *txq;
836 struct sfc_repr_proxy *rp;
837 struct sfc_adapter *sa;
839 sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
840 rp = sfc_repr_proxy_by_adapter(sa);
842 sfc_log_init(sa, "entry");
844 port = sfc_repr_proxy_find_port(rp, repr_id);
846 sfc_err(sa, "%s() failed: no such port", __func__);
850 txq = &port->txq[queue_id];
854 sfc_log_init(sa, "done");