From: Igor Romanov Date: Mon, 11 Oct 2021 14:48:34 +0000 (+0300) Subject: net/sfc: add representor proxy port API X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=c377f1adf7093c6fab17833b289138d67db27563;p=dpdk.git net/sfc: add representor proxy port API The API is required to create and destroy representor proxy port assigned to representor. Signed-off-by: Igor Romanov Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton Reviewed-by: Ivan Malov --- diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c index 152234cb61..f79f4d5ffc 100644 --- a/drivers/net/sfc/sfc.c +++ b/drivers/net/sfc/sfc.c @@ -1043,6 +1043,18 @@ fail_nic_reset: return rc; } +void +sfc_pre_detach(struct sfc_adapter *sa) +{ + sfc_log_init(sa, "entry"); + + SFC_ASSERT(!sfc_adapter_is_locked(sa)); + + sfc_repr_proxy_pre_detach(sa); + + sfc_log_init(sa, "done"); +} + void sfc_detach(struct sfc_adapter *sa) { diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index 34e4772ab8..2b459a72db 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -398,6 +398,7 @@ uint32_t sfc_register_logtype(const struct rte_pci_addr *pci_addr, int sfc_probe(struct sfc_adapter *sa); void sfc_unprobe(struct sfc_adapter *sa); int sfc_attach(struct sfc_adapter *sa); +void sfc_pre_detach(struct sfc_adapter *sa); void sfc_detach(struct sfc_adapter *sa); int sfc_start(struct sfc_adapter *sa); void sfc_stop(struct sfc_adapter *sa); diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index ffd0a88eaf..2e34647e87 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -345,6 +345,8 @@ sfc_dev_close(struct rte_eth_dev *dev) return 0; } + sfc_pre_detach(sa); + sfc_adapter_lock(sa); switch (sa->state) { case SFC_ETHDEV_STARTED: diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c index ec97648f58..fa53a723ae 100644 --- a/drivers/net/sfc/sfc_repr.c +++ b/drivers/net/sfc/sfc_repr.c @@ -19,6 +19,7 @@ #include "sfc_debug.h" #include "sfc_repr.h" #include "sfc_ethdev_state.h" +#include "sfc_repr_proxy_api.h" #include "sfc_switch.h" /** Multi-process shared representor private data */ @@ -285,6 +286,7 @@ static int sfc_repr_dev_close(struct rte_eth_dev *dev) { struct sfc_repr *sr = sfc_repr_by_eth_dev(dev); + struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev); sfcr_info(sr, "entry"); @@ -306,6 +308,8 @@ sfc_repr_dev_close(struct rte_eth_dev *dev) * Rollback primary process sfc_repr_eth_dev_init() below. */ + (void)sfc_repr_proxy_del_port(srs->pf_port_id, srs->repr_id); + dev->dev_ops = NULL; sfc_repr_unlock(sr); @@ -378,6 +382,18 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params) goto fail_mae_assign_switch_port; } + ret = sfc_repr_proxy_add_port(repr_data->pf_port_id, + repr_data->repr_id, + dev->data->port_id, + &repr_data->mport_sel); + if (ret != 0) { + SFC_GENERIC_LOG(ERR, "%s() failed to add repr proxy port", + __func__); + SFC_ASSERT(ret > 0); + ret = -ret; + goto fail_create_port; + } + /* * Allocate process private data from heap, since it should not * be located in shared memory allocated using rte_malloc() API. @@ -419,6 +435,10 @@ fail_mac_addrs: free(sr); fail_alloc_sr: + (void)sfc_repr_proxy_del_port(repr_data->pf_port_id, + repr_data->repr_id); + +fail_create_port: fail_mae_assign_switch_port: SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret)); return ret; diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c index 6d3962304f..f64fa2efc7 100644 --- a/drivers/net/sfc/sfc_repr_proxy.c +++ b/drivers/net/sfc/sfc_repr_proxy.c @@ -13,17 +13,191 @@ #include "sfc_log.h" #include "sfc_service.h" #include "sfc_repr_proxy.h" +#include "sfc_repr_proxy_api.h" #include "sfc.h" +/** + * Amount of time to wait for the representor proxy routine (which is + * running on a service core) to handle a request sent via mbox. + */ +#define SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS 1000 + +static struct sfc_repr_proxy * +sfc_repr_proxy_by_adapter(struct sfc_adapter *sa) +{ + return &sa->repr_proxy; +} + +static struct sfc_adapter * +sfc_get_adapter_by_pf_port_id(uint16_t pf_port_id) +{ + struct rte_eth_dev *dev; + struct sfc_adapter *sa; + + SFC_ASSERT(pf_port_id < RTE_MAX_ETHPORTS); + + dev = &rte_eth_devices[pf_port_id]; + sa = sfc_adapter_by_eth_dev(dev); + + sfc_adapter_lock(sa); + + return sa; +} + +static void +sfc_put_adapter(struct sfc_adapter *sa) +{ + sfc_adapter_unlock(sa); +} + +static int +sfc_repr_proxy_mbox_send(struct sfc_repr_proxy_mbox *mbox, + struct sfc_repr_proxy_port *port, + enum sfc_repr_proxy_mbox_op op) +{ + const unsigned int wait_ms = SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS; + unsigned int i; + + mbox->op = op; + mbox->port = port; + mbox->ack = false; + + /* + * Release ordering enforces marker set after data is populated. + * Paired with acquire ordering in sfc_repr_proxy_mbox_handle(). + */ + __atomic_store_n(&mbox->write_marker, true, __ATOMIC_RELEASE); + + /* + * Wait for the representor routine to process the request. + * Give up on timeout. + */ + for (i = 0; i < wait_ms; i++) { + /* + * Paired with release ordering in sfc_repr_proxy_mbox_handle() + * on acknowledge write. + */ + if (__atomic_load_n(&mbox->ack, __ATOMIC_ACQUIRE)) + break; + + rte_delay_ms(1); + } + + if (i == wait_ms) { + SFC_GENERIC_LOG(ERR, + "%s() failed to wait for representor proxy routine ack", + __func__); + return ETIMEDOUT; + } + + return 0; +} + +static void +sfc_repr_proxy_mbox_handle(struct sfc_repr_proxy *rp) +{ + struct sfc_repr_proxy_mbox *mbox = &rp->mbox; + + /* + * Paired with release ordering in sfc_repr_proxy_mbox_send() + * on marker set. + */ + if (!__atomic_load_n(&mbox->write_marker, __ATOMIC_ACQUIRE)) + return; + + mbox->write_marker = false; + + switch (mbox->op) { + case SFC_REPR_PROXY_MBOX_ADD_PORT: + TAILQ_INSERT_TAIL(&rp->ports, mbox->port, entries); + break; + case SFC_REPR_PROXY_MBOX_DEL_PORT: + TAILQ_REMOVE(&rp->ports, mbox->port, entries); + break; + default: + SFC_ASSERT(0); + return; + } + + /* + * Paired with acquire ordering in sfc_repr_proxy_mbox_send() + * on acknowledge read. + */ + __atomic_store_n(&mbox->ack, true, __ATOMIC_RELEASE); +} + static int32_t sfc_repr_proxy_routine(void *arg) { struct sfc_repr_proxy *rp = arg; - /* Representor proxy boilerplate will be here */ - RTE_SET_USED(rp); + sfc_repr_proxy_mbox_handle(rp); + + return 0; +} + +static int +sfc_repr_proxy_ports_init(struct sfc_adapter *sa) +{ + struct sfc_repr_proxy *rp = &sa->repr_proxy; + int rc; + + sfc_log_init(sa, "entry"); + + rc = efx_mcdi_mport_alloc_alias(sa->nic, &rp->mport_alias, NULL); + if (rc != 0) { + sfc_err(sa, "failed to alloc mport alias: %s", + rte_strerror(rc)); + goto fail_alloc_mport_alias; + } + + TAILQ_INIT(&rp->ports); + + sfc_log_init(sa, "done"); return 0; + +fail_alloc_mport_alias: + + sfc_log_init(sa, "failed: %s", rte_strerror(rc)); + return rc; +} + +void +sfc_repr_proxy_pre_detach(struct sfc_adapter *sa) +{ + struct sfc_repr_proxy *rp = &sa->repr_proxy; + bool close_ports[RTE_MAX_ETHPORTS] = {0}; + struct sfc_repr_proxy_port *port; + unsigned int i; + + SFC_ASSERT(!sfc_adapter_is_locked(sa)); + + sfc_adapter_lock(sa); + + if (sfc_repr_available(sfc_sa2shared(sa))) { + TAILQ_FOREACH(port, &rp->ports, entries) + close_ports[port->rte_port_id] = true; + } else { + sfc_log_init(sa, "representors not supported - skip"); + } + + sfc_adapter_unlock(sa); + + for (i = 0; i < RTE_DIM(close_ports); i++) { + if (close_ports[i]) { + rte_eth_dev_stop(i); + rte_eth_dev_close(i); + } + } +} + +static void +sfc_repr_proxy_ports_fini(struct sfc_adapter *sa) +{ + struct sfc_repr_proxy *rp = &sa->repr_proxy; + + efx_mae_mport_free(sa->nic, &rp->mport_alias); } int @@ -43,6 +217,10 @@ sfc_repr_proxy_attach(struct sfc_adapter *sa) return 0; } + rc = sfc_repr_proxy_ports_init(sa); + if (rc != 0) + goto fail_ports_init; + cid = sfc_get_service_lcore(sa->socket_id); if (cid == RTE_MAX_LCORE && sa->socket_id != SOCKET_ID_ANY) { /* Warn and try to allocate on any NUMA node */ @@ -96,6 +274,9 @@ fail_register: */ fail_get_service_lcore: + sfc_repr_proxy_ports_fini(sa); + +fail_ports_init: sfc_log_init(sa, "failed: %s", rte_strerror(rc)); return rc; } @@ -115,6 +296,7 @@ sfc_repr_proxy_detach(struct sfc_adapter *sa) rte_service_map_lcore_set(rp->service_id, rp->service_core_id, 0); rte_service_component_unregister(rp->service_id); + sfc_repr_proxy_ports_fini(sa); sfc_log_init(sa, "done"); } @@ -165,6 +347,8 @@ sfc_repr_proxy_start(struct sfc_adapter *sa) goto fail_runstate_set; } + rp->started = true; + sfc_log_init(sa, "done"); return 0; @@ -210,5 +394,137 @@ sfc_repr_proxy_stop(struct sfc_adapter *sa) /* Service lcore may be shared and we never stop it */ + rp->started = false; + + sfc_log_init(sa, "done"); +} + +static struct sfc_repr_proxy_port * +sfc_repr_proxy_find_port(struct sfc_repr_proxy *rp, uint16_t repr_id) +{ + struct sfc_repr_proxy_port *port; + + TAILQ_FOREACH(port, &rp->ports, entries) { + if (port->repr_id == repr_id) + return port; + } + + return NULL; +} + +int +sfc_repr_proxy_add_port(uint16_t pf_port_id, uint16_t repr_id, + uint16_t rte_port_id, const efx_mport_sel_t *mport_sel) +{ + struct sfc_repr_proxy_port *port; + struct sfc_repr_proxy *rp; + struct sfc_adapter *sa; + int rc; + + sa = sfc_get_adapter_by_pf_port_id(pf_port_id); + rp = sfc_repr_proxy_by_adapter(sa); + + sfc_log_init(sa, "entry"); + TAILQ_FOREACH(port, &rp->ports, entries) { + if (port->rte_port_id == rte_port_id) { + rc = EEXIST; + sfc_err(sa, "%s() failed: port exists", __func__); + goto fail_port_exists; + } + } + + port = rte_zmalloc("sfc-repr-proxy-port", sizeof(*port), + sa->socket_id); + if (port == NULL) { + rc = ENOMEM; + sfc_err(sa, "failed to alloc memory for proxy port"); + goto fail_alloc_port; + } + + rc = efx_mae_mport_id_by_selector(sa->nic, mport_sel, + &port->egress_mport); + if (rc != 0) { + sfc_err(sa, + "failed get MAE mport id by selector (repr_id %u): %s", + repr_id, rte_strerror(rc)); + goto fail_mport_id; + } + + port->rte_port_id = rte_port_id; + port->repr_id = repr_id; + + if (rp->started) { + rc = sfc_repr_proxy_mbox_send(&rp->mbox, port, + SFC_REPR_PROXY_MBOX_ADD_PORT); + if (rc != 0) { + sfc_err(sa, "failed to add proxy port %u", + port->repr_id); + goto fail_port_add; + } + } else { + TAILQ_INSERT_TAIL(&rp->ports, port, entries); + } + + sfc_log_init(sa, "done"); + sfc_put_adapter(sa); + + return 0; + +fail_port_add: +fail_mport_id: + rte_free(port); +fail_alloc_port: +fail_port_exists: + sfc_log_init(sa, "failed: %s", rte_strerror(rc)); + sfc_put_adapter(sa); + + return rc; +} + +int +sfc_repr_proxy_del_port(uint16_t pf_port_id, uint16_t repr_id) +{ + struct sfc_repr_proxy_port *port; + struct sfc_repr_proxy *rp; + struct sfc_adapter *sa; + int rc; + + sa = sfc_get_adapter_by_pf_port_id(pf_port_id); + rp = sfc_repr_proxy_by_adapter(sa); + + sfc_log_init(sa, "entry"); + + port = sfc_repr_proxy_find_port(rp, repr_id); + if (port == NULL) { + sfc_err(sa, "failed: no such port"); + rc = ENOENT; + goto fail_no_port; + } + + if (rp->started) { + rc = sfc_repr_proxy_mbox_send(&rp->mbox, port, + SFC_REPR_PROXY_MBOX_DEL_PORT); + if (rc != 0) { + sfc_err(sa, "failed to remove proxy port %u", + port->repr_id); + goto fail_port_remove; + } + } else { + TAILQ_REMOVE(&rp->ports, port, entries); + } + + rte_free(port); + sfc_log_init(sa, "done"); + + sfc_put_adapter(sa); + + return 0; + +fail_port_remove: +fail_no_port: + sfc_log_init(sa, "failed: %s", rte_strerror(rc)); + sfc_put_adapter(sa); + + return rc; } diff --git a/drivers/net/sfc/sfc_repr_proxy.h b/drivers/net/sfc/sfc_repr_proxy.h index 953b9922c8..e4a6213c10 100644 --- a/drivers/net/sfc/sfc_repr_proxy.h +++ b/drivers/net/sfc/sfc_repr_proxy.h @@ -12,6 +12,8 @@ #include +#include "efx.h" + #ifdef __cplusplus extern "C" { #endif @@ -24,14 +26,42 @@ extern "C" { #define SFC_REPR_PROXY_NB_TXQ_MIN (1) #define SFC_REPR_PROXY_NB_TXQ_MAX (1) +struct sfc_repr_proxy_port { + TAILQ_ENTRY(sfc_repr_proxy_port) entries; + uint16_t repr_id; + uint16_t rte_port_id; + efx_mport_id_t egress_mport; +}; + +enum sfc_repr_proxy_mbox_op { + SFC_REPR_PROXY_MBOX_ADD_PORT, + SFC_REPR_PROXY_MBOX_DEL_PORT, +}; + +struct sfc_repr_proxy_mbox { + struct sfc_repr_proxy_port *port; + enum sfc_repr_proxy_mbox_op op; + + bool write_marker; + bool ack; +}; + +TAILQ_HEAD(sfc_repr_proxy_ports, sfc_repr_proxy_port); + struct sfc_repr_proxy { uint32_t service_core_id; uint32_t service_id; + efx_mport_id_t mport_alias; + struct sfc_repr_proxy_ports ports; + bool started; + + struct sfc_repr_proxy_mbox mbox; }; struct sfc_adapter; int sfc_repr_proxy_attach(struct sfc_adapter *sa); +void sfc_repr_proxy_pre_detach(struct sfc_adapter *sa); void sfc_repr_proxy_detach(struct sfc_adapter *sa); int sfc_repr_proxy_start(struct sfc_adapter *sa); void sfc_repr_proxy_stop(struct sfc_adapter *sa); diff --git a/drivers/net/sfc/sfc_repr_proxy_api.h b/drivers/net/sfc/sfc_repr_proxy_api.h new file mode 100644 index 0000000000..af9009ca3c --- /dev/null +++ b/drivers/net/sfc/sfc_repr_proxy_api.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019-2021 Xilinx, Inc. + * Copyright(c) 2019 Solarflare Communications Inc. + * + * This software was jointly developed between OKTET Labs (under contract + * for Solarflare) and Solarflare Communications, Inc. + */ + +#ifndef _SFC_REPR_PROXY_API_H +#define _SFC_REPR_PROXY_API_H + +#include + +#include "efx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int sfc_repr_proxy_add_port(uint16_t pf_port_id, uint16_t repr_id, + uint16_t rte_port_id, + const efx_mport_sel_t *mport_set); +int sfc_repr_proxy_del_port(uint16_t pf_port_id, uint16_t repr_id); + +#ifdef __cplusplus +} +#endif +#endif /* _SFC_REPR_PROXY_API_H */