All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Sandbox driver for DSA uclass
@ 2021-02-16 22:48 Vladimir Oltean
  2021-02-16 22:48 ` [PATCH 1/4] net: phy: fixed: be compatible with live OF tree Vladimir Oltean
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Vladimir Oltean @ 2021-02-16 22:48 UTC (permalink / raw)
  To: u-boot

From: Vladimir Oltean <vladimir.oltean@nxp.com>

This is a spin-off of the larger patch series for DSA in U-Boot:
https://patchwork.ozlabs.org/project/uboot/cover/20210125122357.414742-1-olteanv at gmail.com/

There is currently an issue which prevents DSA from working properly
with the sandbox: the sandbox uses CONFIG_OF_LIVE, and DSA has a
dependency in CONFIG_FIXED_PHY which is broken with CONFIG_OF_LIVE.

At Tom Rini's request, the DSA patches were merged without support for
sandbox, and here we are now, submitting them separately.

Claudiu Manoil (1):
  sandbox: add a DSA sandbox driver and unit test

Vladimir Oltean (3):
  net: phy: fixed: be compatible with live OF tree
  net: phy: drop #ifdef CONFIG_DM_ETH around phy_connect_fixed
  net: mdio: teach dm_eth_phy_connect to connect to fixed PHY

 arch/Kconfig              |   2 +
 arch/sandbox/dts/test.dts |  48 ++++++++++
 drivers/net/Kconfig       |   9 ++
 drivers/net/Makefile      |   1 +
 drivers/net/dsa_sandbox.c | 179 ++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/fixed.c   |  30 +++++--
 drivers/net/phy/phy.c     |  36 ++++----
 drivers/net/tsec.c        |   6 +-
 include/configs/sandbox.h |   2 +
 net/mdio-uclass.c         |  12 ++-
 test/dm/Makefile          |   1 +
 test/dm/dsa.c             |  82 +++++++++++++++++
 test/dm/eth.c             |  10 +--
 13 files changed, 377 insertions(+), 41 deletions(-)
 create mode 100644 drivers/net/dsa_sandbox.c
 create mode 100644 test/dm/dsa.c

-- 
2.25.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] net: phy: fixed: be compatible with live OF tree
  2021-02-16 22:48 [PATCH 0/4] Sandbox driver for DSA uclass Vladimir Oltean
@ 2021-02-16 22:48 ` Vladimir Oltean
  2021-03-12  6:34   ` Bin Meng
  2021-02-16 22:48 ` [PATCH 2/4] net: phy: drop #ifdef CONFIG_DM_ETH around phy_connect_fixed Vladimir Oltean
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Vladimir Oltean @ 2021-02-16 22:48 UTC (permalink / raw)
  To: u-boot

From: Vladimir Oltean <vladimir.oltean@nxp.com>

On systems that use CONFIG_OF_LIVE, the "ofnode" type is defined as
const struct device_node *np, while on the flat DT systems it is defined
as a long of_offset into gd->fdt_blob.

It is desirable that the fixed PHY driver uses the higher-level ofnode
abstraction instead of parsing gd->fdt_blob directly, because that
enables it to work on live OF systems.

The fixed PHY driver has used a nastyyyyy hack since its introduction in
commit db40c1aa1c10 ("drivers/net/phy: add fixed-phy / fixed-link support"),
which is to pass the long gd->fdt_blob offset inside int phydev->addr
(a value that normally holds the MDIO bus address at which the PHY
responds). Even ignoring the fact that the types were already mismatched
leading to a potential truncation (flat OF offset was supposed to be a
long and not an int), we really cannot extend this hack any longer,
because there's no way an int will hold the other representation of
ofnode, the struct device_node *np.

