All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Marginean <alexandru.marginean@nxp.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 2/6] drivers: net: add a DSA sandbox driver
Date: Mon, 25 Nov 2019 17:53:12 +0200	[thread overview]
Message-ID: <20191125155316.12744-3-alexandru.marginean@nxp.com> (raw)
In-Reply-To: <20191125155316.12744-1-alexandru.marginean@nxp.com>

The DSA sandbox driver is used for DSA unit testing.  It implements a
simple 4 port switch that uses a very simple tag to identify the ports.
The DSA driver comes paired with an Ethernet driver that loops packets
back and can selectively filter traffic on DSA switch ports.

Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
---
 drivers/net/Kconfig       |   8 ++
 drivers/net/Makefile      |   1 +
 drivers/net/dsa_sandbox.c | 272 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 281 insertions(+)
 create mode 100644 drivers/net/dsa_sandbox.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index a4157cb122..ac420cb474 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -70,6 +70,14 @@ config MDIO_MUX_SANDBOX
 
 	  This driver is used for testing in test/dm/mdio.c
 
+config DSA_SANDBOX
+	depends on DM_DSA && SANDBOX
+	default y
+	bool "Sandbox: Mocked DSA driver"
+	help
+	  This driver implements a dummy switch and a dummy Ethernet device used
+	  to test DSA class code.
+
 menuconfig NETDEVICES
 	bool "Network device support"
 	depends on NET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 30991834ec..8be49f6335 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -82,3 +82,4 @@ obj-y += mscc_eswitch/
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o
 obj-$(CONFIG_FSL_ENETC) += fsl_enetc.o fsl_enetc_mdio.o
+obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
diff --git a/drivers/net/dsa_sandbox.c b/drivers/net/dsa_sandbox.c
new file mode 100644
index 0000000000..07230eb033
--- /dev/null
+++ b/drivers/net/dsa_sandbox.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 NXP
+ */
+
+#include <dsa.h>
+
+#define DSA_SANDBOX_MAGIC	0x00415344
+#define DSA_SANDBOX_TAG_LEN	sizeof(struct dsa_sandbox_tag)
+/*
+ * This global flag is used to enable DSA just for DSA test so it doesn't affect
+ * the existing eth unit test.
+ */
+int dsa_sandbox_port_mask;
+
+struct dsa_sandbox_priv {
+	int enabled;
+	int port_enabled;
+};
+
+struct dsa_sandbox_tag {
+	u32 magic;
+	u32 port;
+};
+
+static int dsa_sandbox_port_enable(struct udevice *dev, int port,
+				   struct phy_device *phy)
+{
+	struct dsa_sandbox_priv *priv = dev->priv;
+
+	if (!priv->enabled)
+		return -EFAULT;
+
+	priv->port_enabled |= BIT(port);
+
+	return 0;
+}
+
+static void dsa_sandbox_port_disable(struct udevice *dev, int port,
+				     struct phy_device *phy)
+{
+	struct dsa_sandbox_priv *priv = dev->priv;
+
+	if (!priv->enabled)
+		return;
+
+	priv->port_enabled &= ~BIT(port);
+}
+
+static int dsa_sandbox_xmit(struct udevice *dev, int port, void *packet,
+			    int length)
+{
+	struct dsa_sandbox_priv *priv = dev->priv;
+	struct dsa_sandbox_tag *tag = packet;
+
+	if (!priv->enabled)
+		return -EFAULT;
+
+	if (!(priv->port_enabled & BIT(port)))
+		return -EFAULT;
+
+	tag->magic = DSA_SANDBOX_MAGIC;
+	tag->port = port;
+
+	return 0;
+}
+
+static int dsa_sandbox_rcv(struct udevice *dev, int *port, void *packet,
+			   int length)
+{
+	struct dsa_sandbox_priv *priv = dev->priv;
+	struct dsa_sandbox_tag *tag = packet;
+
+	if (!priv->enabled)
+		return -EFAULT;
+
+	if (tag->magic != DSA_SANDBOX_MAGIC)
+		return -EFAULT;
+
+	*port = tag->port;
+	if (!(priv->port_enabled & BIT(*port)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static const struct dsa_ops dsa_sandbox_ops = {
+	.port_enable = dsa_sandbox_port_enable,
+	.port_disable = dsa_sandbox_port_disable,
+	.xmit = dsa_sandbox_xmit,
+	.rcv = dsa_sandbox_rcv,
+};
+
+static int dsa_sandbox_bind(struct udevice *dev)
+{
+	struct dsa_perdev_platdata *pdata = dev->platdata;
+
+	/* must be at least 4 to match sandbox test DT */
+	pdata->num_ports = 4;
+	pdata->headroom = DSA_SANDBOX_TAG_LEN;
+
+	return 0;
+}
+
+static int dsa_sandbox_probe(struct udevice *dev)
+{
+	struct dsa_sandbox_priv *priv = dev_get_priv(dev);
+
+	/*
+	 * return error if DSA is not being tested so we don't break existing
+	 * eth test.
+	 */
+	if (!dsa_sandbox_port_mask)
+		return -EINVAL;
+
+	priv->enabled = 1;
+
+	return 0;
+}
+
+static int dsa_sandbox_remove(struct udevice *dev)
+{
+	struct dsa_sandbox_priv *priv = dev_get_priv(dev);
+
+	priv->enabled = 0;
+
+	return 0;
+}
+
+static const struct udevice_id dsa_sandbox_ids[] = {
+	{ .compatible = "sandbox,dsa" },
+	{ }
+};
+
+U_BOOT_DRIVER(dsa_sandbox) = {
+	.name		= "dsa_sandbox",
+	.id		= UCLASS_DSA,
+	.of_match	= dsa_sandbox_ids,
+	.bind		= dsa_sandbox_bind,
+	.probe		= dsa_sandbox_probe,
+	.remove		= dsa_sandbox_remove,
+	.ops		= &dsa_sandbox_ops,
+	.priv_auto_alloc_size = sizeof(struct dsa_sandbox_priv),
+	.platdata_auto_alloc_size = sizeof(struct dsa_perdev_platdata),
+};
+
+struct dsa_sandbox_eth_priv {
+	int enabled;
+	int started;
+	int packet_length;
+	uchar packet[DSA_MAX_FRAME_SIZE];
+};
+
+static int dsa_eth_sandbox_start(struct udevice *dev)
+{
+	struct dsa_sandbox_eth_priv *priv = dev->priv;
+
+	if (!priv->enabled)
+		return -EFAULT;
+
+	priv->started = 1;
+
+	return 0;
+}
+
+static void dsa_eth_sandbox_stop(struct udevice *dev)
+{
+	struct dsa_sandbox_eth_priv *priv = dev->priv;
+
+	if (!priv->enabled)
+		return;
+
+	priv->started = 0;
+}
+
+static int dsa_eth_sandbox_send(struct udevice *dev, void *packet, int length)
+{
+	struct dsa_sandbox_eth_priv *priv = dev->priv;
+	struct dsa_sandbox_tag *tag = packet;
+
+	if (!priv->enabled || !priv->started)
+		return -EFAULT;
+
+	memcpy(priv->packet, packet, length);
+	priv->packet_length = length;
+
+	/*
+	 * for DSA test frames we only respond if the associated port is enabled
+	 * in the dsa test port mask
+	 */
+
+	if (tag->magic == DSA_SANDBOX_MAGIC) {
+		int port = tag->port;
+
+		if (!(dsa_sandbox_port_mask & BIT(port)))
+			/* drop the frame, port is not enabled */
+			priv->packet_length = 0;
+	}
+
+	return 0;
+}
+
+static int dsa_eth_sandbox_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct dsa_sandbox_eth_priv *priv = dev->priv;
+	int length = priv->packet_length;
+
+	if (!priv->enabled || !priv->started)
+		return -EFAULT;
+
+	if (!length) {
+		/* no frames pending, force a time-out */
+		timer_test_add_offset(100);
+		return -EAGAIN;
+	}
+
+	*packetp = priv->packet;
+	priv->packet_length = 0;
+
+	return length;
+}
+
+static const struct eth_ops dsa_eth_sandbox_ops = {
+	.start	= dsa_eth_sandbox_start,
+	.send	= dsa_eth_sandbox_send,
+	.recv	= dsa_eth_sandbox_recv,
+	.stop	= dsa_eth_sandbox_stop,
+};
+
+static int dsa_eth_sandbox_bind(struct udevice *dev)
+{
+	return 0;
+}
+
+static int dsa_eth_sandbox_probe(struct udevice *dev)
+{
+	struct dsa_sandbox_eth_priv *priv = dev->priv;
+
+	priv->enabled = 1;
+
+	/*
+	 * return error if DSA is not being tested do we don't break existing
+	 * eth test.
+	 */
+	return dsa_sandbox_port_mask ? 0 : -EINVAL;
+}
+
+static int dsa_eth_sandbox_remove(struct udevice *dev)
+{
+	struct dsa_sandbox_eth_priv *priv = dev->priv;
+
+	priv->enabled = 0;
+
+	return 0;
+}
+
+static const struct udevice_id dsa_eth_sandbox_ids[] = {
+	{ .compatible = "sandbox,dsa-eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(dsa_eth_sandbox) = {
+	.name		= "dsa_eth_sandbox",
+	.id		= UCLASS_ETH,
+	.of_match	= dsa_eth_sandbox_ids,
+	.bind		= dsa_eth_sandbox_bind,
+	.probe		= dsa_eth_sandbox_probe,
+	.remove		= dsa_eth_sandbox_remove,
+	.ops		= &dsa_eth_sandbox_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct dsa_sandbox_eth_priv),
+};
-- 
2.17.1

  parent reply	other threads:[~2019-11-25 15:53 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-25 15:53 [U-Boot] [PATCH v2 0/6] Introduce DSA Ethernet switch class and Felix driver Alex Marginean
2019-11-25 15:53 ` [U-Boot] [PATCH v2 1/6] net: introduce DSA class for Ethernet switches Alex Marginean
2019-11-30  0:56   ` Joe Hershberger
2019-12-01  2:21     ` Alexandru Marginean
2019-12-01  4:17       ` Florian Fainelli
2019-12-02 12:59         ` Alexandru Marginean
2019-11-25 15:53 ` Alex Marginean [this message]
2019-11-25 15:53 ` [U-Boot] [PATCH v2 3/6] test: dm: add a simple unit test for DSA class Alex Marginean
2019-11-25 15:53 ` [U-Boot] [PATCH v2 4/6] drivers: net: add Felix DSA switch driver Alex Marginean
2019-11-25 15:53 ` [U-Boot] [PATCH v2 5/6] arm: dts: ls1028a: adds Ethernet switch node and its dependencies Alex Marginean
2019-11-25 15:53 ` [U-Boot] [PATCH v2 6/6] configs: ls1028a: enable the Ethernet switch driver in defconfig Alex Marginean

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=20191125155316.12744-3-alexandru.marginean@nxp.com \
    --to=alexandru.marginean@nxp.com \
    --cc=u-boot@lists.denx.de \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.