DPDK patches and discussions
 help / color / mirror / Atom feed
From: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
To: dev@dpdk.org
Cc: Igor Romanov <igor.romanov@oktetlabs.ru>,
	Andy Moreton <amoreton@xilinx.com>,
	Ivan Malov <ivan.malov@oktetlabs.ru>
Subject: [dpdk-dev] [PATCH 11/38] net/sfc: add port representors infrastructure
Date: Fri, 27 Aug 2021 09:56:50 +0300
Message-ID: <20210827065717.1838258-12-andrew.rybchenko@oktetlabs.ru> (raw)
In-Reply-To: <20210827065717.1838258-1-andrew.rybchenko@oktetlabs.ru>

From: Igor Romanov <igor.romanov@oktetlabs.ru>

Provide minimal implementation for port representors that only can be
configured and can provide device information.

Signed-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>
---
 doc/guides/nics/sfc_efx.rst  |  13 +-
 drivers/net/sfc/meson.build  |   1 +
 drivers/net/sfc/sfc_ethdev.c | 156 +++++++++++-
 drivers/net/sfc/sfc_kvargs.c |   1 +
 drivers/net/sfc/sfc_kvargs.h |   2 +
 drivers/net/sfc/sfc_repr.c   | 458 +++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_repr.h   |  36 +++
 drivers/net/sfc/sfc_switch.h |   5 +
 8 files changed, 663 insertions(+), 9 deletions(-)
 create mode 100644 drivers/net/sfc/sfc_repr.c
 create mode 100644 drivers/net/sfc/sfc_repr.h

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index d66cb76dab..4719031508 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -74,6 +74,8 @@ SFC EFX PMD has support for:
 
 - SR-IOV PF
 
+- Port representors (see :ref: switch_representation)
+
 
 Non-supported Features
 ----------------------
@@ -382,7 +384,16 @@ boolean parameters value.
   software virtual switch (for example, Open vSwitch) makes the decision.
   Software virtual switch may install MAE rules to pass established traffic
   flows via hardware and offload software datapath as the result.
-  Default is legacy.
+  Default is legacy, unless representors are specified, in which case switchdev
+  is chosen.
+
+- ``representor`` parameter [list]
+
+  Instantiate port representor Ethernet devices for specified Virtual
+  Functions list.
+
+  It is a standard parameter whose format is described in
+  :ref:`ethernet_device_standard_device_arguments`.
 
 - ``rx_datapath`` [auto|efx|ef10|ef10_essb] (default **auto**)
 
diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 4fc2063f7a..98365e9e73 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -98,4 +98,5 @@ sources = files(
         'sfc_ef100_tx.c',
         'sfc_service.c',
         'sfc_repr_proxy.c',
+        'sfc_repr.c',
 )
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index ff762bb90b..8308cbdfef 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -28,6 +28,7 @@
 #include "sfc_flow.h"
 #include "sfc_dp.h"
 #include "sfc_dp_rx.h"
+#include "sfc_repr.h"
 #include "sfc_sw_stats.h"
 
 #define SFC_XSTAT_ID_INVALID_VAL  UINT64_MAX
@@ -1908,6 +1909,10 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
 	.pool_ops_supported		= sfc_pool_ops_supported,
 };
 