So we unfortunately need to do the right thing, which is to use the
framework introduced by Grygorii Strashko in commit eef0b8a930d1 ("net:
phy: add ofnode node to struct phy_device"). This will populate
phydev->node for the fixed PHY.

Note that phydev->node will not be valid in the probe function, since
that is called synchronously from phy_device_create and we really have
no way of passing the ofnode directly through the phy_device_create API.
So we do what other drivers do too: we move the OF parsing logic from
the .probe to the .config method of the PHY driver. The new function
will be called at phy_config() time.

I do believe I've converted all the possible call paths for creating a
PHY with PHY_FIXED_ID, so there is really no reason to maintain
compatibility with the old logic of retrieving a flat OF tree offset
from phydev->addr. We just pass 0 to phydev->addr now.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/fixed.c | 30 ++++++++++++++++++++++--------
 drivers/net/phy/phy.c   | 30 +++++++++++++++---------------
 2 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 1a38c29469a4..d67c22a7b8c7 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -15,15 +15,17 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int fixedphy_probe(struct phy_device *phydev)
+static int fixedphy_of_init(struct phy_device *phydev)
 {
+	ofnode node = phy_get_ofnode(phydev);
 	struct fixed_link *priv;
-	int ofnode = phydev->addr;
 	u32 val;
 
+	if (!ofnode_valid(node))
+		return -EINVAL;
+
 	/* check for mandatory properties within fixed-link node */
-	val = fdt_getprop_u32_default_node(gd->fdt_blob,
-					   ofnode, 0, "speed", 0);
+	val = ofnode_read_u32_default(node, "speed", 0);
 	if (val != SPEED_10 && val != SPEED_100 && val != SPEED_1000 &&
 	    val != SPEED_2500 && val != SPEED_10000) {
 		printf("ERROR: no/invalid speed given in fixed-link node!");
@@ -33,14 +35,26 @@ int fixedphy_probe(struct phy_device *phydev)
 	priv = malloc(sizeof(*priv));
 	if (!priv)
 		return -ENOMEM;
+
 	memset(priv, 0, sizeof(*priv));
 
 	phydev->priv = priv;
 
 	priv->link_speed = val;
-	priv->duplex = fdtdec_get_bool(gd->fdt_blob, ofnode, "full-duplex");
-	priv->pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "pause");
-	priv->asym_pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "asym-pause");
+	priv->duplex = ofnode_read_bool(node, "full-duplex");
+	priv->pause = ofnode_read_bool(node, "pause");
+	priv->asym_pause = ofnode_read_bool(node, "asym-pause");
+
+	return 0;
+}
+
+static int fixedphy_config(struct phy_device *phydev)
+{
+	int err;
+
+	err = fixedphy_of_init(phydev);
+	if (err)
+		return err;
 
 	/* fixed-link phy must not be reset by core phy code */
 	phydev->flags |= PHY_FLAG_BROKEN_RESET;
@@ -71,7 +85,7 @@ static struct phy_driver fixedphy_driver = {
 	.mask		= 0xffffffff,
 	.name		= "Fixed PHY",
 	.features	= PHY_GBIT_FEATURES | SUPPORTED_MII,
-	.probe		= fixedphy_probe,
+	.config		= fixedphy_config,
 	.startup	= fixedphy_startup,
 	.shutdown	= fixedphy_shutdown,
 };
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 89e3076bfd25..2feb559bba97 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -988,6 +988,7 @@ static struct phy_device *phy_connect_gmii2rgmii(struct mii_dev *bus,
 struct phy_device *fixed_phy_create(ofnode node)
 {
 	phy_interface_t interface = PHY_INTERFACE_MODE_NONE;
+	struct phy_device *phydev;
 	const char *if_str;
 	ofnode subnode;
 
@@ -1004,8 +1005,11 @@ struct phy_device *fixed_phy_create(ofnode node)
 		return NULL;
 	}
 
-	return phy_device_create(NULL, ofnode_to_offset(subnode), PHY_FIXED_ID,
-				 false, interface);
+	phydev = phy_device_create(NULL, 0, PHY_FIXED_ID, false, interface);
+	if (phydev)
+		phydev->node = subnode;
+
+	return phydev;
 }
 
 #ifdef CONFIG_DM_ETH
@@ -1018,20 +1022,16 @@ static struct phy_device *phy_connect_fixed(struct mii_dev *bus,
 					    phy_interface_t interface)
 #endif
 {
-	struct phy_device *phydev = NULL;
-	int sn;
-	const char *name;
+	ofnode node = dev_ofnode(dev), subnode;
+	struct phy_device *phydev;
 
-	sn = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev));
-	while (sn > 0) {
-		name = fdt_get_name(gd->fdt_blob, sn, NULL);
-		if (name && strcmp(name, "fixed-link") == 0) {
-			phydev = phy_device_create(bus, sn, PHY_FIXED_ID, false,
-						   interface);
-			break;
-		}
-		sn = fdt_next_subnode(gd->fdt_blob, sn);
-	}
+	subnode = ofnode_find_subnode(node, "fixed-link");
+	if (!ofnode_valid(subnode))
+		return NULL;
+
+	phydev = phy_device_create(bus, 0, PHY_FIXED_ID, false, interface);
+	if (phydev)
+		phydev->node = subnode;
 
 	return phydev;
 }
