* [RFC net-next 1/4] net: dsa: yt921x: Refactor port error message
2026-01-29 8:51 [RFC net-next 0/4] net: dsa: yt921x: Add tc support David Yang
@ 2026-01-29 8:51 ` David Yang
2026-01-29 8:51 ` [RFC net-next 2/4] net: dsa: yt921x: Refactor long register helpers David Yang
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: David Yang @ 2026-01-29 8:51 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
Sometimes we might get error codes from the underlying bus but the
return type of the method is void, so an error message is desired.
There're many instances of the same pattern, refactor it.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/dsa/yt921x.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index 112c2a237d9c..1b66b07f45b2 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -185,6 +185,9 @@ struct yt921x_reg_mdio {
#define to_yt921x_priv(_ds) container_of_const(_ds, struct yt921x_priv, ds)
#define to_device(priv) ((priv)->ds.dev)
+#define print_port_err(dev, port, res, action) dev_err( \
+ (dev), "Failed to %s port %d: %i\n", (action), (port), (res))
+
static int yt921x_reg_read(struct yt921x_priv *priv, u32 reg, u32 *valp)
{
WARN_ON(!mutex_is_locked(&priv->reg_lock));
@@ -720,8 +723,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
mib->tx_jumbo;
if (res)
- dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
- port, res);
+ print_port_err(dev, port, res, "read stats for");
return res;
}
@@ -1101,8 +1103,7 @@ yt921x_dsa_port_mirror_del(struct dsa_switch *ds, int port,
mutex_unlock(&priv->reg_lock);
if (res)
- dev_err(dev, "Failed to %s port %d: %i\n", "unmirror",
- port, res);
+ print_port_err(dev, port, res, "unmirror");
}
static int
@@ -1689,8 +1690,7 @@ static void yt921x_dsa_port_fast_age(struct dsa_switch *ds, int port)
mutex_unlock(&priv->reg_lock);
if (res)
- dev_err(dev, "Failed to %s port %d: %i\n", "clear FDB for",
- port, res);
+ print_port_err(dev, port, res, "clear FDB for");
}
static int
@@ -2265,8 +2265,7 @@ yt921x_dsa_port_bridge_leave(struct dsa_switch *ds, int port,
mutex_unlock(&priv->reg_lock);
if (res)
- dev_err(dev, "Failed to %s port %d: %i\n", "unbridge",
- port, res);
+ print_port_err(dev, port, res, "unbridge");
}
static int
@@ -2398,8 +2397,7 @@ yt921x_dsa_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
mutex_unlock(&priv->reg_lock);
if (res)
- dev_err(dev, "Failed to %s port %d: %i\n", "set STP state for",
- port, res);
+ print_port_err(dev, port, res, "set STP state for");
}
static int __maybe_unused
@@ -2737,8 +2735,7 @@ yt921x_phylink_mac_link_down(struct phylink_config *config, unsigned int mode,
mutex_unlock(&priv->reg_lock);
if (res)
- dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring down",
- port, res);
+ print_port_err(dp->ds->dev, port, res, "bring down");
}
static void
@@ -2758,8 +2755,7 @@ yt921x_phylink_mac_link_up(struct phylink_config *config,
mutex_unlock(&priv->reg_lock);
if (res)
- dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring up",
- port, res);
+ print_port_err(dp->ds->dev, port, res, "bring up");
schedule_delayed_work(&priv->ports[port].mib_read, 0);
}
@@ -2778,8 +2774,7 @@ yt921x_phylink_mac_config(struct phylink_config *config, unsigned int mode,
mutex_unlock(&priv->reg_lock);
if (res)
- dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "config",
- port, res);
+ print_port_err(dp->ds->dev, port, res, "config");
}
static void
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [RFC net-next 2/4] net: dsa: yt921x: Refactor long register helpers
2026-01-29 8:51 [RFC net-next 0/4] net: dsa: yt921x: Add tc support David Yang
2026-01-29 8:51 ` [RFC net-next 1/4] net: dsa: yt921x: Refactor port error message David Yang
@ 2026-01-29 8:51 ` David Yang
2026-01-29 8:51 ` [RFC net-next 3/4] net: dsa: yt921x: Add port police support David Yang
2026-01-29 8:51 ` [RFC net-next 4/4] net: dsa: yt921x: Add port qdisc tbf support David Yang
3 siblings, 0 replies; 5+ messages in thread
From: David Yang @ 2026-01-29 8:51 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
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 1b66b07f45b2..6d03888b6743 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -258,63 +258,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)
@@ -1843,33 +1882,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
@@ -2329,8 +2367,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)
@@ -2338,12 +2376,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;
@@ -3090,8 +3130,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;
@@ -3152,8 +3192,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
^ permalink raw reply related [flat|nested] 5+ messages in thread* [RFC net-next 3/4] net: dsa: yt921x: Add port police support
2026-01-29 8:51 [RFC net-next 0/4] net: dsa: yt921x: Add tc support David Yang
2026-01-29 8:51 ` [RFC net-next 1/4] net: dsa: yt921x: Refactor port error message David Yang
2026-01-29 8:51 ` [RFC net-next 2/4] net: dsa: yt921x: Refactor long register helpers David Yang
@ 2026-01-29 8:51 ` David Yang
2026-01-29 8:51 ` [RFC net-next 4/4] net: dsa: yt921x: Add port qdisc tbf support David Yang
3 siblings, 0 replies; 5+ messages in thread
From: David Yang @ 2026-01-29 8:51 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
Enable rate meter ability and support limiting the rate of incoming
traffic.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/dsa/yt921x.c | 255 ++++++++++++++++++++++++++++++++++++++-
drivers/net/dsa/yt921x.h | 56 +++++++++
2 files changed, 310 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index 6d03888b6743..f1465c4d9b1b 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -356,6 +356,14 @@ yt921x_longreg_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks,
return yt921x_longreg_write(priv, reg, vs, span);
}
+static void u32a_update_u64(u32 *arr, u64 mask, u64 val)
+{
+ arr[0] &= ~((u32)mask);
+ arr[1] &= ~((u32)(mask >> 32));
+ arr[0] |= (u32)val;
+ arr[1] |= (u32)(val >> 32);
+}
+
static int yt921x_reg_mdio_read(void *context, u32 reg, u32 *valp)
{
struct yt921x_reg_mdio *mdio = context;
@@ -1047,6 +1055,13 @@ yt921x_dsa_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e)
return res;
}
+static int yt921x_mtu_fetch(struct yt921x_priv *priv, int port)
+{
+ struct dsa_port *dp = dsa_to_port(&priv->ds, port);
+
+ return dp->user ? READ_ONCE(dp->user->mtu) : ETH_DATA_LEN;
+}
+
static int
yt921x_dsa_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
@@ -1078,6 +1093,204 @@ 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;
}
+/* v * 2^e */
+#define ldexpi(v, e) ({ \
+ __auto_type _v = (v); \
+ __auto_type _e = (e); \
+ _e >= 0 ? _v << _e : _v >> -_e; \
+})
+
+/* slot (ns) * rate (/s) / 10^9 (ns/s) = 2^C * token * 4^unit */
+#define rate2token(rate, unit, slot_ns, C) \
+ ((u32)(ldexpi((slot_ns) * (rate), \
+ -(2 * (unit) + (C) + YT921X_TOKEN_RATE_C)) / 1000000000))
+#define token2rate(token, unit, slot_ns, C) \
+ (ldexpi(1000000000 * (u64)(token), \
+ 2 * (unit) + (C) + YT921X_TOKEN_RATE_C) / (slot_ns))
+
+/* burst = 2^C * token * 4^unit */
+#define burst2token(burst, unit, C) ((u32)ldexpi((burst), -(2 * (unit) + (C))))
+#define token2burst(token, unit, C) ldexpi((u64)(token), 2 * (unit) + (C))
+
+struct yt921x_meter {
+ u32 cir;
+ u32 cbs;
+ u32 ebs;
+ int unit;
+};
+
+#define YT921X_METER_PKT_MODE BIT(0)
+#define YT921X_METER_SINGLE_BUCKET BIT(1)
+
+static struct yt921x_meter
+yt921x_meter_tfm(struct yt921x_priv *priv, int port, unsigned int slot_ns,
+ u64 rate, u64 burst, unsigned int flags,
+ u32 cir_max, u32 cbs_max, int unit_max)
+{
+ const int C = flags & YT921X_METER_PKT_MODE ? YT921X_TOKEN_PKT_C :
+ YT921X_TOKEN_BYTE_C;
+ struct device *dev = to_device(priv);
+ struct yt921x_meter meter;
+ bool distorted;
+ u64 burst_est;
+ u64 burst_max;
+ u64 rate_max;
+
+ meter.unit = unit_max;
+ rate_max = token2rate(cir_max, meter.unit, slot_ns, C);
+ burst_max = token2burst(cbs_max, meter.unit, C);
+
+ /* clamp rate and burst */
+ if (rate > rate_max || burst > burst_max) {
+ dev_warn(dev,
+ "rate %llu, burst %llu too high, max is %llu, %llu, clamping...\n",
+ rate, burst, rate_max, burst_max);
+
+ if (rate > rate_max)
+ rate = rate_max;
+ if (burst > burst_max)
+ burst = burst_max;
+
+ burst_est = slot_ns * rate / 1000000000;
+ } else {
+ u64 burst_sug;
+
+ burst_est = slot_ns * rate / 1000000000;
+ burst_sug = burst_est;
+ if (flags & YT921X_METER_PKT_MODE)
+ burst_sug++;
+ else
+ burst_sug += ETH_HLEN + yt921x_mtu_fetch(priv, port) +
+ ETH_FCS_LEN;
+ if (burst_sug > burst)
+ dev_warn(dev,
+ "Consider using burst at least %llu to match rate %llu\n",
+ burst_sug, rate);
+
+ /* select unit */
+ for (; meter.unit > 0; meter.unit--) {
+ if (rate > (rate_max >> 2) || burst > (burst_max >> 2))
+ break;
+ rate_max >>= 2;
+ burst_max >>= 2;
+ }
+ }
+
+ /* calculate information rate and bucket size */
+ distorted = false;
+ meter.cir = rate2token(rate, meter.unit, slot_ns, C);
+ if (!meter.cir) {
+ distorted = true;
+ meter.cir = 1;
+ } else if (meter.cir > cir_max) {
+ WARN_ON(1);
+ meter.cir = cir_max;
+ }
+ meter.cbs = burst2token(burst, meter.unit, C);
+ if (!meter.cbs) {
+ distorted = true;
+ meter.cbs = 1;
+ } else if (meter.cbs > cbs_max) {
+ WARN_ON(1);
+ meter.cbs = cbs_max;
+ }
+ if (distorted)
+ dev_warn(dev,
+ "Have to increase rate %llu, burst %llu to %llu, %llu\n",
+ rate, burst,
+ token2rate(meter.cir, meter.unit, slot_ns, C),
+ token2burst(meter.cbs, meter.unit, C));
+
+ /* cut ebs */
+ meter.ebs = 0;
+ if (!(flags & YT921X_METER_SINGLE_BUCKET)) {
+ /* we don't have a chance to adjust rate when MTU is changed */
+ if (flags & YT921X_METER_PKT_MODE)
+ burst_est++;
+ else
+ burst_est += YT921X_FRAME_SIZE_MAX;
+
+ if (burst_est < burst) {
+ u32 pbs = meter.cbs;
+
+ meter.cbs = burst2token(burst_est, meter.unit, C);
+ if (!meter.cbs) {
+ meter.cbs = 1;
+ } else if (meter.cbs > cbs_max) {
+ WARN_ON(1);
+ meter.cbs = cbs_max;
+ }
+
+ if (pbs > meter.cbs)
+ meter.ebs = pbs - meter.cbs;
+ }
+ }
+
+ dev_dbg(dev,
+ "slot %u ns, rate %llu, burst %llu -> unit %d, cir %u, cbs %u, ebs %u\n",
+ slot_ns, rate, burst,
+ meter.unit, meter.cir, meter.cbs, meter.ebs);
+
+ return meter;
+}
+
+static void yt921x_dsa_port_policer_del(struct dsa_switch *ds, int port)
+{
+ struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct device *dev = to_device(priv);
+ int res;
+
+ mutex_lock(&priv->reg_lock);
+ res = yt921x_reg_write(priv, YT921X_PORTn_METER(port), 0);
+ mutex_unlock(&priv->reg_lock);
+
+ if (res)
+ print_port_err(dev, port, res, "delete policer on");
+}
+
+static int
+yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port,
+ struct dsa_mall_policer_tc_entry *policer)
+{
+ struct yt921x_priv *priv = to_yt921x_priv(ds);
+ u32 ctrls[YT921X_METER_CTRL_S];
+ struct yt921x_meter meter;
+ u64 burst;
+ u64 rate;
+ u32 ctrl;
+ int res;
+
+ rate = policer->rate_bytes_per_sec;
+ burst = policer->burst;
+ meter = yt921x_meter_tfm(priv, port, priv->meter_slot_ns, rate, burst,
+ 0, YT921X_METER_RATE_MAX,
+ YT921X_METER_BURST_MAX, YT921X_METER_UNIT_MAX);
+
+ mutex_lock(&priv->reg_lock);
+ ctrl = YT921X_PORT_METER_ID(port) | YT921X_PORT_METER_EN;
+ res = yt921x_reg_write(priv, YT921X_PORTn_METER(port), ctrl);
+ if (res)
+ goto end;
+
+ ctrls[0] = 0;
+ ctrls[1] = YT921X_METER_CTRLb_CIR(meter.cir);
+ ctrls[2] = YT921X_METER_CTRLc_UNIT(meter.unit) |
+ YT921X_METER_CTRLc_DROP_R |
+ YT921X_METER_CTRLc_TOKEN_OVERFLOW_EN |
+ YT921X_METER_CTRLc_METER_EN;
+ u32a_update_u64(&ctrls[0], YT921X_METER_CTRLab_EBS_M,
+ YT921X_METER_CTRLab_EBS(meter.ebs));
+ u32a_update_u64(&ctrls[1], YT921X_METER_CTRLbc_CBS_M,
+ YT921X_METER_CTRLbc_CBS(meter.cbs));
+ res = yt921x_longreg_write(priv,
+ YT921X_METERn_CTRL(port + YT921X_METER_NUM),
+ ctrls, YT921X_METER_CTRL_S);
+end:
+ mutex_unlock(&priv->reg_lock);
+
+ return res;
+}
+
static int
yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress)
{
@@ -3040,6 +3253,7 @@ static int yt921x_chip_detect(struct yt921x_priv *priv)
u32 chipid;
u32 major;
u32 mode;
+ u32 val;
int res;
res = yt921x_reg_read(priv, YT921X_CHIP_ID, &chipid);
@@ -3074,12 +3288,27 @@ static int yt921x_chip_detect(struct yt921x_priv *priv)
return -ENODEV;
}
+ res = yt921x_reg_read(priv, YT921X_SYS_CLK, &val);
+ if (res)
+ return res;
+ switch (FIELD_GET(YT921X_SYS_CLK_SEL_M, val)) {
+ case 0:
+ priv->cycle_ns = info->major == YT9215_MAJOR ? 8 : 6;
+ break;
+ case YT921X_SYS_CLK_143M:
+ priv->cycle_ns = 7;
+ break;
+ default:
+ priv->cycle_ns = 8;
+ }
+
/* Print chipid here since we are interested in lower 16 bits */
dev_info(dev,
"Motorcomm %s ethernet switch, chipid: 0x%x, chipmode: 0x%x 0x%x\n",
info->name, chipid, mode, extmode);
priv->info = info;
+
return 0;
}
@@ -3202,6 +3431,23 @@ static int yt921x_chip_setup_dsa(struct yt921x_priv *priv)
return 0;
}
+static int yt921x_chip_setup_tc(struct yt921x_priv *priv)
+{
+ unsigned int op_ns;
+ u32 ctrl;
+ int res;
+
+ op_ns = 8 * priv->cycle_ns;
+
+ ctrl = max(priv->meter_slot_ns / op_ns, YT921X_METER_SLOT_MIN);
+ res = yt921x_reg_write(priv, YT921X_METER_SLOT, ctrl);
+ if (res)
+ return res;
+ priv->meter_slot_ns = ctrl * op_ns;
+
+ return 0;
+}
+
static int __maybe_unused yt921x_chip_setup_qos(struct yt921x_priv *priv)
{
u32 ctrl;
@@ -3248,7 +3494,7 @@ static int yt921x_chip_setup(struct yt921x_priv *priv)
u32 ctrl;
int res;
- ctrl = YT921X_FUNC_MIB;
+ ctrl = YT921X_FUNC_MIB | YT921X_FUNC_METER;
res = yt921x_reg_set_bits(priv, YT921X_FUNC, ctrl);
if (res)
return res;
@@ -3257,6 +3503,10 @@ static int yt921x_chip_setup(struct yt921x_priv *priv)
if (res)
return res;
+ res = yt921x_chip_setup_tc(priv);
+ if (res)
+ return res;
+
#if IS_ENABLED(CONFIG_DCB)
res = yt921x_chip_setup_qos(priv);
if (res)
@@ -3348,6 +3598,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,
+ /* rate */
+ .port_policer_del = yt921x_dsa_port_policer_del,
+ .port_policer_add = yt921x_dsa_port_policer_add,
/* hsr */
.port_hsr_leave = dsa_port_simple_hsr_leave,
.port_hsr_join = dsa_port_simple_hsr_join,
diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
index 361470582687..129073ed3a4b 100644
--- a/drivers/net/dsa/yt921x.h
+++ b/drivers/net/dsa/yt921x.h
@@ -23,6 +23,7 @@
#define YT921X_RST_HW BIT(31)
#define YT921X_RST_SW BIT(1)
#define YT921X_FUNC 0x80004
+#define YT921X_FUNC_METER BIT(4)
#define YT921X_FUNC_MIB BIT(1)
#define YT921X_CHIP_ID 0x80008
#define YT921X_CHIP_ID_MAJOR GENMASK(31, 16)
@@ -239,6 +240,11 @@
#define YT921X_EDATA_DATA_STATUS_M GENMASK(3, 0)
#define YT921X_EDATA_DATA_STATUS(x) FIELD_PREP(YT921X_EDATA_DATA_STATUS_M, (x))
#define YT921X_EDATA_DATA_IDLE YT921X_EDATA_DATA_STATUS(3)
+#define YT921X_SYS_CLK 0xe0040
+#define YT921X_SYS_CLK_SEL_M GENMASK(1, 0) /* unknown: 167M */
+#define YT9215_SYS_CLK_125M 0
+#define YT9218_SYS_CLK_167M 0
+#define YT921X_SYS_CLK_143M 1
#define YT921X_EXT_MBUS_OP 0x6a000
#define YT921X_INT_MBUS_OP 0xf0000
@@ -466,6 +472,44 @@ enum yt921x_app_selector {
#define YT921X_LAG_HASH_MAC_DA BIT(1)
#define YT921X_LAG_HASH_SRC_PORT BIT(0)
+#define YT921X_PORTn_RATE(port) (0x220000 + 4 * (port))
+#define YT921X_PORT_RATE_GAP_VALUE GENMASK(4, 0) /* default 20 */
+#define YT921X_METER_SLOT 0x220104
+#define YT921X_METER_SLOT_SLOT_M GENMASK(11, 0)
+#define YT921X_PORTn_METER(port) (0x220108 + 4 * (port))
+#define YT921X_PORT_METER_EN BIT(4)
+#define YT921X_PORT_METER_ID_M GENMASK(3, 0)
+#define YT921X_PORT_METER_ID(x) FIELD_PREP(YT921X_PORT_METER_ID_M, (x))
+#define YT921X_METERn_CTRL(x) (0x220800 + 0x10 * (x))
+#define YT921X_METER_CTRL_S 3
+#define YT921X_METER_CTRLc_METER_EN BIT(14)
+#define YT921X_METER_CTRLc_TOKEN_OVERFLOW_EN BIT(13) /* RFC4115: yellow use unused green bw */
+#define YT921X_METER_CTRLc_DROP_M GENMASK(12, 11)
+#define YT921X_METER_CTRLc_DROP(x) FIELD_PREP(YT921X_METER_CTRLc_DROP_M, (x))
+#define YT921X_METER_CTRLc_DROP_GYR YT921X_METER_CTRLc_DROP(0)
+#define YT921X_METER_CTRLc_DROP_YR YT921X_METER_CTRLc_DROP(1)
+#define YT921X_METER_CTRLc_DROP_R YT921X_METER_CTRLc_DROP(2)
+#define YT921X_METER_CTRLc_DROP_NONE YT921X_METER_CTRLc_DROP(3)
+#define YT921X_METER_CTRLc_COLOR_BLIND BIT(10)
+#define YT921X_METER_CTRLc_UNIT_M GENMASK(9, 7)
+#define YT921X_METER_CTRLc_UNIT(x) FIELD_PREP(YT921X_METER_CTRLc_UNIT_M, (x))
+#define YT921X_METER_CTRLc_BYTE_MODE_INCLUDE_GAP BIT(6) /* +GAP_VALUE bytes each packet */
+#define YT921X_METER_CTRLc_PKT_MODE BIT(5) /* 0: byte rate mode */
+#define YT921X_METER_CTRLc_RFC2698 BIT(4) /* 0: RFC4115 */
+#define YT921X_METER_CTRLbc_CBS_M GENMASK_ULL(35, 20)
+#define YT921X_METER_CTRLbc_CBS(x) FIELD_PREP(YT921X_METER_CTRLbc_CBS_M, (x))
+#define YT921X_METER_CTRLb_CIR_M GENMASK(19, 2)
+#define YT921X_METER_CTRLb_CIR(x) FIELD_PREP(YT921X_METER_CTRLb_CIR_M, (x))
+#define YT921X_METER_CTRLab_EBS_M GENMASK_ULL(33, 18)
+#define YT921X_METER_CTRLab_EBS(x) FIELD_PREP(YT921X_METER_CTRLab_EBS_M, (x))
+#define YT921X_METER_CTRLa_EIR_M GENMASK(17, 0)
+#define YT921X_METER_CTRLa_EIR(x) FIELD_PREP(YT921X_METER_CTRLa_EIR_M, (x))
+
+#define YT921X_METERn_STAT_EXCESS(x) (0x221000 + 8 * (x))
+#define YT921X_METERn_STAT_COMMITTED(x) (0x221004 + 8 * (x))
+#define YT921X_METER_STAT_TOKEN_M GENMASK(30, 15)
+#define YT921X_METER_STAT_QUEUE_M GENMASK(14, 0)
+
#define YT921X_PORTn_VLAN_CTRL(port) (0x230010 + 4 * (port))
#define YT921X_PORT_VLAN_CTRL_SVLAN_PRIO_EN BIT(31)
#define YT921X_PORT_VLAN_CTRL_CVLAN_PRIO_EN BIT(30)
@@ -509,6 +553,16 @@ enum yt921x_fdb_entry_status {
#define YT921X_MSTI_NUM 16
+#define YT921X_TOKEN_BYTE_C 1 /* 1 token = 2^1 byte */
+#define YT921X_TOKEN_PKT_C -6 /* 1 token = 2^-6 packets */
+#define YT921X_TOKEN_RATE_C -15
+/* for VLAN only, not including port meters */
+#define YT921X_METER_NUM 64
+#define YT921X_METER_SLOT_MIN 80
+#define YT921X_METER_UNIT_MAX ((1 << 3) - 1)
+#define YT921X_METER_BURST_MAX ((1 << 16) - 1)
+#define YT921X_METER_RATE_MAX ((1 << 18) - 1)
+
#define YT921X_LAG_NUM 2
#define YT921X_LAG_PORT_NUM 4
@@ -603,8 +657,10 @@ struct yt921x_priv {
struct dsa_switch ds;
const struct yt921x_info *info;
+ unsigned int meter_slot_ns;
/* cache of dsa_cpu_ports(ds) */
u16 cpu_ports_mask;
+ u8 cycle_ns;
/* protect the access to the switch registers */
struct mutex reg_lock;
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [RFC net-next 4/4] net: dsa: yt921x: Add port qdisc tbf support
2026-01-29 8:51 [RFC net-next 0/4] net: dsa: yt921x: Add tc support David Yang
` (2 preceding siblings ...)
2026-01-29 8:51 ` [RFC net-next 3/4] net: dsa: yt921x: Add port police support David Yang
@ 2026-01-29 8:51 ` David Yang
3 siblings, 0 replies; 5+ messages in thread
From: David Yang @ 2026-01-29 8:51 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
Enable port shaping and support limiting the rate of outgoing traffic.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/dsa/yt921x.c | 113 +++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/yt921x.h | 18 +++++++
2 files changed, 131 insertions(+)
diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c
index f1465c4d9b1b..dd279f1db837 100644
--- a/drivers/net/dsa/yt921x.c
+++ b/drivers/net/dsa/yt921x.c
@@ -24,6 +24,7 @@
#include <net/dsa.h>
#include <net/dscp.h>
#include <net/ieee8021q.h>
+#include <net/pkt_cls.h>
#include "yt921x.h"
@@ -1291,6 +1292,110 @@ yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port,
return res;
}
+static int
+yt921x_tbf_validate(struct yt921x_priv *priv,
+ const struct tc_tbf_qopt_offload *qopt, int *queuep)
+{
+ struct device *dev = to_device(priv);
+ int queue = -1;
+
+ if (qopt->parent != TC_H_ROOT) {
+ dev_err(dev, "Parent should be \"root\"\n");
+ return -EOPNOTSUPP;
+ }
+
+ switch (qopt->command) {
+ case TC_TBF_REPLACE: {
+ const struct tc_tbf_qopt_offload_replace_params *p;
+
+ p = &qopt->replace_params;
+
+ if (!p->rate.mpu) {
+ dev_info(dev, "Assuming you want mpu = 64\n");
+ } else if (p->rate.mpu != 64) {
+ dev_err(dev, "mpu other than 64 not supported\n");
+ return -EINVAL;
+ }
+ }
+ default:
+ break;
+ }
+
+ *queuep = queue;
+ return 0;
+}
+
+static int
+yt921x_dsa_port_setup_tc_tbf_port(struct dsa_switch *ds, int port,
+ const struct tc_tbf_qopt_offload *qopt)
+{
+ struct yt921x_priv *priv = to_yt921x_priv(ds);
+ u32 ctrls[YT921X_PORT_SHAPE_CTRL_S];
+ int res;
+
+ switch (qopt->command) {
+ case TC_TBF_DESTROY:
+ ctrls[0] = 0;
+ ctrls[1] = 0;
+ break;
+ case TC_TBF_REPLACE: {
+ const struct tc_tbf_qopt_offload_replace_params *p;
+ struct yt921x_meter meter;
+ u64 burst;
+
+ p = &qopt->replace_params;
+
+ /* where is burst??? */
+ burst = priv->port_shape_slot_ns * p->rate.rate_bytes_ps /
+ 1000000000 + 10000;
+ meter = yt921x_meter_tfm(priv, port, priv->port_shape_slot_ns,
+ p->rate.rate_bytes_ps, burst,
+ YT921X_METER_SINGLE_BUCKET,
+ YT921X_SHAPE_RATE_MAX,
+ YT921X_SHAPE_BURST_MAX,
+ YT921X_SHAPE_UNIT_MAX);
+
+ ctrls[0] = YT921X_PORT_SHAPE_CTRLa_CIR(meter.cir) |
+ YT921X_PORT_SHAPE_CTRLa_CBS(meter.cbs);
+ ctrls[1] = YT921X_PORT_SHAPE_CTRLb_UNIT(meter.unit) |
+ YT921X_PORT_SHAPE_CTRLb_EN;
+ break;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ mutex_lock(&priv->reg_lock);
+ res = yt921x_longreg_write(priv, YT921X_PORTn_SHAPE_CTRL(port),
+ ctrls, YT921X_PORT_SHAPE_CTRL_S);
+ mutex_unlock(&priv->reg_lock);
+
+ return res;
+}
+
+static int
+yt921x_dsa_port_setup_tc(struct dsa_switch *ds, int port,
+ enum tc_setup_type type, void *type_data)
+{
+ struct yt921x_priv *priv = to_yt921x_priv(ds);
+ int res;
+
+ switch (type) {
+ case TC_SETUP_QDISC_TBF: {
+ const struct tc_tbf_qopt_offload *qopt = type_data;
+ int queue;
+
+ res = yt921x_tbf_validate(priv, qopt, &queue);
+ if (res)
+ return res;
+
+ return yt921x_dsa_port_setup_tc_tbf_port(ds, port, qopt);
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int
yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress)
{
@@ -3445,6 +3550,13 @@ static int yt921x_chip_setup_tc(struct yt921x_priv *priv)
return res;
priv->meter_slot_ns = ctrl * op_ns;
+ ctrl = max(priv->port_shape_slot_ns / op_ns,
+ YT921X_PORT_SHAPE_SLOT_MIN);
+ res = yt921x_reg_write(priv, YT921X_PORT_SHAPE_SLOT, ctrl);
+ if (res)
+ return res;
+ priv->port_shape_slot_ns = ctrl * op_ns;
+
return 0;
}
@@ -3601,6 +3713,7 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = {
/* rate */
.port_policer_del = yt921x_dsa_port_policer_del,
.port_policer_add = yt921x_dsa_port_policer_add,
+ .port_setup_tc = yt921x_dsa_port_setup_tc,
/* hsr */
.port_hsr_leave = dsa_port_simple_hsr_leave,
.port_hsr_join = dsa_port_simple_hsr_join,
diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h
index 129073ed3a4b..dbcd89c7bd6c 100644
--- a/drivers/net/dsa/yt921x.h
+++ b/drivers/net/dsa/yt921x.h
@@ -537,6 +537,19 @@ enum yt921x_app_selector {
#define YT921X_MIRROR_PORT_M GENMASK(3, 0)
#define YT921X_MIRROR_PORT(x) FIELD_PREP(YT921X_MIRROR_PORT_M, (x))
+#define YT921X_PORT_SHAPE_SLOT 0x34000c
+#define YT921X_PORT_SHAPE_SLOT_SLOT_M GENMASK(11, 0)
+#define YT921X_PORTn_SHAPE_CTRL(port) (0x354000 + 8 * (port))
+#define YT921X_PORT_SHAPE_CTRL_S 2
+#define YT921X_PORT_SHAPE_CTRLb_EN BIT(4)
+#define YT921X_PORT_SHAPE_CTRLb_PKT_MODE BIT(3) /* 0: byte rate mode */
+#define YT921X_PORT_SHAPE_CTRLb_UNIT_M GENMASK(2, 0)
+#define YT921X_PORT_SHAPE_CTRLb_UNIT(x) FIELD_PREP(YT921X_PORT_SHAPE_CTRLb_UNIT_M, (x))
+#define YT921X_PORT_SHAPE_CTRLa_CBS_M GENMASK(31, 18)
+#define YT921X_PORT_SHAPE_CTRLa_CBS(x) FIELD_PREP(YT921X_PORT_SHAPE_CTRLa_CBS_M, (x))
+#define YT921X_PORT_SHAPE_CTRLa_CIR_M GENMASK(17, 0)
+#define YT921X_PORT_SHAPE_CTRLa_CIR(x) FIELD_PREP(YT921X_PORT_SHAPE_CTRLa_CIR_M, (x))
+
#define YT921X_EDATA_EXTMODE 0xfb
#define YT921X_EDATA_LEN 0x100
@@ -562,6 +575,10 @@ enum yt921x_fdb_entry_status {
#define YT921X_METER_UNIT_MAX ((1 << 3) - 1)
#define YT921X_METER_BURST_MAX ((1 << 16) - 1)
#define YT921X_METER_RATE_MAX ((1 << 18) - 1)
+#define YT921X_PORT_SHAPE_SLOT_MIN 80
+#define YT921X_SHAPE_UNIT_MAX ((1 << 3) - 1)
+#define YT921X_SHAPE_BURST_MAX ((1 << 14) - 1)
+#define YT921X_SHAPE_RATE_MAX ((1 << 18) - 1)
#define YT921X_LAG_NUM 2
#define YT921X_LAG_PORT_NUM 4
@@ -658,6 +675,7 @@ struct yt921x_priv {
const struct yt921x_info *info;
unsigned int meter_slot_ns;
+ unsigned int port_shape_slot_ns;
/* cache of dsa_cpu_ports(ds) */
u16 cpu_ports_mask;
u8 cycle_ns;
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread