mirror of
https://github.com/openwrt/openwrt.git
synced 2025-04-10 12:50:47 +00:00
generic: 6.1: backport patch for multi CPU port support on QCA8K
Backport pending patch for multi CPU port support on QCA8K. 6.1 already supports all the requiredt code to change a DSA master port so only this patch fixing the driver is required. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
parent
a62b1544d1
commit
500dbaefd2
@ -0,0 +1,86 @@
|
||||
From 3b4329230db8750bea7a56ef07f07cbbf5fc6c5a Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 4 Jul 2023 22:50:12 +0200
|
||||
Subject: [PATCH 19/20] net: dsa: qca8k: implement lag_fdb_add/del ops
|
||||
|
||||
Implement lag_fdb_add/del ops to correctly support using LAG interface.
|
||||
Qca8k switch supports declaring fdb entry for link aggregation by simply
|
||||
setting the DES_PORT bits to all the LAG member.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-8xxx.c | 2 ++
|
||||
drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/qca/qca8k.h | 6 ++++
|
||||
3 files changed, 56 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -1993,6 +1993,8 @@ static const struct dsa_switch_ops qca8k
|
||||
.port_fdb_add = qca8k_port_fdb_add,
|
||||
.port_fdb_del = qca8k_port_fdb_del,
|
||||
.port_fdb_dump = qca8k_port_fdb_dump,
|
||||
+ .lag_fdb_add = qca8k_lag_fdb_add,
|
||||
+ .lag_fdb_del = qca8k_lag_fdb_del,
|
||||
.port_mdb_add = qca8k_port_mdb_add,
|
||||
.port_mdb_del = qca8k_port_mdb_del,
|
||||
.port_mirror_add = qca8k_port_mirror_add,
|
||||
--- a/drivers/net/dsa/qca/qca8k-common.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-common.c
|
||||
@@ -1215,6 +1215,42 @@ int qca8k_port_lag_leave(struct dsa_swit
|
||||
return qca8k_lag_refresh_portmap(ds, port, lag, true);
|
||||
}
|
||||
|
||||
+int qca8k_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag,
|
||||
+ const unsigned char *addr, u16 vid,
|
||||
+ struct dsa_db db)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
+ struct dsa_port *dp;
|
||||
+ u16 port_mask = 0;
|
||||
+
|
||||
+ /* Set the vid to the port vlan id if no vid is set */
|
||||
+ if (!vid)
|
||||
+ vid = QCA8K_PORT_VID_DEF;
|
||||
+
|
||||
+ dsa_lag_foreach_port(dp, ds->dst, &lag)
|
||||
+ port_mask |= BIT(dp->index);
|
||||
+
|
||||
+ return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
|
||||
+}
|
||||
+
|
||||
+int qca8k_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag,
|
||||
+ const unsigned char *addr, u16 vid,
|
||||
+ struct dsa_db db)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
+ struct dsa_port *dp;
|
||||
+ u16 port_mask = 0;
|
||||
+
|
||||
+ /* Set the vid to the port vlan id if no vid is set */
|
||||
+ if (!vid)
|
||||
+ vid = QCA8K_PORT_VID_DEF;
|
||||
+
|
||||
+ dsa_lag_foreach_port(dp, ds->dst, &lag)
|
||||
+ port_mask |= BIT(dp->index);
|
||||
+
|
||||
+ return qca8k_fdb_del(priv, addr, port_mask, vid);
|
||||
+}
|
||||
+
|
||||
int qca8k_read_switch_id(struct qca8k_priv *priv)
|
||||
{
|
||||
u32 val;
|
||||
--- a/drivers/net/dsa/qca/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca/qca8k.h
|
||||
@@ -590,5 +590,11 @@ int qca8k_port_lag_join(struct dsa_switc
|
||||
struct netlink_ext_ack *extack);
|
||||
int qca8k_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
struct dsa_lag lag);
|
||||
+int qca8k_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag,
|
||||
+ const unsigned char *addr, u16 vid,
|
||||
+ struct dsa_db db);
|
||||
+int qca8k_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag,
|
||||
+ const unsigned char *addr, u16 vid,
|
||||
+ struct dsa_db db);
|
||||
|
||||
#endif /* __QCA8K_H */
|
@ -0,0 +1,37 @@
|
||||
From b954d61d9ecfa64450fc178586719dc2a95b92a7 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 20 Jun 2023 21:48:24 +0200
|
||||
Subject: [PATCH 3/4] net: dsa: qca8k: enable flooding to both CPU port
|
||||
|
||||
To permit a multi-CPU setup, flood all unknown frames to all CPU ports.
|
||||
Each CPU port should have correct LOOKUP MEMBER configuration to
|
||||
prevent receiving duplicate packets from user ports.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-8xxx.c | 13 +++++--------
|
||||
1 file changed, 5 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -1882,15 +1882,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
- /* Forward all unknown frames to CPU port for Linux processing
|
||||
- * Notice that in multi-cpu config only one port should be set
|
||||
- * for igmp, unknown, multicast and broadcast packet
|
||||
- */
|
||||
+ /* Forward all unknown frames to CPU port for Linux processing */
|
||||
ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
|
||||
- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, BIT(cpu_port)) |
|
||||
- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, BIT(cpu_port)) |
|
||||
- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, BIT(cpu_port)) |
|
||||
- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, BIT(cpu_port)));
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, dsa_cpu_ports(ds)) |
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, dsa_cpu_ports(ds)) |
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, dsa_cpu_ports(ds)) |
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, dsa_cpu_ports(ds)));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -0,0 +1,158 @@
|
||||
From b2d6ebf2f92f8695c83fa6979f4ab579c588df76 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 20 Jun 2023 07:57:38 +0200
|
||||
Subject: [PATCH 4/4] net: dsa: qca8k: add support for port_change_master
|
||||
|
||||
Add support for port_change_master to permit assigning an alternative
|
||||
CPU port if the switch have both CPU port connected or create a LAG on
|
||||
both CPU port and assign the LAG as DSA master.
|
||||
|
||||
On port change master request, we check if the master is a LAG.
|
||||
With LAG we compose the cpu_port_mask with the CPU port in the LAG, if
|
||||
master is a simple dsa_port, we derive the index.
|
||||
|
||||
Finally we apply the new cpu_port_mask to the LOOKUP MEMBER to permit
|
||||
the port to receive packet by the new CPU port setup for the port and we
|
||||
refresh the CPU ports LOOKUP MEMBER configuration to reflect the new
|
||||
user port state.
|
||||
|
||||
port_lag_join/leave is updated to refresh the user ports if we detect
|
||||
that the LAG is a DSA master and we have user port using it as a master.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-8xxx.c | 116 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 114 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -1719,6 +1719,117 @@ qca8k_get_tag_protocol(struct dsa_switch
|
||||
return DSA_TAG_PROTO_QCA;
|
||||
}
|
||||
|
||||
+static int qca8k_port_change_master(struct dsa_switch *ds, int port,
|
||||
+ struct net_device *master,
|
||||
+ struct netlink_ext_ack *extack)
|
||||
+{
|
||||
+ struct dsa_switch_tree *dst = ds->dst;
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+ u8 cpu_port_mask = 0;
|
||||
+ struct dsa_port *dp;
|
||||
+ u32 val;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* With LAG of CPU port, compose the mask for port LOOKUP MEMBER */
|
||||
+ if (netif_is_lag_master(master)) {
|
||||
+ struct dsa_lag *lag;
|
||||
+ int id;
|
||||
+
|
||||
+ id = dsa_lag_id(dst, master);
|
||||
+ lag = dsa_lag_by_id(dst, id);
|
||||
+
|
||||
+ dsa_lag_foreach_port(dp, dst, lag)
|
||||
+ if (dsa_port_is_cpu(dp))
|
||||
+ cpu_port_mask |= BIT(dp->index);
|
||||
+ } else {
|
||||
+ dp = master->dsa_ptr;
|
||||
+ cpu_port_mask |= BIT(dp->index);
|
||||
+ }
|
||||
+
|
||||
+ /* Connect port to new cpu port */
|
||||
+ ret = regmap_read(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), &val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Reset connected CPU port in port LOOKUP MEMBER */
|
||||
+ val &= ~dsa_cpu_ports(ds);
|
||||
+ /* Assign the new CPU port in port LOOKUP MEMBER */
|
||||
+ val |= cpu_port_mask;
|
||||
+
|
||||
+ ret = regmap_update_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
+ QCA8K_PORT_LOOKUP_MEMBER,
|
||||
+ val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Refresh CPU port LOOKUP MEMBER with new port */
|
||||
+ dsa_tree_for_each_cpu_port(dp, ds->dst) {
|
||||
+ u32 reg = QCA8K_PORT_LOOKUP_CTRL(dp->index);
|
||||
+
|
||||
+ /* If CPU port in mask assign port, else remove port */
|
||||
+ if (BIT(dp->index) & cpu_port_mask)
|
||||
+ ret = regmap_set_bits(priv->regmap, reg, BIT(port));
|
||||
+ else
|
||||
+ ret = regmap_clear_bits(priv->regmap, reg, BIT(port));
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qca8k_port_lag_refresh_user_ports(struct dsa_switch *ds,
|
||||
+ struct dsa_lag lag)
|
||||
+{
|
||||
+ struct net_device *lag_dev = lag.dev;
|
||||
+ struct dsa_port *dp;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Ignore if LAG is not a DSA master */
|
||||
+ if (!netif_is_lag_master(lag_dev))
|
||||
+ return 0;
|
||||
+
|
||||
+ dsa_switch_for_each_user_port(dp, ds) {
|
||||
+ /* Skip if assigned master is not the LAG */
|
||||
+ if (dsa_port_to_master(dp) != lag_dev)
|
||||
+ continue;
|
||||
+
|
||||
+ ret = qca8k_port_change_master(ds, dp->index,
|
||||
+ lag_dev, NULL);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qca8xxx_port_lag_join(struct dsa_switch *ds, int port,
|
||||
+ struct dsa_lag lag,
|
||||
+ struct netdev_lag_upper_info *info,
|
||||
+ struct netlink_ext_ack *extack)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qca8k_port_lag_join(ds, port, lag, info, extack);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return qca8k_port_lag_refresh_user_ports(ds, lag);
|
||||
+}
|
||||
+
|
||||
+static int qca8xxx_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
+ struct dsa_lag lag)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qca8k_port_lag_leave(ds, port, lag);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return qca8k_port_lag_refresh_user_ports(ds, lag);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
qca8k_master_change(struct dsa_switch *ds, const struct net_device *master,
|
||||
bool operational)
|
||||
@@ -2005,8 +2116,9 @@ static const struct dsa_switch_ops qca8k
|
||||
.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,
|
||||
+ .port_lag_join = qca8xxx_port_lag_join,
|
||||
+ .port_lag_leave = qca8xxx_port_lag_leave,
|
||||
+ .port_change_master = qca8k_port_change_master,
|
||||
.master_state_change = qca8k_master_change,
|
||||
.connect_tag_protocol = qca8k_connect_tag_protocol,
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user