-- 
2.25.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] net: phy: drop #ifdef CONFIG_DM_ETH around phy_connect_fixed
  2021-02-16 22:48 [PATCH 0/4] Sandbox driver for DSA uclass Vladimir Oltean
  2021-02-16 22:48 ` [PATCH 1/4] net: phy: fixed: be compatible with live OF tree Vladimir Oltean
@ 2021-02-16 22:48 ` Vladimir Oltean
  2021-03-11  9:37   ` Bin Meng
  2021-02-16 22:48 ` [PATCH 3/4] net: mdio: teach dm_eth_phy_connect to connect to fixed PHY Vladimir Oltean
  2021-02-16 22:48 ` [PATCH 4/4] sandbox: add a DSA sandbox driver and unit test Vladimir Oltean
  3 siblings, 1 reply; 9+ messages in thread
From: Vladimir Oltean @ 2021-02-16 22:48 UTC (permalink / raw)
  To: u-boot

From: Vladimir Oltean <vladimir.oltean@nxp.com>

In drivers/net/phy/Kconfig, CONFIG_PHY_FIXED already depends on
CONFIG_DM_ETH, so the function prototype definition when CONFIG_DM_ETH=n
does nothing, so it can be dropped. It is also never reachable, since
the whole function is already under #ifdef CONFIG_PHY_FIXED (which
again, as I said, depends on CONFIG_DM_ETH=y).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/phy.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 2feb559bba97..eae40cc0d6b7 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1012,15 +1012,9 @@ struct phy_device *fixed_phy_create(ofnode node)
 	return phydev;
 }
 
-#ifdef CONFIG_DM_ETH
 static struct phy_device *phy_connect_fixed(struct mii_dev *bus,
 					    struct udevice *dev,
 					    phy_interface_t interface)
-#else
-static struct phy_device *phy_connect_fixed(struct mii_dev *bus,
-					    struct eth_device *dev,
-					    phy_interface_t interface)
-#endif
 {
 	ofnode node = dev_ofnode(dev), subnode;
 	struct phy_device *phydev;
-- 
2.25.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] net: mdio: teach dm_eth_phy_connect to connect to fixed PHY
  2021-02-16 22:48 [PATCH 0/4] Sandbox driver for DSA uclass Vladimir Oltean
  2021-02-16 22:48 ` [PATCH 1/4] net: phy: fixed: be compatible with live OF tree Vladimir Oltean
  2021-02-16 22:48 ` [PATCH 2/4] net: phy: drop #ifdef CONFIG_DM_ETH around phy_connect_fixed Vladimir Oltean
@ 2021-02-16 22:48 ` Vladimir Oltean
  2021-03-12  3:29   ` Bin Meng
  2021-02-16 22:48 ` [PATCH 4/4] sandbox: add a DSA sandbox driver and unit test Vladimir Oltean
  3 siblings, 1 reply; 9+ messages in thread
From: Vladimir Oltean @ 2021-02-16 22:48 UTC (permalink / raw)
  To: u-boot

From: Vladimir Oltean <vladimir.oltean@nxp.com>

It would be desirable for top-level callers of PHYLIB to deal with as
little complexity as possible, and when they call dm_eth_phy_connect,
they get a struct phy_device that "just works".

There is a phy_connect_fixed interception put in phy_connect, however
dm_eth_phy_connect will not reach there: if will search for a phy-handle
all by itself, and error out if there isn't one. So we can make callers
of dm_eth_phy_connect suffer by having them call:

	err = dm_eth_phy_connect();
	if (err)
		err = dm_eth_phy_connect_fixed();

or we can just add the logic in dm_eth_phy_connect() that searches for a
fixed-link before searching for a phy-handle.

In fact we already have an in-tree driver that can make use of this
refactoring: the Freescale TSEC driver.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/tsec.c |  6 +-----
 net/mdio-uclass.c  | 12 ++++++++++--
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index ec4868937257..f801d020fb65 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -707,11 +707,7 @@ static int init_phy(struct tsec_private *priv)
 		tsec_configure_serdes(priv);
 
 #if defined(CONFIG_DM_ETH) && defined(CONFIG_DM_MDIO)
