]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
net: dsa: mt7530: Add TBF qdisc offload support
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 31 Oct 2024 14:28:18 +0000 (15:28 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sun, 3 Nov 2024 20:53:42 +0000 (12:53 -0800)
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>
Link: https://patch.msgid.link/20241031-mt7530-tc-offload-v2-1-cb242ad954a0@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/dsa/mt7530.c
drivers/net/dsa/mt7530.h

index d84ee1b419a614dda5f440e6571cff5f4f27bf21..086b8b3d5b40f776815967492914bd46a04b6886 100644 (file)
@@ -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);
 
index 6ad33a9f6b1dff3a423baa668a8a2ca158f72b91..448200689f492dcb73ef056d7284090c1c662e67 100644 (file)
@@ -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))