[PATCH net-next v4 7/7] net: dsa: lantiq_gswip: store switch API version in priv

Daniel Golle posted 7 patches 1 month, 1 week ago
[PATCH net-next v4 7/7] net: dsa: lantiq_gswip: store switch API version in priv
Posted by Daniel Golle 1 month, 1 week ago
Store the switch API version in struct gswip_priv. As the hardware has
the 'major/minor' version bytes in the wrong order preventing numerical
comparisons the version to be stored in gswip_priv is constructed in
such a way that the REV field is the most significant byte and the MOD
field the least significant byte. Also provide a conveniance macro to
allow comparing the stored version of the hardware against the already
defined GSWIP_VERSION_* macros.

This is done in order to prepare supporting newer features such as 4096
VLANs and per-port configurable learning which are only available
starting from specific hardware versions.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v4: use FIELD_GET accessor macro to construct version to be stored,
    add comments and postpone adding the for now unused
    GSWIP_VERSION_2_3 macro
v3: use __force for version field endian exception (__le16 __force) to
    fix sparse warning.
v2: no changes

 drivers/net/dsa/lantiq_gswip.c | 13 +++++++++++--
 drivers/net/dsa/lantiq_gswip.h | 13 +++++++++++--
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
index f8a43c351649..638f9a42f218 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -1908,6 +1908,16 @@ static int gswip_probe(struct platform_device *pdev)
 	mutex_init(&priv->pce_table_lock);
 	version = gswip_switch_r(priv, GSWIP_VERSION);
 
+	/* The hardware has the 'major/minor' version bytes in the wrong order
+	 * preventing numerical comparisons. Construct a 16-bit unsigned integer
+	 * having the REV field as most significant byte and the MOD field as
+	 * least significant byte. This is effectively swapping the two bytes of
+	 * the version variable, but other than using swab16 it doesn't affect
+	 * the source variable.
+	 */
+	priv->version = GSWIP_VERSION_REV(version) << 8 |
+			GSWIP_VERSION_MOD(version);
+
 	np = dev->of_node;
 	switch (version) {
 	case GSWIP_VERSION_2_0:
@@ -1956,8 +1966,7 @@ static int gswip_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, priv);
 
 	dev_info(dev, "probed GSWIP version %lx mod %lx\n",
-		 (version & GSWIP_VERSION_REV_MASK) >> GSWIP_VERSION_REV_SHIFT,
-		 (version & GSWIP_VERSION_MOD_MASK) >> GSWIP_VERSION_MOD_SHIFT);
+		 GSWIP_VERSION_REV(version), GSWIP_VERSION_MOD(version));
 	return 0;
 
 disable_switch:
diff --git a/drivers/net/dsa/lantiq_gswip.h b/drivers/net/dsa/lantiq_gswip.h
index 0b7b6db4eab9..620c2d560cbe 100644
--- a/drivers/net/dsa/lantiq_gswip.h
+++ b/drivers/net/dsa/lantiq_gswip.h
@@ -7,6 +7,7 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
+#include <linux/swab.h>
 #include <net/dsa.h>
 
 /* GSWIP MDIO Registers */
@@ -85,14 +86,21 @@
 #define  GSWIP_SWRES_R1			BIT(1)	/* GSWIP Software reset */
 #define  GSWIP_SWRES_R0			BIT(0)	/* GSWIP Hardware reset */
 #define GSWIP_VERSION			0x013
-#define  GSWIP_VERSION_REV_SHIFT	0
 #define  GSWIP_VERSION_REV_MASK		GENMASK(7, 0)
-#define  GSWIP_VERSION_MOD_SHIFT	8
 #define  GSWIP_VERSION_MOD_MASK		GENMASK(15, 8)
+#define  GSWIP_VERSION_REV(v)		FIELD_GET(GSWIP_VERSION_REV_MASK, v)
+#define  GSWIP_VERSION_MOD(v)		FIELD_GET(GSWIP_VERSION_MOD_MASK, v)
 #define   GSWIP_VERSION_2_0		0x100
 #define   GSWIP_VERSION_2_1		0x021
 #define   GSWIP_VERSION_2_2		0x122
 #define   GSWIP_VERSION_2_2_ETC		0x022
+/* The hardware has the 'major/minor' version bytes in the wrong order
+ * preventing numerical comparisons. Swap the bytes of the 16-bit value
+ * to end up with REV being the most significant byte and MOD being the
+ * least significant byte, which then allows comparing it with the
+ * value stored in struct gswip_priv.
+ */
+#define GSWIP_VERSION_GE(priv, ver)	((priv)->version >= swab16(ver))
 
 #define GSWIP_BM_RAM_VAL(x)		(0x043 - (x))
 #define GSWIP_BM_RAM_ADDR		0x044
@@ -258,6 +266,7 @@ struct gswip_priv {
 	struct gswip_gphy_fw *gphy_fw;
 	u32 port_vlan_filter;
 	struct mutex pce_table_lock;
+	u16 version;
 };
 
 #endif /* __LANTIQ_GSWIP_H */
-- 
2.50.1
Re: [PATCH net-next v4 7/7] net: dsa: lantiq_gswip: store switch API version in priv
Posted by Andrew Lunn 1 month, 1 week ago
On Fri, Aug 22, 2025 at 05:12:21PM +0100, Daniel Golle wrote:
> Store the switch API version in struct gswip_priv. As the hardware has
> the 'major/minor' version bytes in the wrong order preventing numerical
> comparisons the version to be stored in gswip_priv is constructed in
> such a way that the REV field is the most significant byte and the MOD
> field the least significant byte. Also provide a conveniance macro to
> allow comparing the stored version of the hardware against the already
> defined GSWIP_VERSION_* macros.
>
> This is done in order to prepare supporting newer features such as 4096
> VLANs and per-port configurable learning which are only available
> starting from specific hardware versions.

Thanks for the updated commit message and comments. This is much
clearer and the code avoids all the issues around endianness.

> Signed-off-by: Daniel Golle <daniel@makrotopia.org>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew