Message ID | 20241031-mt7530-tc-offload-v2-1-cb242ad954a0@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [net-next,v2] net: dsa: mt7530: Add TBF qdisc offload support | expand |
This is a very nice addition, thanks for working on this! Arınç On 31/10/2024 17:28, Lorenzo Bianconi wrote: > Introduce port_setup_tc callback in mt7530 dsa driver in order to enable > dsa ports rate shaping via hw Token Bucket Filter (TBF) for hw switched > traffic. > > Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > --- > Changes in v2: > - remove device id limitation and allow tbf qdisc configuration on each mt7530 > compliant devices > - rename MT7530_ERLCR_P in MT753X_ERLCR_P and MT7530_GERLCR in > MT753X_GERLCR > - Link to v1: https://lore.kernel.org/r/20241030-mt7530-tc-offload-v1-1-f7eeffaf3d9e@kernel.org > --- > drivers/net/dsa/mt7530.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ > drivers/net/dsa/mt7530.h | 12 ++++++++++++ > 2 files changed, 61 insertions(+) > > diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c > index d84ee1b419a614dda5f440e6571cff5f4f27bf21..086b8b3d5b40f776815967492914bd46a04b6886 100644 > --- a/drivers/net/dsa/mt7530.c > +++ b/drivers/net/dsa/mt7530.c > @@ -21,6 +21,7 @@ > #include <linux/gpio/consumer.h> > #include <linux/gpio/driver.h> > #include <net/dsa.h> > +#include <net/pkt_cls.h> > > #include "mt7530.h" > > @@ -3146,6 +3147,53 @@ mt753x_conduit_state_change(struct dsa_switch *ds, > mt7530_rmw(priv, MT753X_MFC, MT7530_CPU_EN | MT7530_CPU_PORT_MASK, val); > } > > +static int mt753x_tc_setup_qdisc_tbf(struct dsa_switch *ds, int port, > + struct tc_tbf_qopt_offload *qopt) > +{ > + struct tc_tbf_qopt_offload_replace_params *p = &qopt->replace_params; > + struct mt7530_priv *priv = ds->priv; > + u32 rate = 0; > + > + switch (qopt->command) { > + case TC_TBF_REPLACE: > + rate = div_u64(p->rate.rate_bytes_ps, 1000) << 3; /* kbps */ > + fallthrough; > + case TC_TBF_DESTROY: { > + u32 val, tick; > + > + mt7530_rmw(priv, MT753X_GERLCR, EGR_BC_MASK, > + EGR_BC_CRC_IPG_PREAMBLE); > + > + /* if rate is greater than 10Mbps tick is 1/32 ms, > + * 1ms otherwise > + */ > + tick = rate > 10000 ? 2 : 7; > + val = FIELD_PREP(ERLCR_CIR_MASK, (rate >> 5)) | > + FIELD_PREP(ERLCR_EN_MASK, !!rate) | > + FIELD_PREP(ERLCR_EXP_MASK, tick) | > + ERLCR_TBF_MODE_MASK | > + FIELD_PREP(ERLCR_MANT_MASK, 0xf); > + mt7530_write(priv, MT753X_ERLCR_P(port), val); > + break; > + } > + default: > + return -EOPNOTSUPP; > + } > + > + return 0; > +} > + > +static int mt753x_setup_tc(struct dsa_switch *ds, int port, > + enum tc_setup_type type, void *type_data) > +{ > + switch (type) { > + case TC_SETUP_QDISC_TBF: > + return mt753x_tc_setup_qdisc_tbf(ds, port, type_data); > + default: > + return -EOPNOTSUPP; > + } > +} > + > static int mt7988_setup(struct dsa_switch *ds) > { > struct mt7530_priv *priv = ds->priv; > @@ -3193,6 +3241,7 @@ const struct dsa_switch_ops mt7530_switch_ops = { > .get_mac_eee = mt753x_get_mac_eee, > .set_mac_eee = mt753x_set_mac_eee, > .conduit_state_change = mt753x_conduit_state_change, > + .port_setup_tc = mt753x_setup_tc, > }; > EXPORT_SYMBOL_GPL(mt7530_switch_ops); > > diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h > index 6ad33a9f6b1dff3a423baa668a8a2ca158f72b91..448200689f492dcb73ef056d7284090c1c662e67 100644 > --- a/drivers/net/dsa/mt7530.h > +++ b/drivers/net/dsa/mt7530.h > @@ -248,6 +248,18 @@ enum mt7530_vlan_egress_attr { > #define AGE_UNIT_MAX 0xfff > #define AGE_UNIT(x) (AGE_UNIT_MASK & (x)) > > +#define MT753X_ERLCR_P(x) (0x1040 + ((x) * 0x100)) > +#define ERLCR_CIR_MASK GENMASK(31, 16) > +#define ERLCR_EN_MASK BIT(15) > +#define ERLCR_EXP_MASK GENMASK(11, 8) > +#define ERLCR_TBF_MODE_MASK BIT(7) > +#define ERLCR_MANT_MASK GENMASK(6, 0) > + > +#define MT753X_GERLCR 0x10e0 > +#define EGR_BC_MASK GENMASK(7, 0) > +#define EGR_BC_CRC 0x4 /* crc */ > +#define EGR_BC_CRC_IPG_PREAMBLE 0x18 /* crc + ipg + preamble */ > + > /* Register for port STP state control */ > #define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) > #define FID_PST(fid, state) (((state) & 0x3) << ((fid) * 2)) > > --- > base-commit: 157a4881225bd0af5444aab9510e7b6da28f2469 > change-id: 20241030-mt7530-tc-offload-05e204441500 > > Best regards,
On Thu, Oct 31, 2024 at 03:28:18PM +0100, Lorenzo Bianconi wrote: > Introduce port_setup_tc callback in mt7530 dsa driver in order to enable > dsa ports rate shaping via hw Token Bucket Filter (TBF) for hw switched > traffic. > > Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Andrew
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index d84ee1b419a614dda5f440e6571cff5f4f27bf21..086b8b3d5b40f776815967492914bd46a04b6886 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -21,6 +21,7 @@ #include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> #include <net/dsa.h> +#include <net/pkt_cls.h> #include "mt7530.h" @@ -3146,6 +3147,53 @@ mt753x_conduit_state_change(struct dsa_switch *ds, mt7530_rmw(priv, MT753X_MFC, MT7530_CPU_EN | MT7530_CPU_PORT_MASK, val); } +static int mt753x_tc_setup_qdisc_tbf(struct dsa_switch *ds, int port, + struct tc_tbf_qopt_offload *qopt) +{ + struct tc_tbf_qopt_offload_replace_params *p = &qopt->replace_params; + struct mt7530_priv *priv = ds->priv; + u32 rate = 0; + + switch (qopt->command) { + case TC_TBF_REPLACE: + rate = div_u64(p->rate.rate_bytes_ps, 1000) << 3; /* kbps */ + fallthrough; + case TC_TBF_DESTROY: { + u32 val, tick; + + mt7530_rmw(priv, MT753X_GERLCR, EGR_BC_MASK, + EGR_BC_CRC_IPG_PREAMBLE); + + /* if rate is greater than 10Mbps tick is 1/32 ms, + * 1ms otherwise + */ + tick = rate > 10000 ? 2 : 7; + val = FIELD_PREP(ERLCR_CIR_MASK, (rate >> 5)) | + FIELD_PREP(ERLCR_EN_MASK, !!rate) | + FIELD_PREP(ERLCR_EXP_MASK, tick) | + ERLCR_TBF_MODE_MASK | + FIELD_PREP(ERLCR_MANT_MASK, 0xf); + mt7530_write(priv, MT753X_ERLCR_P(port), val); + break; + } + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int mt753x_setup_tc(struct dsa_switch *ds, int port, + enum tc_setup_type type, void *type_data) +{ + switch (type) { + case TC_SETUP_QDISC_TBF: + return mt753x_tc_setup_qdisc_tbf(ds, port, type_data); + default: + return -EOPNOTSUPP; + } +} + static int mt7988_setup(struct dsa_switch *ds) { struct mt7530_priv *priv = ds->priv; @@ -3193,6 +3241,7 @@ const struct dsa_switch_ops mt7530_switch_ops = { .get_mac_eee = mt753x_get_mac_eee, .set_mac_eee = mt753x_set_mac_eee, .conduit_state_change = mt753x_conduit_state_change, + .port_setup_tc = mt753x_setup_tc, }; EXPORT_SYMBOL_GPL(mt7530_switch_ops); diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index 6ad33a9f6b1dff3a423baa668a8a2ca158f72b91..448200689f492dcb73ef056d7284090c1c662e67 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -248,6 +248,18 @@ enum mt7530_vlan_egress_attr { #define AGE_UNIT_MAX 0xfff #define AGE_UNIT(x) (AGE_UNIT_MASK & (x)) +#define MT753X_ERLCR_P(x) (0x1040 + ((x) * 0x100)) +#define ERLCR_CIR_MASK GENMASK(31, 16) +#define ERLCR_EN_MASK BIT(15) +#define ERLCR_EXP_MASK GENMASK(11, 8) +#define ERLCR_TBF_MODE_MASK BIT(7) +#define ERLCR_MANT_MASK GENMASK(6, 0) + +#define MT753X_GERLCR 0x10e0 +#define EGR_BC_MASK GENMASK(7, 0) +#define EGR_BC_CRC 0x4 /* crc */ +#define EGR_BC_CRC_IPG_PREAMBLE 0x18 /* crc + ipg + preamble */ + /* Register for port STP state control */ #define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) #define FID_PST(fid, state) (((state) & 0x3) << ((fid) * 2))