net: dsa: qca8k: add priority tweak to qca8337 switch
authorAnsuel Smith <ansuelsmth@gmail.com>
Fri, 14 May 2021 21:00:01 +0000 (23:00 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 14 May 2021 22:30:22 +0000 (15:30 -0700)
The port 5 of the qca8337 have some problem in flood condition. The
original legacy driver had some specific buffer and priority settings
for the different port suggested by the QCA switch team. Add this
missing settings to improve switch stability under load condition.
The packet priority tweak is only needed for the qca8337 switch and
other qca8k switch are not affected.

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/qca8k.c
drivers/net/dsa/qca8k.h

index 693bd9fd532b74711b8a4dc58e1e848c3e037537..65f27d136aefa1411db9f3ae050d36dc4172bd15 100644 (file)
@@ -779,6 +779,7 @@ qca8k_setup(struct dsa_switch *ds)
 {
        struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
        int ret, i;
+       u32 mask;
 
        /* Make sure that port 0 is the cpu port */
        if (!dsa_is_cpu_port(ds, 0)) {
@@ -884,6 +885,51 @@ qca8k_setup(struct dsa_switch *ds)
                }
        }
 
+       /* The port 5 of the qca8337 have some problem in flood condition. The
+        * original legacy driver had some specific buffer and priority settings
+        * for the different port suggested by the QCA switch team. Add this
+        * missing settings to improve switch stability under load condition.
+        * This problem is limited to qca8337 and other qca8k switch are not affected.
+        */
+       if (priv->switch_id == QCA8K_ID_QCA8337) {
+               for (i = 0; i < QCA8K_NUM_PORTS; i++) {
+                       switch (i) {
+                       /* The 2 CPU port and port 5 requires some different
+                        * priority than any other ports.
+                        */
+                       case 0:
+                       case 5:
+                       case 6:
+                               mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e);
+                               break;
+                       default:
+                               mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) |
+                                       QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19);
+                       }
+                       qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask);
+
+                       mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) |
+                       QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN |
+                       QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN |
+                       QCA8K_PORT_HOL_CTRL1_WRED_EN;
+                       qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i),
+                                 QCA8K_PORT_HOL_CTRL1_ING_BUF |
+                                 QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN |
+                                 QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN |
+                                 QCA8K_PORT_HOL_CTRL1_WRED_EN,
+                                 mask);
+               }
+       }
+
        /* Setup our port MTUs to match power on defaults */
        for (i = 0; i < QCA8K_NUM_PORTS; i++)
                priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
@@ -1569,6 +1615,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
                return -ENODEV;
        }
 
+       priv->switch_id = id;
        priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
        if (!priv->ds)
                return -ENOMEM;
index 87a8b10459c65552301751ccd6ea2aed44d6b73c..42d90836dffaa0879998d3de1fac8aa35cb2adda 100644 (file)
 #define   QCA8K_PORT_LOOKUP_STATE                      GENMASK(18, 16)
 #define   QCA8K_PORT_LOOKUP_LEARN                      BIT(20)
 
+#define QCA8K_REG_PORT_HOL_CTRL0(_i)                   (0x970 + (_i) * 0x8)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF             GENMASK(3, 0)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI0(x)              ((x) << 0)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF             GENMASK(7, 4)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI1(x)              ((x) << 4)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF             GENMASK(11, 8)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI2(x)              ((x) << 8)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF             GENMASK(15, 12)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI3(x)              ((x) << 12)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF             GENMASK(19, 16)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI4(x)              ((x) << 16)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF             GENMASK(23, 20)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PRI5(x)              ((x) << 20)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF             GENMASK(29, 24)
+#define   QCA8K_PORT_HOL_CTRL0_EG_PORT(x)              ((x) << 24)
+
+#define QCA8K_REG_PORT_HOL_CTRL1(_i)                   (0x974 + (_i) * 0x8)
+#define   QCA8K_PORT_HOL_CTRL1_ING_BUF                 GENMASK(3, 0)
+#define   QCA8K_PORT_HOL_CTRL1_ING(x)                  ((x) << 0)
+#define   QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN           BIT(6)
+#define   QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN          BIT(7)
+#define   QCA8K_PORT_HOL_CTRL1_WRED_EN                 BIT(8)
+#define   QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN            BIT(16)
+
 /* Pkt edit registers */
 #define QCA8K_EGRESS_VLAN(x)                           (0x0c70 + (4 * (x / 2)))
 
@@ -220,6 +244,7 @@ struct qca8k_match_data {
 };
 
 struct qca8k_priv {
+       u8 switch_id;
        struct regmap *regmap;
        struct mii_bus *bus;
        struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];