+struct sfc_ethdev_init_data {
+	uint16_t		nb_representors;
+};
+
 /**
  * Duplicate a string in potentially shared memory required for
  * multi-process support.
@@ -2189,7 +2194,7 @@ sfc_register_dp(void)
 }
 
 static int
-sfc_parse_switch_mode(struct sfc_adapter *sa)
+sfc_parse_switch_mode(struct sfc_adapter *sa, bool has_representors)
 {
 	const char *switch_mode = NULL;
 	int rc;
@@ -2201,9 +2206,9 @@ sfc_parse_switch_mode(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_kvargs;
 
-	/* Check representors when supported */
-	if (switch_mode == NULL ||
-	    strcasecmp(switch_mode, SFC_KVARG_SWITCH_MODE_LEGACY) == 0) {
+	if (switch_mode == NULL) {
+		sa->switchdev = has_representors;
+	} else if (strcasecmp(switch_mode, SFC_KVARG_SWITCH_MODE_LEGACY) == 0) {
 		sa->switchdev = false;
 	} else if (strcasecmp(switch_mode,
 			      SFC_KVARG_SWITCH_MODE_SWITCHDEV) == 0) {
@@ -2227,10 +2232,11 @@ sfc_parse_switch_mode(struct sfc_adapter *sa)
 }
 
 static int
-sfc_eth_dev_init(struct rte_eth_dev *dev)
+sfc_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 {
 	struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct sfc_ethdev_init_data *init_data = init_params;
 	uint32_t logtype_main;
 	struct sfc_adapter *sa;
 	int rc;
@@ -2312,7 +2318,7 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
 	sfc_adapter_lock_init(sa);
 	sfc_adapter_lock(sa);
 
-	rc = sfc_parse_switch_mode(sa);
+	rc = sfc_parse_switch_mode(sa, init_data->nb_representors > 0);
 	if (rc != 0)
 		goto fail_switch_mode;
 
@@ -2402,11 +2408,145 @@ static const struct rte_pci_id pci_id_sfc_efx_map[] = {
 	{ .vendor_id = 0 /* sentinel */ }
 };
 
+static int
+sfc_parse_rte_devargs(const char *args, struct rte_eth_devargs *devargs)
+{
+	struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
+	int rc;
+
+	if (args != NULL) {
+		rc = rte_eth_devargs_parse(args, &eth_da);
+		if (rc != 0) {
+			SFC_GENERIC_LOG(ERR,
+					"Failed to parse generic devargs '%s'",
+					args);
+			return rc;
+		}
+	}
+
+	*devargs = eth_da;
+
+	return 0;
+}
+
+static int
+sfc_eth_dev_create(struct rte_pci_device *pci_dev,
+		   struct sfc_ethdev_init_data *init_data,
+		   struct rte_eth_dev **devp)
+{
+	struct rte_eth_dev *dev;
+	int rc;
+
+	rc = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
+				sizeof(struct sfc_adapter_shared),
+				eth_dev_pci_specific_init, pci_dev,
+				sfc_eth_dev_init, init_data);
+	if (rc != 0) {
+		SFC_GENERIC_LOG(ERR, "Failed to create sfc ethdev '%s'",
+				pci_dev->device.name);
+		return rc;
+	}
+
+	dev = rte_eth_dev_allocated(pci_dev->device.name);
+	if (dev == NULL) {
+		SFC_GENERIC_LOG(ERR, "Failed to find allocated sfc ethdev '%s'",
+				pci_dev->device.name);
+		return -ENODEV;
+	}
+
+	*devp = dev;
+
+	return 0;
+}
+
+static int
+sfc_eth_dev_create_representors(struct rte_eth_dev *dev,
+				const struct rte_eth_devargs *eth_da)
+{
+	struct sfc_adapter *sa;
+	unsigned int i;
+	int rc;
+
+	if (eth_da->nb_representor_ports == 0)
+		return 0;
+
+	sa = sfc_adapter_by_eth_dev(dev);
+
+	if (!sa->switchdev) {
+		sfc_err(sa, "cannot create representors in non-switchdev mode");
+		return -EINVAL;
+	}
+
+	if (!sfc_repr_available(sfc_sa2shared(sa))) {
+		sfc_err(sa, "cannot create representors: unsupported");
+
+		return -ENOTSUP;
+	}
+
+	for (i = 0; i < eth_da->nb_representor_ports; ++i) {
+		const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+		efx_mport_sel_t mport_sel;
+
+		rc = efx_mae_mport_by_pcie_function(encp->enc_pf,
+				eth_da->representor_ports[i], &mport_sel);
+		if (rc != 0) {
+			sfc_err(sa,
+				"failed to get representor %u m-port: %s - ignore",
+				eth_da->representor_ports[i],
+				rte_strerror(-rc));
+			continue;
+		}
+
+		rc = sfc_repr_create(dev, eth_da->representor_ports[i],
+				     sa->mae.switch_domain_id, &mport_sel);
+		if (rc != 0) {
+			sfc_err(sa, "cannot create representor %u: %s - ignore",
+				eth_da->representor_ports[i],
+				rte_strerror(-rc));
+		}
+	}
+
+	return 0;
+}
+
 static int sfc_eth_dev_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	struct rte_pci_device *pci_dev)
 {
-	return rte_eth_dev_pci_generic_probe(pci_dev,
-		sizeof(struct sfc_adapter_shared), sfc_eth_dev_init);
+	struct sfc_ethdev_init_data init_data;
+	struct rte_eth_devargs eth_da;
+	struct rte_eth_dev *dev;
+	int rc;
+
+	if (pci_dev->device.devargs != NULL) {
+		rc = sfc_parse_rte_devargs(pci_dev->device.devargs->args,
+					   &eth_da);
+		if (rc != 0)
+			return rc;
+	} else {
+		memset(&eth_da, 0, sizeof(eth_da));
+	}
+
+	init_data.nb_representors = eth_da.nb_representor_ports;
+
+	if (eth_da.nb_representor_ports > 0 &&
+	    rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		SFC_GENERIC_LOG(ERR,
+			"Create representors from secondary process not supported, dev '%s'",
+			pci_dev->device.name);
+		return -ENOTSUP;
+	}
+
+	rc = sfc_eth_dev_create(pci_dev, &init_data, &dev);
+	if (rc != 0)
+		return rc;
+
+	rc = sfc_eth_dev_create_representors(dev, &eth_da);
+	if (rc != 0) {
+		(void)rte_eth_dev_destroy(dev, sfc_eth_dev_uninit);
+		return rc;
+	}
+
+	return 0;
 }
 
 static int sfc_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
