[PATCH net-next 1/3] net: dsa: yt921x: Refactor long register helpers
From: David Yang <mmyangfl@gmail.com>
Date: 2026-02-25 09:09:15
Also in:
lkml
Subsystem:
motorcomm yt921x ethernet switch driver, networking drivers, networking [dsa], the rest · Maintainers:
David Yang, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Linus Torvalds
Dealing long registers with u64 is good, until you realize there are longer registers that are 96 bits. Use u32 arrays instead. Signed-off-by: David Yang <mmyangfl@gmail.com> --- drivers/net/dsa/yt921x.c | 152 +++++++++++++++++++++++++-------------- drivers/net/dsa/yt921x.h | 37 +++++----- 2 files changed, 116 insertions(+), 73 deletions(-)
diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index 98e8915dd6c2..fedc72202d1e 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c@@ -255,63 +255,102 @@ yt921x_reg_toggle_bits(struct yt921x_priv *priv, u32 reg, u32 mask, bool set) return yt921x_reg_update_bits(priv, reg, mask, !set ? 0 : mask); } -/* Some registers, like VLANn_CTRL, should always be written in 64-bit, even if - * you are to write only the lower / upper 32 bits. +/* Some registers, like VLANn_CTRL, should always be written in chunks, even if + * you only want to write parts of 32 bits. * - * There is no such restriction for reading, but we still provide 64-bit read - * wrappers so that we always handle u64 values. + * There is no such restriction for reading, but we still provide multi-chunk + * read wrappers so that we can handle them consistently. */ -static int yt921x_reg64_read(struct yt921x_priv *priv, u32 reg, u64 *valp) +static int +yt921x_longreg_read(struct yt921x_priv *priv, u32 reg, u32 *vals, + unsigned int span) { - u32 lo; - u32 hi; int res; - res = yt921x_reg_read(priv, reg, &lo); - if (res) - return res; - res = yt921x_reg_read(priv, reg + 4, &hi); - if (res) - return res; + for (unsigned int i = 0; i < span; i++) { + res = yt921x_reg_read(priv, reg + 4 * i, &vals[i]); + if (res) + return res; + } - *valp = ((u64)hi << 32) | lo; return 0; } -static int yt921x_reg64_write(struct yt921x_priv *priv, u32 reg, u64 val) +static int +yt921x_longreg_write(struct yt921x_priv *priv, u32 reg, const u32 *vals, + unsigned int span) { int res; - res = yt921x_reg_write(priv, reg, (u32)val); - if (res) - return res; - return yt921x_reg_write(priv, reg + 4, (u32)(val >> 32)); + for (unsigned int i = 0; i < span; i++) { + res = yt921x_reg_write(priv, reg + 4 * i, vals[i]); + if (res) + return res; + } + + return 0; } static int -yt921x_reg64_update_bits(struct yt921x_priv *priv, u32 reg, u64 mask, u64 val) +yt921x_longreg_update_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks, + const u32 *vals, unsigned int span) { + bool changed = false; + u32 vs[4]; int res; - u64 v; - u64 u; - res = yt921x_reg64_read(priv, reg, &v); + BUILD_BUG_ON(span > ARRAY_SIZE(vs)); + + res = yt921x_longreg_read(priv, reg, vs, span); if (res) return res; - u = v; - u &= ~mask; - u |= val; - if (u == v) + for (unsigned int i = 0; i < span; i++) { + u32 u = vs[i]; + + u &= ~masks[i]; + u |= vals[i]; + if (u != vs[i]) + changed = true; + + vs[i] = u; + } + + if (!changed) return 0; - return yt921x_reg64_write(priv, reg, u); + return yt921x_longreg_write(priv, reg, vs, span); } -static int yt921x_reg64_clear_bits(struct yt921x_priv *priv, u32 reg, u64 mask) +static int +yt921x_longreg_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks, + unsigned int span) { - return yt921x_reg64_update_bits(priv, reg, mask, 0); + bool changed = false; + u32 vs[4]; + int res; + + BUILD_BUG_ON(span > ARRAY_SIZE(vs)); + + res = yt921x_longreg_read(priv, reg, vs, span); + if (res) + return res; + + for (unsigned int i = 0; i < span; i++) { + u32 u = vs[i]; + + u &= ~masks[i]; + if (u != vs[i]) + changed = true; + + vs[i] = u; + } + + if (!changed) + return 0; + + return yt921x_longreg_write(priv, reg, vs, span); } static int yt921x_reg_mdio_read(void *context, u32 reg, u32 *valp)
@@ -1844,33 +1883,32 @@ yt921x_vlan_filtering(struct yt921x_priv *priv, int port, bool vlan_filtering) return 0; } -static int -yt921x_vlan_del(struct yt921x_priv *priv, int port, u16 vid) +static int yt921x_vlan_del(struct yt921x_priv *priv, int port, u16 vid) { - u64 mask64; + u32 masks[YT921X_VLAN_CTRL_S]; - mask64 = YT921X_VLAN_CTRL_PORTS(port) | - YT921X_VLAN_CTRL_UNTAG_PORTn(port); + masks[0] = YT921X_VLAN_CTRLa_PORTn(port); + masks[1] = YT921X_VLAN_CTRLb_UNTAG_PORTn(port); - return yt921x_reg64_clear_bits(priv, YT921X_VLANn_CTRL(vid), mask64); + return yt921x_longreg_clear_bits(priv, YT921X_VLANn_CTRL(vid), masks, + YT921X_VLAN_CTRL_S); } static int yt921x_vlan_add(struct yt921x_priv *priv, int port, u16 vid, bool untagged) { - u64 mask64; - u64 ctrl64; + u32 masks[YT921X_VLAN_CTRL_S]; + u32 ctrls[YT921X_VLAN_CTRL_S]; - mask64 = YT921X_VLAN_CTRL_PORTn(port) | - YT921X_VLAN_CTRL_PORTS(priv->cpu_ports_mask); - ctrl64 = mask64; + masks[0] = YT921X_VLAN_CTRLa_PORTn(port) | + YT921X_VLAN_CTRLa_PORTS(priv->cpu_ports_mask); + ctrls[0] = masks[0]; - mask64 |= YT921X_VLAN_CTRL_UNTAG_PORTn(port); - if (untagged) - ctrl64 |= YT921X_VLAN_CTRL_UNTAG_PORTn(port); + masks[1] = YT921X_VLAN_CTRLb_UNTAG_PORTn(port); + ctrls[1] = untagged ? masks[1] : 0; - return yt921x_reg64_update_bits(priv, YT921X_VLANn_CTRL(vid), - mask64, ctrl64); + return yt921x_longreg_update_bits(priv, YT921X_VLANn_CTRL(vid), + masks, ctrls, YT921X_VLAN_CTRL_S); } static int
@@ -2331,8 +2369,8 @@ 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; + u32 masks[YT921X_VLAN_CTRL_S]; + u32 ctrls[YT921X_VLAN_CTRL_S]; int res; if (!msti->vid)
@@ -2340,12 +2378,14 @@ yt921x_dsa_vlan_msti_set(struct dsa_switch *ds, struct dsa_bridge bridge, 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); + masks[0] = 0; + ctrls[0] = 0; + masks[1] = YT921X_VLAN_CTRLb_STP_ID_M; + ctrls[1] = YT921X_VLAN_CTRLb_STP_ID(msti->msti); mutex_lock(&priv->reg_lock); - res = yt921x_reg64_update_bits(priv, YT921X_VLANn_CTRL(msti->vid), - mask64, ctrl64); + res = yt921x_longreg_update_bits(priv, YT921X_VLANn_CTRL(msti->vid), + masks, ctrls, YT921X_VLAN_CTRL_S); mutex_unlock(&priv->reg_lock); return res;
@@ -3096,8 +3136,8 @@ static int yt921x_chip_reset(struct yt921x_priv *priv) static int yt921x_chip_setup_dsa(struct yt921x_priv *priv) { struct dsa_switch *ds = &priv->ds; + u32 ctrls[YT921X_VLAN_CTRL_S]; unsigned long cpu_ports_mask; - u64 ctrl64; u32 ctrl; int port; int res;
@@ -3158,8 +3198,10 @@ static int yt921x_chip_setup_dsa(struct yt921x_priv *priv) /* Tagged VID 0 should be treated as untagged, which confuses the * hardware a lot */ - ctrl64 = YT921X_VLAN_CTRL_LEARN_DIS | YT921X_VLAN_CTRL_PORTS_M; - res = yt921x_reg64_write(priv, YT921X_VLANn_CTRL(0), ctrl64); + ctrls[0] = YT921X_VLAN_CTRLa_LEARN_DIS | YT921X_VLAN_CTRLa_PORTS_M; + ctrls[1] = 0; + res = yt921x_longreg_write(priv, YT921X_VLANn_CTRL(0), ctrls, + YT921X_VLAN_CTRL_S); if (res) return res;
diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
index 3f129b8d403f..361470582687 100644
--- a/drivers/net/dsa/yt921x.h
+++ b/drivers/net/dsa/yt921x.h@@ -429,24 +429,25 @@ enum yt921x_app_selector { #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_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_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_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_ULL(22) -#define YT921X_VLAN_CTRL_PRIO_EN BIT_ULL(21) -#define YT921X_VLAN_CTRL_PRIO_M GENMASK_ULL(20, 18) -#define YT921X_VLAN_CTRL_PRIO(x) FIELD_PREP(YT921X_VLAN_CTRL_PRIO_M, (x)) -#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_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_VLAN_CTRL_S 2 +#define YT921X_VLAN_CTRLb_UNTAG_PORTS_M GENMASK(18, 8) +#define YT921X_VLAN_CTRLb_UNTAG_PORTS(x) FIELD_PREP(YT921X_VLAN_CTRLb_UNTAG_PORTS_M, (x)) +#define YT921X_VLAN_CTRLb_UNTAG_PORTn(port) BIT((port) + 8) +#define YT921X_VLAN_CTRLb_STP_ID_M GENMASK(7, 4) +#define YT921X_VLAN_CTRLb_STP_ID(x) FIELD_PREP(YT921X_VLAN_CTRLb_STP_ID_M, (x)) +#define YT921X_VLAN_CTRLb_SVLAN_EN BIT(3) +#define YT921X_VLAN_CTRLab_FID_M GENMASK_ULL(34, 23) +#define YT921X_VLAN_CTRLab_FID(x) FIELD_PREP(YT921X_VLAN_CTRLab_FID_M, (x)) +#define YT921X_VLAN_CTRLa_LEARN_DIS BIT(22) +#define YT921X_VLAN_CTRLa_PRIO_EN BIT(21) +#define YT921X_VLAN_CTRLa_PRIO_M GENMASK(20, 18) +#define YT921X_VLAN_CTRLa_PRIO(x) FIELD_PREP(YT921X_VLAN_CTRLa_PRIO_M, (x)) +#define YT921X_VLAN_CTRLa_PORTS_M GENMASK(17, 7) +#define YT921X_VLAN_CTRLa_PORTS(x) FIELD_PREP(YT921X_VLAN_CTRLa_PORTS_M, (x)) +#define YT921X_VLAN_CTRLa_PORTn(port) BIT((port) + 7) +#define YT921X_VLAN_CTRLa_BYPASS_1X_AC BIT(6) +#define YT921X_VLAN_CTRLa_METER_EN BIT(5) +#define YT921X_VLAN_CTRLa_METER_ID_M GENMASK(4, 0) #define YT921X_TPID_IGRn(x) (0x210000 + 4 * (x)) /* [0, 3] */ #define YT921X_TPID_IGR_TPID_M GENMASK(15, 0)
--
2.51.0