-	if (ofnode_valid(ofnode_find_subnode(dev_ofnode(priv->dev),
-					     "fixed-link")))
-		phydev = phy_connect(NULL, 0, priv->dev, priv->interface);
-	else
-		phydev = dm_eth_phy_connect(priv->dev);
+	phydev = dm_eth_phy_connect(priv->dev);
 #else
 	phydev = phy_connect(priv->bus, priv->phyaddr, priv->dev,
 			     priv->interface);
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
index 697e5f838d94..766d4711cc23 100644
--- a/net/mdio-uclass.c
+++ b/net/mdio-uclass.c
@@ -177,9 +177,10 @@ static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev,
 /* Connect to a PHY linked in eth DT node */
 struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
 {
-	const char *if_str;
+	ofnode node = dev_ofnode(ethdev), subnode;
 	phy_interface_t interface;
 	struct phy_device *phy;
+	const char *if_str;
 	int i;
 
 	if (!dev_has_ofnode(ethdev)) {
@@ -200,7 +201,14 @@ struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
 	if (interface == PHY_INTERFACE_MODE_NONE)
 		dev_dbg(ethdev, "can't find interface mode, default to NONE\n");
 
-	phy = dm_eth_connect_phy_handle(ethdev, interface);
+	subnode = ofnode_find_subnode(node, "fixed-link");
+	if (ofnode_valid(subnode)) {
+		phy = phy_connect(NULL, 0, ethdev, interface);
+		if (phy)
+			phy->node = subnode;
+	} else {
+		phy = dm_eth_connect_phy_handle(ethdev, interface);
+	}
 
 	if (!phy)
 		return NULL;
-- 
2.25.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] sandbox: add a DSA sandbox driver and unit test
  2021-02-16 22:48 [PATCH 0/4] Sandbox driver for DSA uclass Vladimir Oltean
                   ` (2 preceding siblings ...)
  2021-02-16 22:48 ` [PATCH 3/4] net: mdio: teach dm_eth_phy_connect to connect to fixed PHY Vladimir Oltean
@ 2021-02-16 22:48 ` Vladimir Oltean
  3 siblings, 0 replies; 9+ messages in thread
From: Vladimir Oltean @ 2021-02-16 22:48 UTC (permalink / raw)
  To: u-boot

From: Claudiu Manoil <claudiu.manoil@nxp.com>

The DSA sandbox driver is used for unit testing the DSA class code.
It implements a simple 2 port switch plus 1 CPU port, and uses a very
simple tag to identify the ports.
The DSA sandbox device is connected via CPU port to a regular Ethernet
sandbox device, called 'dsa-test-eth, managed by the existing eth sandbox
driver.  The 'dsa-test-eth' is not intended for testing the eth class
code however, but it is used to emulate traffic through the 'lan0' and
'lan1' front pannel switch ports.  To achieve this the dsa sandbox driver
registers a tx handler for the 'dsa-test-eth' device.  The switch ports,
labeled as 'lan0' and 'lan1', are also registered as eth devices by the
dsa class code this time.  So pinging through these switch ports is as
easy as:
=> setenv ethact lan0
=> ping 1.2.3.5

Unit tests for the dsa class code were also added.  The 'dsa_probe'
test exercises most API functions from dsa.h.  The 'dsa' unit test
simply exercises ARP/ICMP traffic through the two switch ports,
including tag injection and extraction, with the help of the dsa
sandbox driver.
I took care to minimize the impact on the existing eth unit tests,
though some adjustments needed to be made with the addition of
extra eth interfaces used by the dsa unit tests. The additional eth
interfaces also require MAC addresses, these have been added to the
sandbox default environment.

Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 arch/Kconfig              |   2 +
 arch/sandbox/dts/test.dts |  48 ++++++++++
 drivers/net/Kconfig       |   9 ++
 drivers/net/Makefile      |   1 +
 drivers/net/dsa_sandbox.c | 179 ++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h |   2 +
 test/dm/Makefile          |   1 +
 test/dm/dsa.c             |  82 +++++++++++++++++
 test/dm/eth.c             |  10 +--
 9 files changed, 329 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/dsa_sandbox.c
 create mode 100644 test/dm/dsa.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 6c8167826cf8..f114a025fa5b 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -161,6 +161,8 @@ config SANDBOX
 	imply CMD_CLONE
 	imply SILENT_CONSOLE
 	imply BOOTARGS_SUBST
+	imply PHY_FIXED
+	imply DM_DSA
 
 config SH
 	bool "SuperH architecture"
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e95f4631bf2f..d4ee6ddbbe4c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -14,7 +14,9 @@
 	aliases {
 		console = &uart0;
 		eth0 = "/eth at 10002000";
+		eth2 = &swp_0;
 		eth3 = &eth_3;
+		eth4 = &dsa_eth0;
 		eth5 = &eth_5;
 		gpio1 = &gpio_a;
 		gpio2 = &gpio_b;
@@ -432,6 +434,52 @@
 		fake-host-hwaddr = [00 00 66 44 22 22];
 	};
 
+	dsa_eth0: dsa-test-eth {
+		compatible = "sandbox,eth";
+		reg = <0x10006000 0x1000>;
+		fake-host-hwaddr = [00 00 66 44 22 66];
+	};
+
+	dsa-test {
+		compatible = "sandbox,dsa";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			swp_0: port at 0 {
+				reg = <0>;
+				label = "lan0";
+				phy-mode = "rgmii-rxid";
+
+				fixed-link {
+					speed = <100>;
+					full-duplex;
+				};
+			};
+
+			swp_1: port at 1 {
+				reg = <1>;
+				label = "lan1";
+				phy-mode = "rgmii-txid";
+
+				fixed-link {
+					speed = <100>;
+					full-duplex;
+				};
+			};
+
+			port at 2 {
+				reg = <2>;
+				ethernet = <&dsa_eth0>;
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+		};
+	};
+
 	firmware {
 		sandbox_firmware: sandbox-firmware {
 			compatible = "sandbox,firmware";
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0e84c22b5075..f96ee642494a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -78,6 +78,15 @@ config DM_ETH_PHY
 	help
 	  Enable driver model for Ethernet Generic PHY .
 
+config DSA_SANDBOX
+	depends on DM_DSA && SANDBOX
+	default y
+	bool "Sandbox: Mocked DSA driver"
+	help
+	  This driver implements a dummy DSA switch connected to a dummy sandbox
+	  Ethernet device used as DSA master, to test DSA class code, including
+	  exported DSA API and datapath processing of Ethernet traffic.
+
 menuconfig NETDEVICES
 	bool "Network device support"
 	depends on NET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a19511aaa7ba..108138fdb972 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o
 obj-$(CONFIG_ETH_DESIGNWARE_S700) += dwmac_s700.o
 obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
 obj-$(CONFIG_DNET) += dnet.o
+obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
 obj-$(CONFIG_DM_ETH_PHY) += eth-phy-uclass.o
 obj-$(CONFIG_E1000) += e1000.o
 obj-$(CONFIG_E1000_SPI) += e1000_spi.o
diff --git a/drivers/net/dsa_sandbox.c b/drivers/net/dsa_sandbox.c
new file mode 100644
index 000000000000..4b62670e5d17
--- /dev/null
+++ b/drivers/net/dsa_sandbox.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019-2021 NXP Semiconductors
+ */
+
+#include <asm/eth.h>
+#include <net/dsa.h>
+#include <net.h>
+
+#define DSA_SANDBOX_MAGIC	0x00415344
+#define DSA_SANDBOX_TAG_LEN	sizeof(struct dsa_sandbox_tag)
+
+struct dsa_sandbox_priv {
+	struct eth_sandbox_priv *master_priv;
+	int port_en_mask;
+};
+
+struct dsa_sandbox_tag {
+	u32 magic;
+	u32 port;
+};
+
+static bool sb_dsa_port_enabled(struct udevice *dev, int port)
+{
+	struct dsa_sandbox_priv *priv = dev_get_priv(dev);
+
+	return priv->port_en_mask & BIT(port);
+}
+
+static bool sb_dsa_master_enabled(struct udevice *dev)
+{
+	struct dsa_sandbox_priv *priv = dev_get_priv(dev);
+
+	return !priv->master_priv->disabled;
+}
+
+static int dsa_sandbox_port_enable(struct udevice *dev, int port,
+				   struct phy_device *phy)
+{
+	struct dsa_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (!sb_dsa_master_enabled(dev))
+		return -EFAULT;
+
+	priv->port_en_mask |= 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_get_priv(dev);
+
+	priv->port_en_mask &= ~BIT(port);
+}
+
+static int dsa_sandbox_xmit(struct udevice *dev, int port, void *packet,
+			    int length)
+{
+	struct dsa_sandbox_tag *tag = packet;
+
+	if (!sb_dsa_master_enabled(dev))
+		return -EFAULT;
+
+	if (!sb_dsa_port_enabled(dev, 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_tag *tag = packet;
+
+	if (!sb_dsa_master_enabled(dev))
+		return -EFAULT;
+
+	if (tag->magic != DSA_SANDBOX_MAGIC)
+		return -EFAULT;
+
+	*port = tag->port;
+	if (!sb_dsa_port_enabled(dev, tag->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 sb_dsa_handler(struct udevice *dev, void *packet,
+			  unsigned int len)
+{
+	struct eth_sandbox_priv *master_priv;
+	struct dsa_sandbox_tag *tag = packet;
+	struct udevice *dsa_dev;
+	u32 port_index;
+	void *rx_buf;
+	int i;
+
+	/* this emulates the switch hw and the network side */
+	if (tag->magic != DSA_SANDBOX_MAGIC)
+		return -EFAULT;
+
+	port_index = tag->port;
+	master_priv = dev_get_priv(dev);
+	dsa_dev = master_priv->priv;
+	if (!sb_dsa_port_enabled(dsa_dev, port_index))
+		return -EFAULT;
+
+	packet += DSA_SANDBOX_TAG_LEN;
+	len -= DSA_SANDBOX_TAG_LEN;
+
+	if (!sandbox_eth_arp_req_to_reply(dev, packet, len))
+		goto dsa_tagging;
+	if (!sandbox_eth_ping_req_to_reply(dev, packet, len))
+		goto dsa_tagging;
+
+	return 0;
+
+dsa_tagging:
+	master_priv->recv_packets--;
+	i = master_priv->recv_packets;
+	rx_buf = master_priv->recv_packet_buffer[i];
+	len = master_priv->recv_packet_length[i];
+	memmove(rx_buf + DSA_SANDBOX_TAG_LEN, rx_buf, len);
+
+	tag = rx_buf;
+	tag->magic = DSA_SANDBOX_MAGIC;
+	tag->port = port_index;
+	len += DSA_SANDBOX_TAG_LEN;
+	master_priv->recv_packet_length[i] = len;
+	master_priv->recv_packets++;
+
+	return 0;
+}
+
+static int dsa_sandbox_probe(struct udevice *dev)
+{
+	struct dsa_sandbox_priv *priv = dev_get_priv(dev);
+	struct udevice *master = dsa_get_master(dev);
+	struct eth_sandbox_priv *master_priv;
+
+	if (!master)
+		return -ENODEV;
+
+	dsa_set_tagging(dev, DSA_SANDBOX_TAG_LEN, 0);
+
+	master_priv = dev_get_priv(master);
+	master_priv->priv = dev;
+	master_priv->tx_handler = sb_dsa_handler;
+
+	priv->master_priv = master_priv;
+
+	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,
+	.probe		= dsa_sandbox_probe,
+	.ops		= &dsa_sandbox_ops,
+	.priv_auto	= sizeof(struct dsa_sandbox_priv),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e0708fe57395..91f636b2c102 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -93,7 +93,9 @@
 #endif
 
 #define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
+					"eth2addr=00:00:11:22:33:48\0" \
 					"eth3addr=00:00:11:22:33:45\0" \
+					"eth4addr=00:00:11:22:33:48\0" \
 					"eth5addr=00:00:11:22:33:46\0" \
 					"eth6addr=00:00:11:22:33:47\0" \
 					"ipaddr=1.2.3.4\0"
diff --git a/test/dm/Makefile b/test/dm/Makefile
index e70e50f40243..42dc2d56a764 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CLK) += clk.o clk_ccf.o
 obj-$(CONFIG_CROS_EC) += cros_ec.o
 obj-$(CONFIG_DEVRES) += devres.o
 obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o
+obj-$(CONFIG_DM_DSA) += dsa.o
 obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_FIRMWARE) += firmware.o
 obj-$(CONFIG_DM_GPIO) += gpio.o
diff --git a/test/dm/dsa.c b/test/dm/dsa.c
new file mode 100644
index 000000000000..18c1776460da
--- /dev/null
+++ b/test/dm/dsa.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020-2021 NXP Semiconductors
+ */
+
+#include <net/dsa.h>
+#include <dm/test.h>
+#include <test/ut.h>
+#include <net.h>
+#include <dm/uclass-internal.h>
+#include <dm/device-internal.h>
+
+/* This test exercises the major dsa.h API functions, after making sure
+ * that the DSA ports and the master Eth are correctly probed.
+ */
+static int dm_test_dsa_probe(struct unit_test_state *uts)
+{
+	struct udevice *dev_dsa, *dev_port, *dev_master;
+	struct dsa_pdata *dsa_pdata;
+	enum uclass_id id;
+
+	id = uclass_get_by_name("dsa");
+	ut_assert(id == UCLASS_DSA);
+
+	ut_assertok(uclass_find_device_by_name(UCLASS_DSA, "dsa-test",
+					       &dev_dsa));
+	ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "dsa-test-eth",
+					       &dev_master));
+	ut_assertok(device_probe(dev_master));
+
+	ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "dsa-test at 0",
+					       &dev_port));
+	ut_assertok(device_probe(dev_port));
+
+	ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "dsa-test at 1",
+					       &dev_port));
+	ut_assertok(device_probe(dev_port));
+
+	/* exercise DSA API */
+	dsa_pdata = dev_get_uclass_plat(dev_dsa);
+	ut_assertnonnull(dsa_pdata);
+	/* includes CPU port */
+	ut_assert(dsa_pdata->num_ports == 3);
+
+	ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "lan0",
+					       &dev_port));
+	ut_assertok(device_probe(dev_port));
+
+	ut_assertok(uclass_find_device_by_name(UCLASS_ETH, "lan1",
+					       &dev_port));
+	ut_assertok(device_probe(dev_port));
+
+	dev_master = dsa_get_master(dev_dsa);
+	ut_assertnonnull(dev_master);
+	ut_asserteq_str("dsa-test-eth", dev_master->name);
+
+	return 0;
+}
+
+DM_TEST(dm_test_dsa_probe, UT_TESTF_SCAN_FDT);
+
+/* This test sends ping requests with the local address through each DSA port
+ * via the sandbox DSA master Eth.
+ */
+static int dm_test_dsa(struct unit_test_state *uts)
+{
+	net_ping_ip = string_to_ip("1.2.3.5");
+
+	env_set("ethact", "eth2");
+	ut_assertok(net_loop(PING));
+
+	env_set("ethact", "lan0");
+	ut_assertok(net_loop(PING));
+	env_set("ethact", "lan1");
+	ut_assertok(net_loop(PING));
+
+	env_set("ethact", "");
+
+	return 0;
+}
+
+DM_TEST(dm_test_dsa, UT_TESTF_SCAN_FDT);
diff --git a/test/dm/eth.c b/test/dm/eth.c
index fa8a69da7013..e4ee69561064 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -53,8 +53,8 @@ static int dm_test_eth_alias(struct unit_test_state *uts)
 	ut_assertok(net_loop(PING));
 	ut_asserteq_str("eth at 10004000", env_get("ethact"));
 
-	/* Expected to fail since eth2 is not defined in the device tree */
-	env_set("ethact", "eth2");
+	/* Expected to fail since eth1 is not defined in the device tree */
+	env_set("ethact", "eth1");
 	ut_assertok(net_loop(PING));
 	ut_asserteq_str("eth at 10002000", env_get("ethact"));
 
@@ -227,7 +227,7 @@ static int _dm_test_net_retry(struct unit_test_state *uts)
 	 * the active device should be eth0
 	 */
 	sandbox_eth_disable_response(1, true);
-	env_set("ethact", "eth at 10004000");
+	env_set("ethact", "lan1");
 	env_set("netretry", "yes");
 	sandbox_eth_skip_timeout();
 	ut_assertok(net_loop(PING));
@@ -237,11 +237,11 @@ static int _dm_test_net_retry(struct unit_test_state *uts)
 	 * eth1 is disabled and netretry is no, so the ping should fail and the
 	 * active device should be eth1
 	 */
-	env_set("ethact", "eth at 10004000");
+	env_set("ethact", "lan1");
 	env_set("netretry", "no");
 	sandbox_eth_skip_timeout();
 	ut_asserteq(-ENONET, net_loop(PING));
-	ut_asserteq_str("eth at 10004000", env_get("ethact"));
+	ut_asserteq_str("lan1", env_get("ethact"));
 
 	return 0;
 }
-- 
2.25.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] net: phy: drop #ifdef CONFIG_DM_ETH around phy_connect_fixed
  2021-02-16 22:48 ` [PATCH 2/4] net: phy: drop #ifdef CONFIG_DM_ETH around phy_connect_fixed Vladimir Oltean
@ 2021-03-11  9:37   ` Bin Meng
  0 siblings, 0 replies; 9+ messages in thread
From: Bin Meng @ 2021-03-11  9:37 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 17, 2021 at 6:48 AM Vladimir Oltean <olteanv@gmail.com> wrote:
>
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
> In drivers/net/phy/Kconfig, CONFIG_PHY_FIXED already depends on
> CONFIG_DM_ETH, so the function prototype definition when CONFIG_DM_ETH=n
> does nothing, so it can be dropped. It is also never reachable, since
> the whole function is already under #ifdef CONFIG_PHY_FIXED (which
> again, as I said, depends on CONFIG_DM_ETH=y).
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/phy/phy.c | 6 ------
>  1 file changed, 6 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/4] net: mdio: teach dm_eth_phy_connect to connect to fixed PHY
  2021-02-16 22:48 ` [PATCH 3/4] net: mdio: teach dm_eth_phy_connect to connect to fixed PHY Vladimir Oltean
@ 2021-03-12  3:29   ` Bin Meng
  0 siblings, 0 replies; 9+ messages in thread
From: Bin Meng @ 2021-03-12  3:29 UTC (permalink / raw)
  To: u-boot

Hi Vladimir,

On Wed, Feb 17, 2021 at 6:48 AM Vladimir Oltean <olteanv@gmail.com> wrote:
>
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
> It would be desirable for top-level callers of PHYLIB to deal with as
> little complexity as possible, and when they call dm_eth_phy_connect,
> they get a struct phy_device that "just works".
>
> There is a phy_connect_fixed interception put in phy_connect, however
> dm_eth_phy_connect will not reach there: if will search for a phy-handle
> all by itself, and error out if there isn't one. So we can make callers
> of dm_eth_phy_connect suffer by having them call:
>
>         err = dm_eth_phy_connect();
>         if (err)
>                 err = dm_eth_phy_connect_fixed();
>
> or we can just add the logic in dm_eth_phy_connect() that searches for a
> fixed-link before searching for a phy-handle.

This logic already exists since:

commit bdf319273b4a752664c089fbffee5bb2024c8586
Author: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Date:   Mon Oct 5 15:15:16 2020 +0200

    mdio-uclass.c: support fixed-link subnodes

> In fact we already have an in-tree driver that can make use of this
> refactoring: the Freescale TSEC driver.

I will drop the dm_eth_phy_connect() changes and only keep the TSEC
changes in v2.

>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/tsec.c |  6 +-----
>  net/mdio-uclass.c  | 12 ++++++++++--
>  2 files changed, 11 insertions(+), 7 deletions(-)
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] net: phy: fixed: be compatible with live OF tree
  2021-02-16 22:48 ` [PATCH 1/4] net: phy: fixed: be compatible with live OF tree Vladimir Oltean
@ 2021-03-12  6:34   ` Bin Meng
  2021-03-12  7:53     ` Bin Meng
  0 siblings, 1 reply; 9+ messages in thread
From: Bin Meng @ 2021-03-12  6:34 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 17, 2021 at 6:48 AM Vladimir Oltean <olteanv@gmail.com> wrote:
>
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
> On systems that use CONFIG_OF_LIVE, the "ofnode" type is defined as
> const struct device_node *np, while on the flat DT systems it is defined
> as a long of_offset into gd->fdt_blob.
>
> It is desirable that the fixed PHY driver uses the higher-level ofnode
> abstraction instead of parsing gd->fdt_blob directly, because that
> enables it to work on live OF systems.
>
> The fixed PHY driver has used a nastyyyyy hack since its introduction in
> commit db40c1aa1c10 ("drivers/net/phy: add fixed-phy / fixed-link support"),
> which is to pass the long gd->fdt_blob offset inside int phydev->addr
> (a value that normally holds the MDIO bus address at which the PHY
> responds). Even ignoring the fact that the types were already mismatched
> leading to a potential truncation (flat OF offset was supposed to be a
> long and not an int), we really cannot extend this hack any longer,
> because there's no way an int will hold the other representation of
> ofnode, the struct device_node *np.
>
> So we unfortunately need to do the right thing, which is to use the
> framework introduced by Grygorii Strashko in commit eef0b8a930d1 ("net:
> phy: add ofnode node to struct phy_device"). This will populate
> phydev->node for the fixed PHY.
>
> Note that phydev->node will not be valid in the probe function, since
> that is called synchronously from phy_device_create and we really have
> no way of passing the ofnode directly through the phy_device_create API.
> So we do what other drivers do too: we move the OF parsing logic from
> the .probe to the .config method of the PHY driver. The new function
> will be called at phy_config() time.
>
> I do believe I've converted all the possible call paths for creating a
> PHY with PHY_FIXED_ID, so there is really no reason to maintain
> compatibility with the old logic of retrieving a flat OF tree offset
> from phydev->addr. We just pass 0 to phydev->addr now.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/phy/fixed.c | 30 ++++++++++++++++++++++--------
>  drivers/net/phy/phy.c   | 30 +++++++++++++++---------------
>  2 files changed, 37 insertions(+), 23 deletions(-)
>

For the record,

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] net: phy: fixed: be compatible with live OF tree
  2021-03-12  6:34   ` Bin Meng
@ 2021-03-12  7:53     ` Bin Meng
  0 siblings, 0 replies; 9+ messages in thread
From: Bin Meng @ 2021-03-12  7:53 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 12, 2021 at 2:34 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> On Wed, Feb 17, 2021 at 6:48 AM Vladimir Oltean <olteanv@gmail.com> wrote:
> >
> > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> >
> > On systems that use CONFIG_OF_LIVE, the "ofnode" type is defined as
> > const struct device_node *np, while on the flat DT systems it is defined
> > as a long of_offset into gd->fdt_blob.
> >
> > It is desirable that the fixed PHY driver uses the higher-level ofnode
> > abstraction instead of parsing gd->fdt_blob directly, because that
> > enables it to work on live OF systems.
> >
> > The fixed PHY driver has used a nastyyyyy hack since its introduction in
> > commit db40c1aa1c10 ("drivers/net/phy: add fixed-phy / fixed-link support"),
> > which is to pass the long gd->fdt_blob offset inside int phydev->addr
> > (a value that normally holds the MDIO bus address at which the PHY
> > responds). Even ignoring the fact that the types were already mismatched
> > leading to a potential truncation (flat OF offset was supposed to be a
> > long and not an int), we really cannot extend this hack any longer,
> > because there's no way an int will hold the other representation of
> > ofnode, the struct device_node *np.
> >
> > So we unfortunately need to do the right thing, which is to use the
> > framework introduced by Grygorii Strashko in commit eef0b8a930d1 ("net:
> > phy: add ofnode node to struct phy_device"). This will populate
> > phydev->node for the fixed PHY.
> >
> > Note that phydev->node will not be valid in the probe function, since
> > that is called synchronously from phy_device_create and we really have
> > no way of passing the ofnode directly through the phy_device_create API.
> > So we do what other drivers do too: we move the OF parsing logic from
> > the .probe to the .config method of the PHY driver. The new function
> > will be called at phy_config() time.
> >
> > I do believe I've converted all the possible call paths for creating a
> > PHY with PHY_FIXED_ID, so there is really no reason to maintain
> > compatibility with the old logic of retrieving a flat OF tree offset
> > from phydev->addr. We just pass 0 to phydev->addr now.
> >
> > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > ---
> >  drivers/net/phy/fixed.c | 30 ++++++++++++++++++++++--------
> >  drivers/net/phy/phy.c   | 30 +++++++++++++++---------------
> >  2 files changed, 37 insertions(+), 23 deletions(-)
> >
>
> For the record,
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> Tested-by: Bin Meng <bmeng.cn@gmail.com>

fixedphy_probe() has to be kept, to set the PHY_FLAG_BROKEN_RESET
flag. Will fix in v2.

Regards,
Bin

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-03-12  7:53 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-16 22:48 [PATCH 0/4] Sandbox driver for DSA uclass Vladimir Oltean
2021-02-16 22:48 ` [PATCH 1/4] net: phy: fixed: be compatible with live OF tree Vladimir Oltean
2021-03-12  6:34   ` Bin Meng
2021-03-12  7:53     ` Bin Meng
2021-02-16 22:48 ` [PATCH 2/4] net: phy: drop #ifdef CONFIG_DM_ETH around phy_connect_fixed Vladimir Oltean
2021-03-11  9:37   ` Bin Meng
2021-02-16 22:48 ` [PATCH 3/4] net: mdio: teach dm_eth_phy_connect to connect to fixed PHY Vladimir Oltean
2021-03-12  3:29   ` Bin Meng
2021-02-16 22:48 ` [PATCH 4/4] sandbox: add a DSA sandbox driver and unit test Vladimir Oltean

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.