diff --git a/drivers/net/sfc/sfc_kvargs.c b/drivers/net/sfc/sfc_kvargs.c
index cd16213637..783cb43ae6 100644
--- a/drivers/net/sfc/sfc_kvargs.c
+++ b/drivers/net/sfc/sfc_kvargs.c
@@ -23,6 +23,7 @@ sfc_kvargs_parse(struct sfc_adapter *sa)
 	struct rte_devargs *devargs = eth_dev->device->devargs;
 	const char **params = (const char *[]){
 		SFC_KVARG_SWITCH_MODE,
+		SFC_KVARG_REPRESENTOR,
 		SFC_KVARG_STATS_UPDATE_PERIOD_MS,
 		SFC_KVARG_PERF_PROFILE,
 		SFC_KVARG_RX_DATAPATH,
diff --git a/drivers/net/sfc/sfc_kvargs.h b/drivers/net/sfc/sfc_kvargs.h
index 8e34ec92a2..2226f2b3d9 100644
--- a/drivers/net/sfc/sfc_kvargs.h
+++ b/drivers/net/sfc/sfc_kvargs.h
@@ -26,6 +26,8 @@ extern "C" {
 	"[" SFC_KVARG_SWITCH_MODE_LEGACY "|" \
 	    SFC_KVARG_SWITCH_MODE_SWITCHDEV "]"
 
+#define SFC_KVARG_REPRESENTOR		"representor"
+
 #define SFC_KVARG_PERF_PROFILE		"perf_profile"
 
 #define SFC_KVARG_PERF_PROFILE_AUTO		"auto"
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
new file mode 100644
index 0000000000..603a613ec6
--- /dev/null
+++ b/drivers/net/sfc/sfc_repr.c
@@ -0,0 +1,458 @@
+/* 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.
+ */
+
+#include <stdint.h>
+
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <ethdev_driver.h>
+
+#include "efx.h"
+
+#include "sfc_log.h"
+#include "sfc_debug.h"
+#include "sfc_repr.h"
+#include "sfc_ethdev_state.h"
+#include "sfc_switch.h"
+
+/** Multi-process shared representor private data */
+struct sfc_repr_shared {
+	uint16_t		pf_port_id;
+	uint16_t		repr_id;
+	uint16_t		switch_domain_id;
+	uint16_t		switch_port_id;
+};
+
+/** Primary process representor private data */
+struct sfc_repr {
+	/**
+	 * PMD setup and configuration is not thread safe. Since it is not
+	 * performance sensitive, it is better to guarantee thread-safety
+	 * and add device level lock. Adapter control operations which
+	 * change its state should acquire the lock.
+	 */
+	rte_spinlock_t			lock;
+	enum sfc_ethdev_state		state;
+};
+
+#define sfcr_err(sr, ...) \
+	do {								\
+		const struct sfc_repr *_sr = (sr);			\
+									\
+		(void)_sr;						\
+		SFC_GENERIC_LOG(ERR, __VA_ARGS__);			\
+	} while (0)
+
+#define sfcr_info(sr, ...) \
+	do {								\
+		const struct sfc_repr *_sr = (sr);			\
+									\
+		(void)_sr;						\
+		SFC_GENERIC_LOG(INFO,					\
+				RTE_FMT("%s() "				\
+				RTE_FMT_HEAD(__VA_ARGS__ ,),		\
+				__func__,				\
+				RTE_FMT_TAIL(__VA_ARGS__ ,)));		\
+	} while (0)
+
+static inline struct sfc_repr_shared *
+sfc_repr_shared_by_eth_dev(struct rte_eth_dev *eth_dev)
+{
+	struct sfc_repr_shared *srs = eth_dev->data->dev_private;
+
+	return srs;
+}
+
+static inline struct sfc_repr *
+sfc_repr_by_eth_dev(struct rte_eth_dev *eth_dev)
+{
+	struct sfc_repr *sr = eth_dev->process_private;
+
+	return sr;
+}
+
+/*
+ * Add wrapper functions to acquire/release lock to be able to remove or
+ * change the lock in one place.
+ */
+
+static inline void
+sfc_repr_lock_init(struct sfc_repr *sr)
+{
+	rte_spinlock_init(&sr->lock);
+}
+
+#ifdef RTE_LIBRTE_SFC_EFX_DEBUG
+
+static inline int
+sfc_repr_lock_is_locked(struct sfc_repr *sr)
+{
+	return rte_spinlock_is_locked(&sr->lock);
+}
+
+#endif
+
+static inline void
+sfc_repr_lock(struct sfc_repr *sr)
+{
+	rte_spinlock_lock(&sr->lock);
+}
+
+static inline void
+sfc_repr_unlock(struct sfc_repr *sr)
+{
+	rte_spinlock_unlock(&sr->lock);
+}
+
+static inline void
+sfc_repr_lock_fini(__rte_unused struct sfc_repr *sr)
+{
+	/* Just for symmetry of the API */
+}
+
+static int
+sfc_repr_check_conf(struct sfc_repr *sr, uint16_t nb_rx_queues,
+		    const struct rte_eth_conf *conf)
+{
+	const struct rte_eth_rss_conf *rss_conf;
+	int ret = 0;
+
+	sfcr_info(sr, "entry");
+
+	if (conf->link_speeds != 0) {
+		sfcr_err(sr, "specific link speeds not supported");
+		ret = -EINVAL;
+	}
+
+	switch (conf->rxmode.mq_mode) {
+	case ETH_MQ_RX_RSS:
+		if (nb_rx_queues != 1) {
+			sfcr_err(sr, "Rx RSS is not supported with %u queues",
+				 nb_rx_queues);
+			ret = -EINVAL;
+			break;
+		}
+
+		rss_conf = &conf->rx_adv_conf.rss_conf;
+		if (rss_conf->rss_key != NULL || rss_conf->rss_key_len != 0 ||
+		    rss_conf->rss_hf != 0) {
+			sfcr_err(sr, "Rx RSS configuration is not supported");
+			ret = -EINVAL;
+		}
+		break;
+	case ETH_MQ_RX_NONE:
+		break;
+	default:
+		sfcr_err(sr, "Rx mode MQ modes other than RSS not supported");
+		ret = -EINVAL;
+		break;
+	}
+
+	if (conf->txmode.mq_mode != ETH_MQ_TX_NONE) {
+		sfcr_err(sr, "Tx mode MQ modes not supported");
+		ret = -EINVAL;
+	}
+
+	if (conf->lpbk_mode != 0) {
+		sfcr_err(sr, "loopback not supported");
+		ret = -EINVAL;
+	}
+
+	if (conf->dcb_capability_en != 0) {
+		sfcr_err(sr, "priority-based flow control not supported");
+		ret = -EINVAL;
+	}
+
+	if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) {
+		sfcr_err(sr, "Flow Director not supported");
+		ret = -EINVAL;
+	}
+
+	if (conf->intr_conf.lsc != 0) {
+		sfcr_err(sr, "link status change interrupt not supported");
+		ret = -EINVAL;
+	}
+
+	if (conf->intr_conf.rxq != 0) {
+		sfcr_err(sr, "receive queue interrupt not supported");
+		ret = -EINVAL;
+	}
+
+	if (conf->intr_conf.rmv != 0) {
+		sfcr_err(sr, "remove interrupt not supported");
+		ret = -EINVAL;
+	}
+
+	sfcr_info(sr, "done %d", ret);
+
+	return ret;
+}
+
+
+static int
+sfc_repr_configure(struct sfc_repr *sr, uint16_t nb_rx_queues,
+		   const struct rte_eth_conf *conf)
+{
+	int ret;
+
+	sfcr_info(sr, "entry");
+
+	SFC_ASSERT(sfc_repr_lock_is_locked(sr));
+
+	ret = sfc_repr_check_conf(sr, nb_rx_queues, conf);
+	if (ret != 0)
+		goto fail_check_conf;
+
+	sr->state = SFC_ETHDEV_CONFIGURED;
+
+	sfcr_info(sr, "done");
+
+	return 0;
+
+fail_check_conf:
+	sfcr_info(sr, "failed %s", rte_strerror(-ret));
+	return ret;
+}
+
+static int
+sfc_repr_dev_configure(struct rte_eth_dev *dev)
+{
+	struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
+	struct rte_eth_dev_data *dev_data = dev->data;
+	int ret;
+
+	sfcr_info(sr, "entry n_rxq=%u n_txq=%u",
+		  dev_data->nb_rx_queues, dev_data->nb_tx_queues);
+
+	sfc_repr_lock(sr);
+	switch (sr->state) {
+	case SFC_ETHDEV_CONFIGURED:
+		/* FALLTHROUGH */
+	case SFC_ETHDEV_INITIALIZED:
+		ret = sfc_repr_configure(sr, dev_data->nb_rx_queues,
+					 &dev_data->dev_conf);
+		break;
+	default:
+		sfcr_err(sr, "unexpected adapter state %u to configure",
+			 sr->state);
+		ret = -EINVAL;
+		break;
+	}
+	sfc_repr_unlock(sr);
+
+	sfcr_info(sr, "done %s", rte_strerror(-ret));
+
+	return ret;
+}
+
+static int
+sfc_repr_dev_infos_get(struct rte_eth_dev *dev,
+		       struct rte_eth_dev_info *dev_info)
+{
+	struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
+
+	dev_info->device = dev->device;
+
+	dev_info->max_rx_queues = SFC_REPR_RXQ_MAX;
+	dev_info->max_tx_queues = SFC_REPR_TXQ_MAX;
+	dev_info->default_rxconf.rx_drop_en = 1;
+	dev_info->switch_info.domain_id = srs->switch_domain_id;
+	dev_info->switch_info.port_id = srs->switch_port_id;
+
+	return 0;
+}
+
+static void
+sfc_repr_close(struct sfc_repr *sr)
+{
+	SFC_ASSERT(sfc_repr_lock_is_locked(sr));
+
+	SFC_ASSERT(sr->state == SFC_ETHDEV_CONFIGURED);
+	sr->state = SFC_ETHDEV_CLOSING;
+
+	/* Put representor close actions here */
+
+	sr->state = SFC_ETHDEV_INITIALIZED;
+}
+
+static int
+sfc_repr_dev_close(struct rte_eth_dev *dev)
+{
+	struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
+
+	sfcr_info(sr, "entry");
+
+	sfc_repr_lock(sr);
+	switch (sr->state) {
+	case SFC_ETHDEV_CONFIGURED:
+		sfc_repr_close(sr);
+		SFC_ASSERT(sr->state == SFC_ETHDEV_INITIALIZED);
+		/* FALLTHROUGH */
+	case SFC_ETHDEV_INITIALIZED:
+		break;
+	default:
+		sfcr_err(sr, "unexpected adapter state %u on close", sr->state);
+		break;
+	}
+
+	/*
+	 * Cleanup all resources.
+	 * Rollback primary process sfc_repr_eth_dev_init() below.
+	 */
+
+	dev->dev_ops = NULL;
+
+	sfc_repr_unlock(sr);
+	sfc_repr_lock_fini(sr);
+
+	sfcr_info(sr, "done");
+
+	free(sr);
+
+	return 0;
+}
+
+static const struct eth_dev_ops sfc_repr_dev_ops = {
+	.dev_configure			= sfc_repr_dev_configure,
+	.dev_close			= sfc_repr_dev_close,
+	.dev_infos_get			= sfc_repr_dev_infos_get,
+};
+
+
+struct sfc_repr_init_data {
+	uint16_t		pf_port_id;
+	uint16_t		repr_id;
+	uint16_t		switch_domain_id;
+	efx_mport_sel_t		mport_sel;
+};
+
+static int
+sfc_repr_assign_mae_switch_port(uint16_t switch_domain_id,
+				const struct sfc_mae_switch_port_request *req,
+				uint16_t *switch_port_id)
+{
+	int rc;
+
+	rc = sfc_mae_assign_switch_port(switch_domain_id, req, switch_port_id);
+
+	SFC_ASSERT(rc >= 0);
+	return -rc;
+}
+
+static int
+sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
+{
+	const struct sfc_repr_init_data *repr_data = init_params;
+	struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
+	struct sfc_mae_switch_port_request switch_port_request;
+	efx_mport_sel_t ethdev_mport_sel;
+	struct sfc_repr *sr;
+	int ret;
+
+	/*
+	 * Currently there is no mport we can use for representor's
+	 * ethdev. Use an invalid one for now. This way representors
+	 * can be instantiated.
+	 */
+	efx_mae_mport_invalid(&ethdev_mport_sel);
+
+	memset(&switch_port_request, 0, sizeof(switch_port_request));
+	switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
+	switch_port_request.ethdev_mportp = &ethdev_mport_sel;
+	switch_port_request.entity_mportp = &repr_data->mport_sel;
+	switch_port_request.ethdev_port_id = dev->data->port_id;
+
+	ret = sfc_repr_assign_mae_switch_port(repr_data->switch_domain_id,
+					      &switch_port_request,
+					      &srs->switch_port_id);
+	if (ret != 0) {
+		SFC_GENERIC_LOG(ERR,
+			"%s() failed to assign MAE switch port (domain id %u)",
+			__func__, repr_data->switch_domain_id);
+		goto fail_mae_assign_switch_port;
+	}
+
+	/*
+	 * Allocate process private data from heap, since it should not
+	 * be located in shared memory allocated using rte_malloc() API.
+	 */
+	sr = calloc(1, sizeof(*sr));
+	if (sr == NULL) {
+		ret = -ENOMEM;
+		goto fail_alloc_sr;
+	}
+
+	sfc_repr_lock_init(sr);
+	sfc_repr_lock(sr);
+
+	dev->process_private = sr;
+
+	srs->pf_port_id = repr_data->pf_port_id;
+	srs->repr_id = repr_data->repr_id;
+	srs->switch_domain_id = repr_data->switch_domain_id;
+
+	dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
+	dev->data->representor_id = srs->repr_id;
+	dev->data->parent_port_id = srs->pf_port_id;
+
+	dev->data->mac_addrs = rte_zmalloc("sfcr", RTE_ETHER_ADDR_LEN, 0);
+	if (dev->data->mac_addrs == NULL) {
+		ret = -ENOMEM;
+		goto fail_mac_addrs;
+	}
+
+	dev->dev_ops = &sfc_repr_dev_ops;
+
+	sr->state = SFC_ETHDEV_INITIALIZED;
+	sfc_repr_unlock(sr);
+
+	return 0;
+
+fail_mac_addrs:
+	sfc_repr_unlock(sr);
+	free(sr);
+
+fail_alloc_sr:
+fail_mae_assign_switch_port:
+	SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
+	return ret;
+}
+
+int
+sfc_repr_create(struct rte_eth_dev *parent, uint16_t representor_id,
+		uint16_t switch_domain_id, const efx_mport_sel_t *mport_sel)
+{
+	struct sfc_repr_init_data repr_data;
+	char name[RTE_ETH_NAME_MAX_LEN];
+	int ret;
+
+	if (snprintf(name, sizeof(name), "net_%s_representor_%u",
+		     parent->device->name, representor_id) >=
+			(int)sizeof(name)) {
+		SFC_GENERIC_LOG(ERR, "%s() failed name too long", __func__);
+		return -ENAMETOOLONG;
+	}
+
+	memset(&repr_data, 0, sizeof(repr_data));
+	repr_data.pf_port_id = parent->data->port_id;
+	repr_data.repr_id = representor_id;
+	repr_data.switch_domain_id = switch_domain_id;
+	repr_data.mport_sel = *mport_sel;
+
+	ret = rte_eth_dev_create(parent->device, name,
+				  sizeof(struct sfc_repr_shared),
+				  NULL, NULL,
+				  sfc_repr_eth_dev_init, &repr_data);
+	if (ret != 0)
+		SFC_GENERIC_LOG(ERR, "%s() failed to create device", __func__);
+
+	SFC_GENERIC_LOG(INFO, "%s() done: %s", __func__, rte_strerror(-ret));
+
+	return ret;
+}
diff --git a/drivers/net/sfc/sfc_repr.h b/drivers/net/sfc/sfc_repr.h
new file mode 100644
index 0000000000..1347206006
--- /dev/null
+++ b/drivers/net/sfc/sfc_repr.h
@@ -0,0 +1,36 @@
+/* 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_H
+#define _SFC_REPR_H
+
+#include <stdint.h>
+
+#include <rte_ethdev.h>
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Max count of the representor Rx queues */
+#define SFC_REPR_RXQ_MAX	1
+
+/** Max count of the representor Tx queues */
+#define SFC_REPR_TXQ_MAX	1
+
+int sfc_repr_create(struct rte_eth_dev *parent, uint16_t representor_id,
+		    uint16_t switch_domain_id,
+		    const efx_mport_sel_t *mport_sel);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  /* _SFC_REPR_H */
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index 84a02a61f8..a1a2ab9848 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -27,6 +27,11 @@ enum sfc_mae_switch_port_type {
 	 * and thus refers to its underlying PCIe function
 	 */
 	SFC_MAE_SWITCH_PORT_INDEPENDENT = 0,
+	/**
+	 * The switch port is operated by a representor RTE ethdev
+	 * and thus refers to the represented PCIe function
+	 */
+	SFC_MAE_SWITCH_PORT_REPRESENTOR,
 };
 
 struct sfc_mae_switch_port_request {
-- 
2.30.2


  parent reply	other threads:[~2021-08-27  6:58 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-27  6:56 [dpdk-dev] [PATCH 00/38] net/sfc: support port representors Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 01/38] common/sfc_efx/base: update MCDI headers Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 02/38] common/sfc_efx/base: update EF100 registers definitions Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 03/38] net/sfc: add switch mode device argument Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 04/38] net/sfc: insert switchdev mode MAE rules Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 05/38] common/sfc_efx/base: add an API to get mport ID by selector Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 06/38] net/sfc: support EF100 Tx override prefix Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 07/38] net/sfc: add representors proxy infrastructure Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 08/38] net/sfc: reserve TxQ and RxQ for port representors Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 09/38] net/sfc: move adapter state enum to separate header Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 10/38] common/sfc_efx/base: allow creating invalid mport selectors Andrew Rybchenko
