netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v3 0/4] net: dsa: yt921x: Add STP/MST/HSR/LAG support
@ 2025-11-26  9:32 David Yang
  2025-11-26  9:32 ` [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL David Yang
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: David Yang @ 2025-11-26  9:32 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Russell King, linux-kernel

Support for these features was deferred from the initial submission of the
driver.

v2: https://lore.kernel.org/r/20251025170606.1937327-1-mmyangfl@gmail.com
  - reverse christmas-tree
v1: https://lore.kernel.org/r/20251024033237.1336249-1-mmyangfl@gmail.com
  - use *_ULL bitfield macros for VLAN_CTRL

David Yang (4):
  net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL
  net: dsa: yt921x: Add STP/MST support
  net: dsa: yt921x: Add HSR offloading support
  net: dsa: yt921x: Add LAG offloading support

 drivers/net/dsa/yt921x.c | 324 +++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/yt921x.h |  55 +++++--
 net/dsa/tag_yt921x.c     |   4 +
 3 files changed, 370 insertions(+), 13 deletions(-)

--
2.51.0


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

* [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL
  2025-11-26  9:32 [PATCH net-next v3 0/4] net: dsa: yt921x: Add STP/MST/HSR/LAG support David Yang
@ 2025-11-26  9:32 ` David Yang
  2025-11-28  1:58   ` Jakub Kicinski
  2025-11-28 10:51   ` david laight
  2025-11-26  9:32 ` [PATCH net-next v3 2/4] net: dsa: yt921x: Add STP/MST support David Yang
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 10+ messages in thread
From: David Yang @ 2025-11-26  9:32 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Russell King, linux-kernel

VLAN_CTRL should be treated as a 64-bit register. GENMASK and BIT
macros use unsigned long as the underlying type, which will result in a
build error on architectures where sizeof(long) == 32.

Replace them with unsigned long long variants.

Signed-off-by: David Yang <mmyangfl@gmail.com>
---
 drivers/net/dsa/yt921x.h | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
index 3e85d90826fb..85d995cdb7c5 100644
--- a/drivers/net/dsa/yt921x.h
+++ b/drivers/net/dsa/yt921x.h
@@ -328,23 +328,23 @@
 #define  YT921X_FDB_HW_FLUSH_ON_LINKDOWN	BIT(0)
 
 #define YT921X_VLANn_CTRL(vlan)		(0x188000 + 8 * (vlan))
-#define  YT921X_VLAN_CTRL_UNTAG_PORTS_M		GENMASK(50, 40)
+#define  YT921X_VLAN_CTRL_UNTAG_PORTS_M		GENMASK_ULL(50, 40)
 #define   YT921X_VLAN_CTRL_UNTAG_PORTS(x)		FIELD_PREP(YT921X_VLAN_CTRL_UNTAG_PORTS_M, (x))
-#define  YT921X_VLAN_CTRL_UNTAG_PORTn(port)	BIT((port) + 40)
-#define  YT921X_VLAN_CTRL_STP_ID_M		GENMASK(39, 36)
+#define  YT921X_VLAN_CTRL_UNTAG_PORTn(port)	BIT_ULL((port) + 40)
+#define  YT921X_VLAN_CTRL_STP_ID_M		GENMASK_ULL(39, 36)
 #define   YT921X_VLAN_CTRL_STP_ID(x)			FIELD_PREP(YT921X_VLAN_CTRL_STP_ID_M, (x))
-#define  YT921X_VLAN_CTRL_SVLAN_EN		BIT(35)
-#define  YT921X_VLAN_CTRL_FID_M			GENMASK(34, 23)
+#define  YT921X_VLAN_CTRL_SVLAN_EN		BIT_ULL(35)
+#define  YT921X_VLAN_CTRL_FID_M			GENMASK_ULL(34, 23)
 #define   YT921X_VLAN_CTRL_FID(x)			FIELD_PREP(YT921X_VLAN_CTRL_FID_M, (x))
-#define  YT921X_VLAN_CTRL_LEARN_DIS		BIT(22)
-#define  YT921X_VLAN_CTRL_INT_PRI_EN		BIT(21)
-#define  YT921X_VLAN_CTRL_INT_PRI_M		GENMASK(20, 18)
-#define  YT921X_VLAN_CTRL_PORTS_M		GENMASK(17, 7)
+#define  YT921X_VLAN_CTRL_LEARN_DIS		BIT_ULL(22)
+#define  YT921X_VLAN_CTRL_INT_PRI_EN		BIT_ULL(21)
+#define  YT921X_VLAN_CTRL_INT_PRI_M		GENMASK_ULL(20, 18)
+#define  YT921X_VLAN_CTRL_PORTS_M		GENMASK_ULL(17, 7)
 #define   YT921X_VLAN_CTRL_PORTS(x)			FIELD_PREP(YT921X_VLAN_CTRL_PORTS_M, (x))
-#define  YT921X_VLAN_CTRL_PORTn(port)		BIT((port) + 7)
-#define  YT921X_VLAN_CTRL_BYPASS_1X_AC		BIT(6)
-#define  YT921X_VLAN_CTRL_METER_EN		BIT(5)
-#define  YT921X_VLAN_CTRL_METER_ID_M		GENMASK(4, 0)
+#define  YT921X_VLAN_CTRL_PORTn(port)		BIT_ULL((port) + 7)
+#define  YT921X_VLAN_CTRL_BYPASS_1X_AC		BIT_ULL(6)
+#define  YT921X_VLAN_CTRL_METER_EN		BIT_ULL(5)
+#define  YT921X_VLAN_CTRL_METER_ID_M		GENMASK_ULL(4, 0)
 
 #define YT921X_TPID_IGRn(x)		(0x210000 + 4 * (x))	/* [0, 3] */
 #define  YT921X_TPID_IGR_TPID_M			GENMASK(15, 0)
-- 
2.51.0


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

* [PATCH net-next v3 2/4] net: dsa: yt921x: Add STP/MST support
  2025-11-26  9:32 [PATCH net-next v3 0/4] net: dsa: yt921x: Add STP/MST/HSR/LAG support David Yang
  2025-11-26  9:32 ` [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL David Yang
@ 2025-11-26  9:32 ` David Yang
  2025-11-26  9:32 ` [PATCH net-next v3 3/4] net: dsa: yt921x: Add HSR offloading support David Yang
  2025-11-26  9:32 ` [PATCH net-next v3 4/4] net: dsa: yt921x: Add LAG " David Yang
  3 siblings, 0 replies; 10+ messages in thread
From: David Yang @ 2025-11-26  9:32 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Russell King, linux-kernel

Support for STP/MST was deferred from the initial submission of the
driver.

Signed-off-by: David Yang <mmyangfl@gmail.com>
---
 drivers/net/dsa/yt921x.c | 115 +++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/yt921x.h |   9 +++
 2 files changed, 124 insertions(+)

diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index 133151abef8b..e88b4037ee80 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -2103,6 +2103,117 @@ yt921x_dsa_port_bridge_join(struct dsa_switch *ds, int port,
 	return res;
 }
 
+static int
+yt921x_dsa_port_mst_state_set(struct dsa_switch *ds, int port,
+			      const struct switchdev_mst_state *st)
+{
+	struct yt921x_priv *priv = to_yt921x_priv(ds);
+	u32 mask;
+	u32 ctrl;
+	int res;
+
+	mask = YT921X_STP_PORTn_M(port);
+	switch (st->state) {
+	case BR_STATE_DISABLED:
+		ctrl = YT921X_STP_PORTn_DISABLED(port);
+		break;
+	case BR_STATE_LISTENING:
+	case BR_STATE_LEARNING:
+		ctrl = YT921X_STP_PORTn_LEARNING(port);
+		break;
+	case BR_STATE_FORWARDING:
+	default:
+		ctrl = YT921X_STP_PORTn_FORWARD(port);
+		break;
+	case BR_STATE_BLOCKING:
+		ctrl = YT921X_STP_PORTn_BLOCKING(port);
+		break;
+	}
+
+	mutex_lock(&priv->reg_lock);
+	res = yt921x_reg_update_bits(priv, YT921X_STPn(st->msti), mask, ctrl);
+	mutex_unlock(&priv->reg_lock);
+
+	return res;
+}
+
+static int
+yt921x_dsa_vlan_msti_set(struct dsa_switch *ds, struct dsa_bridge bridge,
+			 const struct switchdev_vlan_msti *msti)
+{
+	struct yt921x_priv *priv = to_yt921x_priv(ds);
+	u64 mask64;
+	u64 ctrl64;
+	int res;
+
+	if (!msti->vid)
+		return -EINVAL;
+	if (!msti->msti || msti->msti >= YT921X_MSTI_NUM)
+		return -EINVAL;
+
+	mask64 = YT921X_VLAN_CTRL_STP_ID_M;
+	ctrl64 = YT921X_VLAN_CTRL_STP_ID(msti->msti);
+
+	mutex_lock(&priv->reg_lock);
+	res = yt921x_reg64_update_bits(priv, YT921X_VLANn_CTRL(msti->vid),
+				       mask64, ctrl64);
+	mutex_unlock(&priv->reg_lock);
+
+	return res;
+}
+
+static void
+yt921x_dsa_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
+{
+	struct yt921x_priv *priv = to_yt921x_priv(ds);
+	struct dsa_port *dp = dsa_to_port(ds, port);
+	struct device *dev = to_device(priv);
+	bool learning;
+	u32 mask;
+	u32 ctrl;
+	int res;
+
+	mask = YT921X_STP_PORTn_M(port);
+	learning = false;
+	switch (state) {
+	case BR_STATE_DISABLED:
+		ctrl = YT921X_STP_PORTn_DISABLED(port);
+		break;
+	case BR_STATE_LISTENING:
+		ctrl = YT921X_STP_PORTn_LEARNING(port);
+		break;
+	case BR_STATE_LEARNING:
+		ctrl = YT921X_STP_PORTn_LEARNING(port);
+		learning = dp->learning;
+		break;
+	case BR_STATE_FORWARDING:
+	default:
+		ctrl = YT921X_STP_PORTn_FORWARD(port);
+		learning = dp->learning;
+		break;
+	case BR_STATE_BLOCKING:
+		ctrl = YT921X_STP_PORTn_BLOCKING(port);
+		break;
+	}
+
+	mutex_lock(&priv->reg_lock);
+	do {
+		res = yt921x_reg_update_bits(priv, YT921X_STPn(0), mask, ctrl);
+		if (res)
+			break;
+
+		mask = YT921X_PORT_LEARN_DIS;
+		ctrl = !learning ? YT921X_PORT_LEARN_DIS : 0;
+		res = yt921x_reg_update_bits(priv, YT921X_PORTn_LEARN(port),
+					     mask, ctrl);
+	} while (0);
+	mutex_unlock(&priv->reg_lock);
+
+	if (res)
+		dev_err(dev, "Failed to %s port %d: %i\n", "set STP state for",
+			port, res);
+}
+
 static int yt921x_port_down(struct yt921x_priv *priv, int port)
 {
 	u32 mask;
@@ -2789,6 +2900,10 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = {
 	.port_bridge_flags	= yt921x_dsa_port_bridge_flags,
 	.port_bridge_leave	= yt921x_dsa_port_bridge_leave,
 	.port_bridge_join	= yt921x_dsa_port_bridge_join,
+	/* mst */
+	.port_mst_state_set	= yt921x_dsa_port_mst_state_set,
+	.vlan_msti_set		= yt921x_dsa_vlan_msti_set,
+	.port_stp_state_set	= yt921x_dsa_port_stp_state_set,
 	/* port */
 	.get_tag_protocol	= yt921x_dsa_get_tag_protocol,
 	.phylink_get_caps	= yt921x_dsa_phylink_get_caps,
diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
index 85d995cdb7c5..2a986b219080 100644
--- a/drivers/net/dsa/yt921x.h
+++ b/drivers/net/dsa/yt921x.h
@@ -220,6 +220,13 @@
 #define  YT921X_VLAN_IGR_FILTER_PORTn(port)	BIT(port)
 #define YT921X_PORTn_ISOLATION(port)	(0x180294 + 4 * (port))
 #define  YT921X_PORT_ISOLATION_BLOCKn(port)	BIT(port)
+#define YT921X_STPn(n)			(0x18038c + 4 * (n))
+#define  YT921X_STP_PORTn_M(port)		GENMASK(2 * (port) + 1, 2 * (port))
+#define   YT921X_STP_PORTn(port, x)			((x) << (2 * (port)))
+#define   YT921X_STP_PORTn_DISABLED(port)		YT921X_STP_PORTn(port, 0)
+#define   YT921X_STP_PORTn_LEARNING(port)		YT921X_STP_PORTn(port, 1)
+#define   YT921X_STP_PORTn_BLOCKING(port)		YT921X_STP_PORTn(port, 2)
+#define   YT921X_STP_PORTn_FORWARD(port)		YT921X_STP_PORTn(port, 3)
 #define YT921X_PORTn_LEARN(port)	(0x1803d0 + 4 * (port))
 #define  YT921X_PORT_LEARN_VID_LEARN_MULTI_EN	BIT(22)
 #define  YT921X_PORT_LEARN_VID_LEARN_MODE	BIT(21)
@@ -395,6 +402,8 @@ enum yt921x_fdb_entry_status {
 	YT921X_FDB_ENTRY_STATUS_STATIC = 7,
 };
 
+#define YT921X_MSTI_NUM		16
+
 #define YT9215_MAJOR	0x9002
 #define YT9218_MAJOR	0x9001
 
-- 
2.51.0


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

* [PATCH net-next v3 3/4] net: dsa: yt921x: Add HSR offloading support
  2025-11-26  9:32 [PATCH net-next v3 0/4] net: dsa: yt921x: Add STP/MST/HSR/LAG support David Yang
  2025-11-26  9:32 ` [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL David Yang
  2025-11-26  9:32 ` [PATCH net-next v3 2/4] net: dsa: yt921x: Add STP/MST support David Yang
@ 2025-11-26  9:32 ` David Yang
  2025-11-26 16:26   ` Vladimir Oltean
  2025-11-26  9:32 ` [PATCH net-next v3 4/4] net: dsa: yt921x: Add LAG " David Yang
  3 siblings, 1 reply; 10+ messages in thread
From: David Yang @ 2025-11-26  9:32 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Russell King, linux-kernel

Add offloading for packet duplication supported by the YT921x switches.

Signed-off-by: David Yang <mmyangfl@gmail.com>
---
 drivers/net/dsa/yt921x.c | 24 ++++++++++++++++++++++++
 net/dsa/tag_yt921x.c     |  4 ++++
 2 files changed, 28 insertions(+)

diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index e88b4037ee80..e7b416719b58 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -1038,6 +1038,27 @@ static int yt921x_dsa_port_max_mtu(struct dsa_switch *ds, int port)
 	return YT921X_FRAME_SIZE_MAX - ETH_HLEN - ETH_FCS_LEN - YT921X_TAG_LEN;
 }
 
+static int
+yt921x_dsa_port_hsr_leave(struct dsa_switch *ds, int port,
+			  struct net_device *hsr)
+{
+	return 0;
+}
+
+static int
+yt921x_dsa_port_hsr_join(struct dsa_switch *ds, int port,
+			 struct net_device *hsr, struct netlink_ext_ack *extack)
+{
+	struct dsa_port *dp = dsa_to_port(ds, port);
+	struct net_device *user = dp->user;
+
+	/* Nothing special here; we natively support tx packet duplication */
+
+	user->features |= NETIF_F_HW_HSR_DUP;
+
+	return 0;
+}
+
 static int
 yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress)
 {
@@ -2880,6 +2901,9 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = {
 	/* mtu */
 	.port_change_mtu	= yt921x_dsa_port_change_mtu,
 	.port_max_mtu		= yt921x_dsa_port_max_mtu,
+	/* hsr */
+	.port_hsr_leave		= yt921x_dsa_port_hsr_leave,
+	.port_hsr_join		= yt921x_dsa_port_hsr_join,
 	/* mirror */
 	.port_mirror_del	= yt921x_dsa_port_mirror_del,
 	.port_mirror_add	= yt921x_dsa_port_mirror_add,
diff --git a/net/dsa/tag_yt921x.c b/net/dsa/tag_yt921x.c
index 995da44f0a2a..0ad83924fda1 100644
--- a/net/dsa/tag_yt921x.c
+++ b/net/dsa/tag_yt921x.c
@@ -46,6 +46,7 @@ yt921x_tag_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct dsa_port *dp = dsa_user_to_port(netdev);
 	unsigned int port = dp->index;
+	struct dsa_port *partner;
 	__be16 *tag;
 	u16 tx;
 
@@ -59,6 +60,9 @@ yt921x_tag_xmit(struct sk_buff *skb, struct net_device *netdev)
 	tag[1] = 0;
 	tag[2] = 0;
 	tx = YT921X_TAG_PORT_EN | YT921X_TAG_TX_PORTn(port);
+	if (dp->hsr_dev)
+		dsa_hsr_foreach_port(partner, dp->ds, dp->hsr_dev)
+			tx |= YT921X_TAG_TX_PORTn(partner->index);
 	tag[3] = htons(tx);
 
 	return skb;
-- 
2.51.0


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

* [PATCH net-next v3 4/4] net: dsa: yt921x: Add LAG offloading support
  2025-11-26  9:32 [PATCH net-next v3 0/4] net: dsa: yt921x: Add STP/MST/HSR/LAG support David Yang
                   ` (2 preceding siblings ...)
  2025-11-26  9:32 ` [PATCH net-next v3 3/4] net: dsa: yt921x: Add HSR offloading support David Yang
@ 2025-11-26  9:32 ` David Yang
  3 siblings, 0 replies; 10+ messages in thread
From: David Yang @ 2025-11-26  9:32 UTC (permalink / raw)
  To: netdev
  Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Russell King, linux-kernel

Add offloading for a link aggregation group supported by the YT921x
switches.

Signed-off-by: David Yang <mmyangfl@gmail.com>
---
 drivers/net/dsa/yt921x.c | 185 +++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/yt921x.h |  20 +++++
 2 files changed, 205 insertions(+)

diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index e7b416719b58..609dd38adefc 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -1143,6 +1143,187 @@ yt921x_dsa_port_mirror_add(struct dsa_switch *ds, int port,
 	return res;
 }
 
+static int yt921x_lag_hash(struct yt921x_priv *priv, u32 ctrl, bool unique_lag,
+			   struct netlink_ext_ack *extack)
+{
+	u32 val;
+	int res;
+
+	/* Hash Mode is global. Make sure the same Hash Mode is set to all the
+	 * 2 possible lags.
+	 * If we are the unique LAG we can set whatever hash mode we want.
+	 * To change hash mode it's needed to remove all LAG and change the mode
+	 * with the latest.
+	 */
+	if (unique_lag) {
+		res = yt921x_reg_write(priv, YT921X_LAG_HASH, ctrl);
+		if (res)
+			return res;
+	} else {
+		res = yt921x_reg_read(priv, YT921X_LAG_HASH, &val);
+		if (res)
+			return res;
+
+		if (val != ctrl) {
+			NL_SET_ERR_MSG_MOD(extack,
+					   "Mismatched Hash Mode across different lags is not supported");
+			return -EOPNOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
+static int yt921x_lag_leave(struct yt921x_priv *priv, u8 index)
+{
+	return yt921x_reg_write(priv, YT921X_LAG_GROUPn(index), 0);
+}
+
+static int yt921x_lag_join(struct yt921x_priv *priv, u8 index, u16 ports_mask)
+{
+	unsigned long targets_mask = ports_mask;
+	unsigned int cnt;
+	u32 ctrl;
+	int port;
+	int res;
+
+	cnt = 0;
+	for_each_set_bit(port, &targets_mask, YT921X_PORT_NUM) {
+		ctrl = YT921X_LAG_MEMBER_PORT(port);
+		res = yt921x_reg_write(priv, YT921X_LAG_MEMBERnm(index, cnt),
+				       ctrl);
+		if (res)
+			return res;
+
+		cnt++;
+	}
+
+	ctrl = YT921X_LAG_GROUP_PORTS(ports_mask) |
+	       YT921X_LAG_GROUP_MEMBER_NUM(cnt);
+	return yt921x_reg_write(priv, YT921X_LAG_GROUPn(index), ctrl);
+}
+
+static int
+yt921x_dsa_port_lag_leave(struct dsa_switch *ds, int port, struct dsa_lag lag)
+{
+	struct yt921x_priv *priv = to_yt921x_priv(ds);
+	int res;
+
+	if (!lag.id)
+		return -EINVAL;
+
+	mutex_lock(&priv->reg_lock);
+	res = yt921x_lag_leave(priv, lag.id - 1);
+	mutex_unlock(&priv->reg_lock);
+
+	return res;
+}
+
+static int
+yt921x_dsa_port_lag_check(struct dsa_switch *ds, struct dsa_lag lag,
+			  struct netdev_lag_upper_info *info,
+			  struct netlink_ext_ack *extack)
+{
+	unsigned int members;
+	struct dsa_port *dp;
+
+	if (!lag.id)
+		return -EINVAL;
+
+	members = 0;
+	dsa_lag_foreach_port(dp, ds->dst, &lag)
+		/* Includes the port joining the LAG */
+		members++;
+
+	if (members > YT921X_LAG_PORT_NUM) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Cannot offload more than 4 LAG ports");
+		return -EOPNOTSUPP;
+	}
+
+	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Can only offload LAG using hash TX type");
+		return -EOPNOTSUPP;
+	}
+
+	if (info->hash_type != NETDEV_LAG_HASH_L2 &&
+	    info->hash_type != NETDEV_LAG_HASH_L23 &&
+	    info->hash_type != NETDEV_LAG_HASH_L34) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Can only offload L2 or L2+L3 or L3+L4 TX hash");
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int
+yt921x_dsa_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag,
+			 struct netdev_lag_upper_info *info,
+			 struct netlink_ext_ack *extack)
+{
+	struct yt921x_priv *priv = to_yt921x_priv(ds);
+	struct dsa_port *dp;
+	bool unique_lag;
+	unsigned int i;
+	u32 ctrl;
+	int res;
+
+	res = yt921x_dsa_port_lag_check(ds, lag, info, extack);
+	if (res)
+		return res;
+
+	ctrl = 0;
+	switch (info->hash_type) {
+	case NETDEV_LAG_HASH_L34:
+		ctrl |= YT921X_LAG_HASH_IP_DST;
+		ctrl |= YT921X_LAG_HASH_IP_SRC;
+		ctrl |= YT921X_LAG_HASH_IP_PROTO;
+
+		ctrl |= YT921X_LAG_HASH_L4_DPORT;
+		ctrl |= YT921X_LAG_HASH_L4_SPORT;
+		break;
+	case NETDEV_LAG_HASH_L23:
+		ctrl |= YT921X_LAG_HASH_MAC_DA;
+		ctrl |= YT921X_LAG_HASH_MAC_SA;
+
+		ctrl |= YT921X_LAG_HASH_IP_DST;
+		ctrl |= YT921X_LAG_HASH_IP_SRC;
+		ctrl |= YT921X_LAG_HASH_IP_PROTO;
+		break;
+	case NETDEV_LAG_HASH_L2:
+		ctrl |= YT921X_LAG_HASH_MAC_DA;
+		ctrl |= YT921X_LAG_HASH_MAC_SA;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	/* Check if we are the unique configured LAG */
+	unique_lag = true;
+	dsa_lags_foreach_id(i, ds->dst)
+		if (i != lag.id && dsa_lag_by_id(ds->dst, i)) {
+			unique_lag = false;
+			break;
+		}
+
+	mutex_lock(&priv->reg_lock);
+	do {
+		res = yt921x_lag_hash(priv, ctrl, unique_lag, extack);
+		if (res)
+			break;
+
+		ctrl = 0;
+		dsa_lag_foreach_port(dp, ds->dst, &lag)
+			ctrl |= BIT(dp->index);
+		res = yt921x_lag_join(priv, lag.id - 1, ctrl);
+	} while (0);
+	mutex_unlock(&priv->reg_lock);
+
+	return res;
+}
+
 static int yt921x_fdb_wait(struct yt921x_priv *priv, u32 *valp)
 {
 	struct device *dev = to_device(priv);
@@ -2907,6 +3088,9 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = {
 	/* mirror */
 	.port_mirror_del	= yt921x_dsa_port_mirror_del,
 	.port_mirror_add	= yt921x_dsa_port_mirror_add,
+	/* lag */
+	.port_lag_leave		= yt921x_dsa_port_lag_leave,
+	.port_lag_join		= yt921x_dsa_port_lag_join,
 	/* fdb */
 	.port_fdb_dump		= yt921x_dsa_port_fdb_dump,
 	.port_fast_age		= yt921x_dsa_port_fast_age,
@@ -3001,6 +3185,7 @@ static int yt921x_mdio_probe(struct mdio_device *mdiodev)
 	ds->priv = priv;
 	ds->ops = &yt921x_dsa_switch_ops;
 	ds->phylink_mac_ops = &yt921x_phylink_mac_ops;
+	ds->num_lag_ids = YT921X_LAG_NUM;
 	ds->num_ports = YT921X_PORT_NUM;
 
 	mdiodev_set_drvdata(mdiodev, priv);
diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
index 2a986b219080..0afd90461108 100644
--- a/drivers/net/dsa/yt921x.h
+++ b/drivers/net/dsa/yt921x.h
@@ -316,6 +316,14 @@
 #define  YT921X_FILTER_PORTn(port)		BIT(port)
 #define YT921X_VLAN_EGR_FILTER		0x180598
 #define  YT921X_VLAN_EGR_FILTER_PORTn(port)	BIT(port)
+#define YT921X_LAG_GROUPn(n)		(0x1805a8 + 4 * (n))
+#define  YT921X_LAG_GROUP_PORTS_M		GENMASK(13, 3)
+#define   YT921X_LAG_GROUP_PORTS(x)			FIELD_PREP(YT921X_LAG_GROUP_PORTS_M, (x))
+#define  YT921X_LAG_GROUP_MEMBER_NUM_M		GENMASK(2, 0)
+#define   YT921X_LAG_GROUP_MEMBER_NUM(x)		FIELD_PREP(YT921X_LAG_GROUP_MEMBER_NUM_M, (x))
+#define YT921X_LAG_MEMBERnm(n, m)	(0x1805b0 + 4 * (4 * (n) + (m)))
+#define  YT921X_LAG_MEMBER_PORT_M		GENMASK(3, 0)
+#define   YT921X_LAG_MEMBER_PORT(x)			FIELD_PREP(YT921X_LAG_MEMBER_PORT_M, (x))
 #define YT921X_CPU_COPY			0x180690
 #define  YT921X_CPU_COPY_FORCE_INT_PORT		BIT(2)
 #define  YT921X_CPU_COPY_TO_INT_CPU		BIT(1)
@@ -360,6 +368,15 @@
 #define  YT921X_PORT_IGR_TPIDn_STAG(x)		BIT((x) + 4)
 #define  YT921X_PORT_IGR_TPIDn_CTAG_M		GENMASK(3, 0)
 #define  YT921X_PORT_IGR_TPIDn_CTAG(x)		BIT(x)
+#define YT921X_LAG_HASH			0x210090
+#define  YT921X_LAG_HASH_L4_SPORT		BIT(7)
+#define  YT921X_LAG_HASH_L4_DPORT		BIT(6)
+#define  YT921X_LAG_HASH_IP_PROTO		BIT(5)
+#define  YT921X_LAG_HASH_IP_SRC			BIT(4)
+#define  YT921X_LAG_HASH_IP_DST			BIT(3)
+#define  YT921X_LAG_HASH_MAC_SA			BIT(2)
+#define  YT921X_LAG_HASH_MAC_DA			BIT(1)
+#define  YT921X_LAG_HASH_SRC_PORT		BIT(0)
 
 #define YT921X_PORTn_VLAN_CTRL(port)	(0x230010 + 4 * (port))
 #define  YT921X_PORT_VLAN_CTRL_SVLAN_PRI_EN	BIT(31)
@@ -404,6 +421,9 @@ enum yt921x_fdb_entry_status {
 
 #define YT921X_MSTI_NUM		16
 
+#define YT921X_LAG_NUM		2
+#define YT921X_LAG_PORT_NUM	4
+
 #define YT9215_MAJOR	0x9002
 #define YT9218_MAJOR	0x9001
 
-- 
2.51.0


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

* Re: [PATCH net-next v3 3/4] net: dsa: yt921x: Add HSR offloading support
  2025-11-26  9:32 ` [PATCH net-next v3 3/4] net: dsa: yt921x: Add HSR offloading support David Yang
@ 2025-11-26 16:26   ` Vladimir Oltean
  0 siblings, 0 replies; 10+ messages in thread
From: Vladimir Oltean @ 2025-11-26 16:26 UTC (permalink / raw)
  To: David Yang
  Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King,
	linux-kernel

On Wed, Nov 26, 2025 at 05:32:36PM +0800, David Yang wrote:
> Add offloading for packet duplication supported by the YT921x switches.
> 
> Signed-off-by: David Yang <mmyangfl@gmail.com>
> ---

I like the idea behind this patch from a purely technical perspective,
but there's an important question. Do you, or people you know or have
interacted with, use HSR/PRP on the YT921x switches, in order to find
this change useful?

If NETIF_F_HW_HSR_DUP is the only offload that the switch supports, then
one can hardly say that the switch was designed to be an HSR accelerator.
I'm working on some patches to make this feature generically available
to most DSA switch drivers, rather than being arbitrarily implemented
here and there. The usefulness of having this single offload generally
available is where I am lacking some data points.

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

* Re: [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL
  2025-11-26  9:32 ` [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL David Yang
@ 2025-11-28  1:58   ` Jakub Kicinski
  2025-11-28 10:51   ` david laight
  1 sibling, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2025-11-28  1:58 UTC (permalink / raw)
  To: David Yang
  Cc: netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Paolo Abeni, Simon Horman, Russell King,
	linux-kernel

On Wed, 26 Nov 2025 17:32:34 +0800 David Yang wrote:
> VLAN_CTRL should be treated as a 64-bit register. GENMASK and BIT
> macros use unsigned long as the underlying type, which will result in a
> build error on architectures where sizeof(long) == 32.

nit: sizeof(long) == 4 ?

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

* Re: [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL
  2025-11-26  9:32 ` [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL David Yang
  2025-11-28  1:58   ` Jakub Kicinski
@ 2025-11-28 10:51   ` david laight
  2025-11-28 11:43     ` Russell King (Oracle)
  1 sibling, 1 reply; 10+ messages in thread
From: david laight @ 2025-11-28 10:51 UTC (permalink / raw)
  To: David Yang
  Cc: netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Russell King, linux-kernel

On Wed, 26 Nov 2025 17:32:34 +0800
David Yang <mmyangfl@gmail.com> wrote:

> VLAN_CTRL should be treated as a 64-bit register. GENMASK and BIT
> macros use unsigned long as the underlying type, which will result in a
> build error on architectures where sizeof(long) == 4.

I suspect GENMASK() should generate u32 or u64 depending on the value
of a constant 'high bit'.

I found code elsewhere that doesn't really want FIELD_PREP() to
generate a 64bit value.

There are actually a lot of dubious uses of 'long' throughout
the kernel that break on 32bit.
(Actually pretty much all of them!)

	David



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

* Re: [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL
  2025-11-28 10:51   ` david laight
@ 2025-11-28 11:43     ` Russell King (Oracle)
  2025-11-28 19:25       ` david laight
  0 siblings, 1 reply; 10+ messages in thread
From: Russell King (Oracle) @ 2025-11-28 11:43 UTC (permalink / raw)
  To: david laight
  Cc: David Yang, netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	linux-kernel

On Fri, Nov 28, 2025 at 10:51:41AM +0000, david laight wrote:
> On Wed, 26 Nov 2025 17:32:34 +0800
> David Yang <mmyangfl@gmail.com> wrote:
> 
> > VLAN_CTRL should be treated as a 64-bit register. GENMASK and BIT
> > macros use unsigned long as the underlying type, which will result in a
> > build error on architectures where sizeof(long) == 4.
> 
> I suspect GENMASK() should generate u32 or u64 depending on the value
> of a constant 'high bit'.

I suggest checking before making such statements to save embarrasment.
The above is incorrect.

#define GENMASK_TYPE(t, h, l)                                   \
        ((t)(GENMASK_INPUT_CHECK(h, l) +                        \
             (type_max(t) << (l) &                              \
              type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h)))))

#define GENMASK(h, l)           GENMASK_TYPE(unsigned long, h, l)
#define GENMASK_ULL(h, l)       GENMASK_TYPE(unsigned long long, h, l)

#define GENMASK_U8(h, l)        GENMASK_TYPE(u8, h, l)
#define GENMASK_U16(h, l)       GENMASK_TYPE(u16, h, l)
#define GENMASK_U32(h, l)       GENMASK_TYPE(u32, h, l)
#define GENMASK_U64(h, l)       GENMASK_TYPE(u64, h, l)
#define GENMASK_U128(h, l)      GENMASK_TYPE(u128, h, l)

Note that GENMASK(33, 15) will fail to build on 32-bit systems.

> I found code elsewhere that doesn't really want FIELD_PREP() to
> generate a 64bit value.
> 
> There are actually a lot of dubious uses of 'long' throughout
> the kernel that break on 32bit.
> (Actually pretty much all of them!)

If you're referring to the use of GENMASK() with bitfields larger
than 32-bits, then as can be seen from the above, the code wouldn't
even compile and our CI systems would be screaming about it. They
aren't, so I think your statement here is also wrong.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

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

* Re: [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL
  2025-11-28 11:43     ` Russell King (Oracle)
@ 2025-11-28 19:25       ` david laight
  0 siblings, 0 replies; 10+ messages in thread
From: david laight @ 2025-11-28 19:25 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: David Yang, netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	linux-kernel

On Fri, 28 Nov 2025 11:43:17 +0000
"Russell King (Oracle)" <linux@armlinux.org.uk> wrote:

> On Fri, Nov 28, 2025 at 10:51:41AM +0000, david laight wrote:
> > On Wed, 26 Nov 2025 17:32:34 +0800
> > David Yang <mmyangfl@gmail.com> wrote:
> >   
> > > VLAN_CTRL should be treated as a 64-bit register. GENMASK and BIT
> > > macros use unsigned long as the underlying type, which will result in a
> > > build error on architectures where sizeof(long) == 4.  
> > 
> > I suspect GENMASK() should generate u32 or u64 depending on the value
> > of a constant 'high bit'.  
> 
> I suggest checking before making such statements to save embarrasment.
> The above is incorrect.

Is was a suggestion about what it would be a good idea for it to do,
not a statement about what it actually does.
I know GENMASK() generates 'unsigned long'.
The problem is that (as here) if the value is larger than u32 you get
a build error on 32bit,
Then you get the opposite problem that any portable code has to handle
the fact that the result type is (effectively) u64 on 64bit so
you get unwanted (or just unnecessary) integer promotions where the
result is used.
Given that pretty much all GENMASK() are used for hardware bit-patterns
not having a fixed size result type seems wrong.

The newly added GENMASK_U8() and GENMASK_U16() are also pointless.
Integer promotion converts the value to 'signed int' before it
is used.

>... 
> > I found code elsewhere that doesn't really want FIELD_PREP() to
> > generate a 64bit value.
> > 
> > There are actually a lot of dubious uses of 'long' throughout
> > the kernel that break on 32bit.
> > (Actually pretty much all of them!)  
> 
> If you're referring to the use of GENMASK() with bitfields larger
> than 32-bits, then as can be seen from the above, the code wouldn't
> even compile and our CI systems would be screaming about it. They
> aren't, so I think your statement here is also wrong.

No, I'm talking about a 'normal' FIELD_PREP(GENMASK(7, 5), val) having
a 64bit type on 64bit.
It tripped up my min_t(int, ) 'cast truncation test' a few times :-)

The problem with with 'long' is more pervasive.
It gets used for 'quite big' values that are clearly independent of whether
a 32bit or 64bit kernel is being built.
You're going to want to see an example, I think this overflows badly on 32bit:
static long pll1443x_calc_kdiv(int mdiv, int pdiv, int sdiv,
		unsigned long rate, unsigned long prate)
{
	long kdiv;

	/* calc kdiv = round(rate * pdiv * 65536 * 2^sdiv / prate) - (mdiv * 65536) */
	kdiv = ((rate * ((pdiv * 65536) << sdiv) + prate / 2) / prate) - (mdiv * 65536);

	return clamp_t(short, kdiv, KDIV_MIN, KDIV_MAX);
}
https://elixir.bootlin.com/linux/v6.18-rc6/source/drivers/clk/imx/clk-pll14xx.c#L120
(Spot the non-functional clamp_t() - which is why I found this code.)

I'm sure I've seen fs code comparing u64 and ulong that both hold block numbers.
Such code should really only use fixed size types.
Either a value fits in 32bits, so int or u32 is fine; or it doesn't and you
need a u64. 'long' doesn't enter into it.

	David




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

end of thread, other threads:[~2025-11-28 19:26 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-26  9:32 [PATCH net-next v3 0/4] net: dsa: yt921x: Add STP/MST/HSR/LAG support David Yang
2025-11-26  9:32 ` [PATCH net-next v3 1/4] net: dsa: yt921x: Use *_ULL bitfield macros for VLAN_CTRL David Yang
2025-11-28  1:58   ` Jakub Kicinski
2025-11-28 10:51   ` david laight
2025-11-28 11:43     ` Russell King (Oracle)
2025-11-28 19:25       ` david laight
2025-11-26  9:32 ` [PATCH net-next v3 2/4] net: dsa: yt921x: Add STP/MST support David Yang
2025-11-26  9:32 ` [PATCH net-next v3 3/4] net: dsa: yt921x: Add HSR offloading support David Yang
2025-11-26 16:26   ` Vladimir Oltean
2025-11-26  9:32 ` [PATCH net-next v3 4/4] net: dsa: yt921x: Add LAG " David Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).