[openwrt/openwrt] generic: 5.15: backport mirror mode and LAG feature for qca8k

LEDE Commits lede-commits at lists.infradead.org
Sat Mar 26 21:19:48 PDT 2022


dangole pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/ec818e5d291169784f183680c2b4013174324b68

commit ec818e5d291169784f183680c2b4013174324b68
Author: Ansuel Smith <ansuelsmth at gmail.com>
AuthorDate: Sun Dec 19 03:37:53 2021 +0100

    generic: 5.15: backport mirror mode and LAG feature for qca8k
    
    Backport LAG and mirror mode feature for qca8k.
    
    Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
---
 ...net-dsa-qca8k-add-support-for-mirror-mode.patch | 162 +++++++++++
 ...63-net-next-net-dsa-qca8k-add-LAG-support.patch | 295 +++++++++++++++++++++
 ...-net-dsa-qca8k-fix-warning-in-LAG-feature.patch |  45 ++++
 3 files changed, 502 insertions(+)

diff --git a/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch b/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch
new file mode 100644
index 0000000000..4ebdfda651
--- /dev/null
+++ b/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch
@@ -0,0 +1,162 @@
+From 2c1bdbc7e7560d7de754cad277d968d56bb1899e Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Tue, 23 Nov 2021 03:59:10 +0100
+Subject: net: dsa: qca8k: add support for mirror mode
+
+The switch supports mirror mode. Only one port can set as mirror port and
+every other port can set to both ingress and egress mode. The mirror
+port is disabled and reverted to normal operation once every port is
+removed from sending packet to it.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/qca8k.h |  4 +++
+ 2 files changed, 99 insertions(+)
+
+diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
+index 67742fbd80409..bd9d756f40011 100644
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -2022,6 +2022,99 @@ qca8k_port_mdb_del(struct dsa_switch *ds, int port,
+ 	return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
+ }
+ 
++static int
++qca8k_port_mirror_add(struct dsa_switch *ds, int port,
++		      struct dsa_mall_mirror_tc_entry *mirror,
++		      bool ingress)
++{
++	struct qca8k_priv *priv = ds->priv;
++	int monitor_port, ret;
++	u32 reg, val;
++
++	/* Check for existent entry */
++	if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
++		return -EEXIST;
++
++	ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val);
++	if (ret)
++		return ret;
++
++	/* QCA83xx can have only one port set to mirror mode.
++	 * Check that the correct port is requested and return error otherwise.
++	 * When no mirror port is set, the values is set to 0xF
++	 */
++	monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
++	if (monitor_port != 0xF && monitor_port != mirror->to_local_port)
++		return -EEXIST;
++
++	/* Set the monitor port */
++	val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM,
++			 mirror->to_local_port);
++	ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
++				 QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
++	if (ret)
++		return ret;
++
++	if (ingress) {
++		reg = QCA8K_PORT_LOOKUP_CTRL(port);
++		val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
++	} else {
++		reg = QCA8K_REG_PORT_HOL_CTRL1(port);
++		val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
++	}
++
++	ret = regmap_update_bits(priv->regmap, reg, val, val);
++	if (ret)
++		return ret;
++
++	/* Track mirror port for tx and rx to decide when the
++	 * mirror port has to be disabled.
++	 */
++	if (ingress)
++		priv->mirror_rx |= BIT(port);
++	else
++		priv->mirror_tx |= BIT(port);
++
++	return 0;
++}
++
++static void
++qca8k_port_mirror_del(struct dsa_switch *ds, int port,
++		      struct dsa_mall_mirror_tc_entry *mirror)
++{
++	struct qca8k_priv *priv = ds->priv;
++	u32 reg, val;
++	int ret;
++
++	if (mirror->ingress) {
++		reg = QCA8K_PORT_LOOKUP_CTRL(port);
++		val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
++	} else {
++		reg = QCA8K_REG_PORT_HOL_CTRL1(port);
++		val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
++	}
++
++	ret = regmap_clear_bits(priv->regmap, reg, val);
++	if (ret)
++		goto err;
++
++	if (mirror->ingress)
++		priv->mirror_rx &= ~BIT(port);
++	else
++		priv->mirror_tx &= ~BIT(port);
++
++	/* No port set to send packet to mirror port. Disable mirror port */
++	if (!priv->mirror_rx && !priv->mirror_tx) {
++		val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF);
++		ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
++					 QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
++		if (ret)
++			goto err;
++	}
++err:
++	dev_err(priv->dev, "Failed to del mirror port from %d", port);
++}
++
+ static int
+ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+ 			  struct netlink_ext_ack *extack)
+@@ -2132,6 +2225,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
+ 	.port_fdb_dump		= qca8k_port_fdb_dump,
+ 	.port_mdb_add		= qca8k_port_mdb_add,
+ 	.port_mdb_del		= qca8k_port_mdb_del,
++	.port_mirror_add	= qca8k_port_mirror_add,
++	.port_mirror_del	= qca8k_port_mirror_del,
+ 	.port_vlan_filtering	= qca8k_port_vlan_filtering,
+ 	.port_vlan_add		= qca8k_port_vlan_add,
+ 	.port_vlan_del		= qca8k_port_vlan_del,
+diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
+index 40ec8012622f7..7c87a968c0104 100644
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -180,6 +180,7 @@
+ #define   QCA8K_ATU_AGE_TIME(x)				FIELD_PREP(QCA8K_ATU_AGE_TIME_MASK, (x))
+ #define QCA8K_REG_GLOBAL_FW_CTRL0			0x620
+ #define   QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN		BIT(10)
++#define   QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM		GENMASK(7, 4)
+ #define QCA8K_REG_GLOBAL_FW_CTRL1			0x624
+ #define   QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK		GENMASK(30, 24)
+ #define   QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK		GENMASK(22, 16)
+@@ -201,6 +202,7 @@
+ #define   QCA8K_PORT_LOOKUP_STATE_LEARNING		QCA8K_PORT_LOOKUP_STATE(0x3)
+ #define   QCA8K_PORT_LOOKUP_STATE_FORWARD		QCA8K_PORT_LOOKUP_STATE(0x4)
+ #define   QCA8K_PORT_LOOKUP_LEARN			BIT(20)
++#define   QCA8K_PORT_LOOKUP_ING_MIRROR_EN		BIT(25)
+ 
+ #define QCA8K_REG_GLOBAL_FC_THRESH			0x800
+ #define   QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK		GENMASK(24, 16)
+@@ -305,6 +307,8 @@ struct qca8k_ports_config {
+ struct qca8k_priv {
+ 	u8 switch_id;
+ 	u8 switch_revision;
++	u8 mirror_rx;
++	u8 mirror_tx;
+ 	bool legacy_phy_port_mapping;
+ 	struct qca8k_ports_config ports_config;
+ 	struct regmap *regmap;
+-- 
+cgit 1.2.3-1.el7
+
diff --git a/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch b/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch
new file mode 100644
index 0000000000..9967211828
--- /dev/null
+++ b/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch
@@ -0,0 +1,295 @@
+From def975307c01191b6f0170048c3724b0ed3348af Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Tue, 23 Nov 2021 03:59:11 +0100
+Subject: net: dsa: qca8k: add LAG support
+
+Add LAG support to this switch. In Documentation this is described as
+trunk mode. A max of 4 LAGs are supported and each can support up to 4
+port. The current tx mode supported is Hash mode with both L2 and L2+3
+mode.
+When no port are present in the trunk, the trunk is disabled in the
+switch.
+When a port is disconnected, the traffic is redirected to the other
+available port.
+The hash mode is global and each LAG require to have the same hash mode
+set. To change the hash mode when multiple LAG are configured, it's
+required to remove each LAG and set the desired hash mode to the last.
+An error is printed when it's asked to set a not supported hadh mode.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/qca8k.h |  33 +++++++++
+ 2 files changed, 210 insertions(+)
+
+diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
+index bd9d756f40011..6516df08a5d5f 100644
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -1336,6 +1336,9 @@ qca8k_setup(struct dsa_switch *ds)
+ 	ds->ageing_time_min = 7000;
+ 	ds->ageing_time_max = 458745000;
+ 
++	/* Set max number of LAGs supported */
++	ds->num_lag_ids = QCA8K_NUM_LAGS;
++
+ 	return 0;
+ }
+ 
+@@ -2203,6 +2206,178 @@ qca8k_get_tag_protocol(struct dsa_switch *ds, int port,
+ 	return DSA_TAG_PROTO_QCA;
+ }
+ 
++static bool
++qca8k_lag_can_offload(struct dsa_switch *ds,
++		      struct net_device *lag,
++		      struct netdev_lag_upper_info *info)
++{
++	struct dsa_port *dp;
++	int id, members = 0;
++
++	id = dsa_lag_id(ds->dst, lag);
++	if (id < 0 || id >= ds->num_lag_ids)
++		return false;
++
++	dsa_lag_foreach_port(dp, ds->dst, lag)
++		/* Includes the port joining the LAG */
++		members++;
++
++	if (members > QCA8K_NUM_PORTS_FOR_LAG)
++		return false;
++
++	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
++		return false;
++
++	if (info->hash_type != NETDEV_LAG_HASH_L2 ||
++	    info->hash_type != NETDEV_LAG_HASH_L23)
++		return false;
++
++	return true;
++}
++
++static int
++qca8k_lag_setup_hash(struct dsa_switch *ds,
++		     struct net_device *lag,
++		     struct netdev_lag_upper_info *info)
++{
++	struct qca8k_priv *priv = ds->priv;
++	bool unique_lag = true;
++	int i, id;
++	u32 hash;
++
++	id = dsa_lag_id(ds->dst, lag);
++
++	switch (info->hash_type) {
++	case NETDEV_LAG_HASH_L23:
++		hash |= QCA8K_TRUNK_HASH_SIP_EN;
++		hash |= QCA8K_TRUNK_HASH_DIP_EN;
++		fallthrough;
++	case NETDEV_LAG_HASH_L2:
++		hash |= QCA8K_TRUNK_HASH_SA_EN;
++		hash |= QCA8K_TRUNK_HASH_DA_EN;
++		break;
++	default: /* We should NEVER reach this */
++		return -EOPNOTSUPP;
++	}
++
++	/* Check if we are the unique configured LAG */
++	dsa_lags_foreach_id(i, ds->dst)
++		if (i != id && dsa_lag_dev(ds->dst, i)) {
++			unique_lag = false;
++			break;
++		}
++
++	/* Hash Mode is global. Make sure the same Hash Mode
++	 * is set to all the 4 possible lag.
++	 * If we are the unique LAG we can set whatever hash
++	 * mode we want.
++	 * To change hash mode it's needed to remove all LAG
++	 * and change the mode with the latest.
++	 */
++	if (unique_lag) {
++		priv->lag_hash_mode = hash;
++	} else if (priv->lag_hash_mode != hash) {
++		netdev_err(lag, "Error: Mismateched Hash Mode across different lag is not supported\n");
++		return -EOPNOTSUPP;
++	}
++
++	return regmap_update_bits(priv->regmap, QCA8K_TRUNK_HASH_EN_CTRL,
++				  QCA8K_TRUNK_HASH_MASK, hash);
++}
++
++static int
++qca8k_lag_refresh_portmap(struct dsa_switch *ds, int port,
++			  struct net_device *lag, bool delete)
++{
++	struct qca8k_priv *priv = ds->priv;
++	int ret, id, i;
++	u32 val;
++
++	id = dsa_lag_id(ds->dst, lag);
++
++	/* Read current port member */
++	ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0, &val);
++	if (ret)
++		return ret;
++
++	/* Shift val to the correct trunk */
++	val >>= QCA8K_REG_GOL_TRUNK_SHIFT(id);
++	val &= QCA8K_REG_GOL_TRUNK_MEMBER_MASK;
++	if (delete)
++		val &= ~BIT(port);
++	else
++		val |= BIT(port);
++
++	/* Update port member. With empty portmap disable trunk */
++	ret = regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0,
++				 QCA8K_REG_GOL_TRUNK_MEMBER(id) |
++				 QCA8K_REG_GOL_TRUNK_EN(id),
++				 !val << QCA8K_REG_GOL_TRUNK_SHIFT(id) |
++				 val << QCA8K_REG_GOL_TRUNK_SHIFT(id));
++
++	/* Search empty member if adding or port on deleting */
++	for (i = 0; i < QCA8K_NUM_PORTS_FOR_LAG; i++) {
++		ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id), &val);
++		if (ret)
++			return ret;
++
++		val >>= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i);
++		val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_MASK;
++
++		if (delete) {
++			/* If port flagged to be disabled assume this member is
++			 * empty
++			 */
++			if (val != QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK)
++				continue;
++
++			val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK;
++			if (val != port)
++				continue;
++		} else {
++			/* If port flagged to be enabled assume this member is
++			 * already set
++			 */
++			if (val == QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK)
++				continue;
++		}
++
++		/* We have found the member to add/remove */
++		break;
++	}
++
++	/* Set port in the correct port mask or disable port if in delete mode */
++	return regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id),
++				  QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN(id, i) |
++				  QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT(id, i),
++				  !delete << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i) |
++				  port << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i));
++}
++
++static int
++qca8k_port_lag_join(struct dsa_switch *ds, int port,
++		    struct net_device *lag,
++		    struct netdev_lag_upper_info *info)
++{
++	int ret;
++
++	if (!qca8k_lag_can_offload(ds, lag, info))
++		return -EOPNOTSUPP;
++
++	ret = qca8k_lag_setup_hash(ds, lag, info);
++	if (ret)
++		return ret;
++
++	return qca8k_lag_refresh_portmap(ds, port, lag, false);
++}
++
++static int
++qca8k_port_lag_leave(struct dsa_switch *ds, int port,
++		     struct net_device *lag)
++{
++	return qca8k_lag_refresh_portmap(ds, port, lag, true);
++}
++
+ static const struct dsa_switch_ops qca8k_switch_ops = {
+ 	.get_tag_protocol	= qca8k_get_tag_protocol,
+ 	.setup			= qca8k_setup,
+@@ -2236,6 +2411,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
+ 	.phylink_mac_link_down	= qca8k_phylink_mac_link_down,
+ 	.phylink_mac_link_up	= qca8k_phylink_mac_link_up,
+ 	.get_phy_flags		= qca8k_get_phy_flags,
++	.port_lag_join		= qca8k_port_lag_join,
++	.port_lag_leave		= qca8k_port_lag_leave,
+ };
+ 
+ static int qca8k_read_switch_id(struct qca8k_priv *priv)
+diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
+index 7c87a968c0104..ab4a417b25a9c 100644
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -15,6 +15,8 @@
+ #define QCA8K_NUM_PORTS					7
+ #define QCA8K_NUM_CPU_PORTS				2
+ #define QCA8K_MAX_MTU					9000
++#define QCA8K_NUM_LAGS					4
++#define QCA8K_NUM_PORTS_FOR_LAG				4
+ 
+ #define PHY_ID_QCA8327					0x004dd034
+ #define QCA8K_ID_QCA8327				0x12
+@@ -122,6 +124,14 @@
+ #define QCA8K_REG_EEE_CTRL				0x100
+ #define  QCA8K_REG_EEE_CTRL_LPI_EN(_i)			((_i + 1) * 2)
+ 
++/* TRUNK_HASH_EN registers */
++#define QCA8K_TRUNK_HASH_EN_CTRL			0x270
++#define   QCA8K_TRUNK_HASH_SIP_EN			BIT(3)
++#define   QCA8K_TRUNK_HASH_DIP_EN			BIT(2)
++#define   QCA8K_TRUNK_HASH_SA_EN			BIT(1)
++#define   QCA8K_TRUNK_HASH_DA_EN			BIT(0)
++#define   QCA8K_TRUNK_HASH_MASK				GENMASK(3, 0)
++
+ /* ACL registers */
+ #define QCA8K_REG_PORT_VLAN_CTRL0(_i)			(0x420 + (_i * 8))
+ #define   QCA8K_PORT_VLAN_CVID_MASK			GENMASK(27, 16)
+@@ -204,6 +214,28 @@
+ #define   QCA8K_PORT_LOOKUP_LEARN			BIT(20)
+ #define   QCA8K_PORT_LOOKUP_ING_MIRROR_EN		BIT(25)
+ 
++#define QCA8K_REG_GOL_TRUNK_CTRL0			0x700
++/* 4 max trunk first
++ * first 6 bit for member bitmap
++ * 7th bit is to enable trunk port
++ */
++#define QCA8K_REG_GOL_TRUNK_SHIFT(_i)			((_i) * 8)
++#define QCA8K_REG_GOL_TRUNK_EN_MASK			BIT(7)
++#define QCA8K_REG_GOL_TRUNK_EN(_i)			(QCA8K_REG_GOL_TRUNK_EN_MASK << QCA8K_REG_GOL_TRUNK_SHIFT(_i))
++#define QCA8K_REG_GOL_TRUNK_MEMBER_MASK			GENMASK(6, 0)
++#define QCA8K_REG_GOL_TRUNK_MEMBER(_i)			(QCA8K_REG_GOL_TRUNK_MEMBER_MASK << QCA8K_REG_GOL_TRUNK_SHIFT(_i))
++/* 0x704 for TRUNK 0-1 --- 0x708 for TRUNK 2-3 */
++#define QCA8K_REG_GOL_TRUNK_CTRL(_i)			(0x704 + (((_i) / 2) * 4))
++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_MASK		GENMASK(3, 0)
++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK		BIT(3)
++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK		GENMASK(2, 0)
++#define QCA8K_REG_GOL_TRUNK_ID_SHIFT(_i)		(((_i) / 2) * 16)
++#define QCA8K_REG_GOL_MEM_ID_SHIFT(_i)			((_i) * 4)
++/* Complex shift: FIRST shift for port THEN shift for trunk */
++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(_i, _j)	(QCA8K_REG_GOL_MEM_ID_SHIFT(_j) + QCA8K_REG_GOL_TRUNK_ID_SHIFT(_i))
++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN(_i, _j)	(QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(_i, _j))
++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT(_i, _j)	(QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(_i, _j))
++
+ #define QCA8K_REG_GLOBAL_FC_THRESH			0x800
+ #define   QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK		GENMASK(24, 16)
+ #define   QCA8K_GLOBAL_FC_GOL_XON_THRES(x)		FIELD_PREP(QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK, x)
+@@ -309,6 +341,7 @@ struct qca8k_priv {
+ 	u8 switch_revision;
+ 	u8 mirror_rx;
+ 	u8 mirror_tx;
++	u8 lag_hash_mode;
+ 	bool legacy_phy_port_mapping;
+ 	struct qca8k_ports_config ports_config;
+ 	struct regmap *regmap;
+-- 
+cgit 1.2.3-1.el7
+
diff --git a/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch b/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch
new file mode 100644
index 0000000000..2bde440093
--- /dev/null
+++ b/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch
@@ -0,0 +1,45 @@
+From 0898ca67b86e14207d4feb3f3fea8b87cec5aab1 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Tue, 23 Nov 2021 16:44:46 +0100
+Subject: net: dsa: qca8k: fix warning in LAG feature
+
+Fix warning reported by bot.
+Make sure hash is init to 0 and fix wrong logic for hash_type in
+qca8k_lag_can_offload.
+
+Reported-by: kernel test robot <lkp at intel.com>
+Fixes: def975307c01 ("net: dsa: qca8k: add LAG support")
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Link: https://lore.kernel.org/r/20211123154446.31019-1-ansuelsmth@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/qca8k.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
+index 6516df08a5d5f..d04b25eca2503 100644
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -2228,7 +2228,7 @@ qca8k_lag_can_offload(struct dsa_switch *ds,
+ 	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
+ 		return false;
+ 
+-	if (info->hash_type != NETDEV_LAG_HASH_L2 ||
++	if (info->hash_type != NETDEV_LAG_HASH_L2 &&
+ 	    info->hash_type != NETDEV_LAG_HASH_L23)
+ 		return false;
+ 
+@@ -2242,8 +2242,8 @@ qca8k_lag_setup_hash(struct dsa_switch *ds,
+ {
+ 	struct qca8k_priv *priv = ds->priv;
+ 	bool unique_lag = true;
++	u32 hash = 0;
+ 	int i, id;
+-	u32 hash;
+ 
+ 	id = dsa_lag_id(ds->dst, lag);
+ 
+-- 
+cgit 1.2.3-1.el7
+




More information about the lede-commits mailing list