2021-08-27  6:56 ` Andrew Rybchenko [this message]
2021-08-27  6:56 ` [dpdk-dev] [PATCH 12/38] common/sfc_efx/base: add filter ingress mport matching field Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 13/38] common/sfc_efx/base: add API to get mport selector by ID Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 14/38] common/sfc_efx/base: add mport alias MCDI wrappers Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 15/38] net/sfc: add representor proxy port API Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 16/38] net/sfc: implement representor queue setup and release Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 17/38] net/sfc: implement representor RxQ start/stop Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 18/38] net/sfc: implement representor TxQ start/stop Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 19/38] net/sfc: implement port representor start and stop Andrew Rybchenko
2021-08-27  6:56 ` [dpdk-dev] [PATCH 20/38] net/sfc: implement port representor link update Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 21/38] net/sfc: support multiple device probe Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 22/38] net/sfc: implement representor Tx routine Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 23/38] net/sfc: use xword type for EF100 Rx prefix Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 24/38] net/sfc: handle ingress m-port in " Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 25/38] net/sfc: implement representor Rx routine Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 26/38] net/sfc: add simple port representor statistics Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 27/38] net/sfc: free MAE lock once switch domain is assigned Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 28/38] common/sfc_efx/base: add multi-host function M-port selector Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 29/38] common/sfc_efx/base: retrieve function interfaces for VNICs Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 30/38] common/sfc_efx/base: add a means to read MAE mport journal Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 31/38] common/sfc_efx/base: allow getting VNIC MCDI client handles Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 32/38] net/sfc: maintain controller to EFX interface mapping Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 33/38] net/sfc: store PCI address for represented entities Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 34/38] net/sfc: include controller and port in representor name Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 35/38] net/sfc: support new representor parameter syntax Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 36/38] net/sfc: use switch port ID as representor ID Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 37/38] net/sfc: implement the representor info API Andrew Rybchenko
2021-08-27  6:57 ` [dpdk-dev] [PATCH 38/38] net/sfc: update comment about representor support Andrew Rybchenko
2021-10-11 14:48 ` [dpdk-dev] [PATCH v2 00/38] net/sfc: support port representors Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 01/38] common/sfc_efx/base: update MCDI headers Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 02/38] common/sfc_efx/base: update EF100 registers definitions Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 03/38] net/sfc: add switch mode device argument Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 04/38] net/sfc: insert switchdev mode MAE rules Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 05/38] common/sfc_efx/base: add an API to get mport ID by selector Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 06/38] net/sfc: support EF100 Tx override prefix Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 07/38] net/sfc: add representors proxy infrastructure Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 08/38] net/sfc: reserve TxQ and RxQ for port representors Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 09/38] net/sfc: move adapter state enum to separate header Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 10/38] common/sfc_efx/base: allow creating invalid mport selectors Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 11/38] net/sfc: add port representors infrastructure Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 12/38] common/sfc_efx/base: add filter ingress mport matching field Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 13/38] common/sfc_efx/base: add API to get mport selector by ID Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 14/38] common/sfc_efx/base: add mport alias MCDI wrappers Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 15/38] net/sfc: add representor proxy port API Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 16/38] net/sfc: implement representor queue setup and release Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 17/38] net/sfc: implement representor RxQ start/stop Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 18/38] net/sfc: implement representor TxQ start/stop Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 19/38] net/sfc: implement port representor start and stop Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 20/38] net/sfc: implement port representor link update Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 21/38] net/sfc: support multiple device probe Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 22/38] net/sfc: implement representor Tx routine Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 23/38] net/sfc: use xword type for EF100 Rx prefix Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 24/38] net/sfc: handle ingress m-port in " Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 25/38] net/sfc: implement representor Rx routine Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 26/38] net/sfc: add simple port representor statistics Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 27/38] net/sfc: free MAE lock once switch domain is assigned Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 28/38] common/sfc_efx/base: add multi-host function M-port selector Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 29/38] common/sfc_efx/base: retrieve function interfaces for VNICs Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 30/38] common/sfc_efx/base: add a means to read MAE mport journal Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 31/38] common/sfc_efx/base: allow getting VNIC MCDI client handles Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 32/38] net/sfc: maintain controller to EFX interface mapping Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 33/38] net/sfc: store PCI address for represented entities Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 34/38] net/sfc: include controller and port in representor name Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 35/38] net/sfc: support new representor parameter syntax Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 36/38] net/sfc: use switch port ID as representor ID Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 37/38] net/sfc: implement the representor info API Andrew Rybchenko
2021-10-11 14:48   ` [dpdk-dev] [PATCH v2 38/38] net/sfc: update comment about representor support Andrew Rybchenko
2021-10-12 16:45   ` [dpdk-dev] [PATCH v2 00/38] net/sfc: support port representors Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210827065717.1838258-12-andrew.rybchenko@oktetlabs.ru \
    --to=andrew.rybchenko@oktetlabs.ru \
    --cc=amoreton@xilinx.com \
    --cc=dev@dpdk.org \
    --cc=igor.romanov@oktetlabs.ru \
    --cc=ivan.malov@oktetlabs.ru \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git