diff options
-rw-r--r-- | drivers/net/dsa/qca8k.c | 47 | ||||
-rw-r--r-- | drivers/net/dsa/qca8k.h | 25 |
2 files changed, 72 insertions, 0 deletions
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index 693bd9fd532b..65f27d136aef 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -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; diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h index 87a8b10459c6..42d90836dffa 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -168,6 +168,30 @@ #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]; |