123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- From 412e1775f413c944b8c51bdadb675be957d83dc8 Mon Sep 17 00:00:00 2001
- Message-ID: <412e1775f413c944b8c51bdadb675be957d83dc8.1728674648.git.mschiffer@universe-factory.net>
- In-Reply-To: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
- References: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
- From: Matthias Schiffer <[email protected]>
- Date: Thu, 20 Jun 2024 19:25:49 +0200
- Subject: [PATCH] net: dsa: qca8k: factor out bridge join/leave logic
- Most of the logic in qca8k_port_bridge_join() and qca8k_port_bridge_leave()
- is the same. Refactor to reduce duplication and prepare for reusing the
- code for implementing bridge port isolation.
- dsa_port_offloads_bridge_dev() is used instead of
- dsa_port_offloads_bridge(), passing the bridge in as a struct netdevice *,
- as we won't have a struct dsa_bridge in qca8k_port_bridge_flags().
- The error handling is changed slightly in the bridge leave case,
- returning early and emitting an error message when a regmap access fails.
- This shouldn't matter in practice, as there isn't much we can do if
- communication with the switch breaks down in the middle of reconfiguration.
- Signed-off-by: Matthias Schiffer <[email protected]>
- Reviewed-by: Wojciech Drewek <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- drivers/net/dsa/qca/qca8k-common.c | 101 ++++++++++++++---------------
- 1 file changed, 50 insertions(+), 51 deletions(-)
- --- a/drivers/net/dsa/qca/qca8k-common.c
- +++ b/drivers/net/dsa/qca/qca8k-common.c
- @@ -615,6 +615,49 @@ void qca8k_port_stp_state_set(struct dsa
- qca8k_port_configure_learning(ds, port, learning);
- }
-
- +static int qca8k_update_port_member(struct qca8k_priv *priv, int port,
- + const struct net_device *bridge_dev,
- + bool join)
- +{
- + struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp;
- + u32 port_mask = BIT(dp->cpu_dp->index);
- + int i, ret;
- +
- + for (i = 0; i < QCA8K_NUM_PORTS; i++) {
- + if (i == port)
- + continue;
- + if (dsa_is_cpu_port(priv->ds, i))
- + continue;
- +
- + other_dp = dsa_to_port(priv->ds, i);
- + if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev))
- + continue;
- +
- + /* Add/remove this port to/from the portvlan mask of the other
- + * ports in the bridge
- + */
- + if (join) {
- + port_mask |= BIT(i);
- + ret = regmap_set_bits(priv->regmap,
- + QCA8K_PORT_LOOKUP_CTRL(i),
- + BIT(port));
- + } else {
- + ret = regmap_clear_bits(priv->regmap,
- + QCA8K_PORT_LOOKUP_CTRL(i),
- + BIT(port));
- + }
- +
- + if (ret)
- + return ret;
- + }
- +
- + /* Add/remove all other ports to/from this port's portvlan mask */
- + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
- + QCA8K_PORT_LOOKUP_MEMBER, port_mask);
- +
- + return ret;
- +}
- +
- int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
- struct switchdev_brport_flags flags,
- struct netlink_ext_ack *extack)
- @@ -647,65 +690,21 @@ int qca8k_port_bridge_join(struct dsa_sw
- struct netlink_ext_ack *extack)
- {
- struct qca8k_priv *priv = ds->priv;
- - int port_mask, cpu_port;
- - int i, ret;
- -
- - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
- - port_mask = BIT(cpu_port);
-
- - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
- - if (i == port)
- - continue;
- - if (dsa_is_cpu_port(ds, i))
- - continue;
- - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
- - continue;
- - /* Add this port to the portvlan mask of the other ports
- - * in the bridge
- - */
- - ret = regmap_set_bits(priv->regmap,
- - QCA8K_PORT_LOOKUP_CTRL(i),
- - BIT(port));
- - if (ret)
- - return ret;
- - port_mask |= BIT(i);
- - }
- -
- - /* Add all other ports to this ports portvlan mask */
- - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
- - QCA8K_PORT_LOOKUP_MEMBER, port_mask);
- -
- - return ret;
- + return qca8k_update_port_member(priv, port, bridge.dev, true);
- }
-
- void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge)
- {
- struct qca8k_priv *priv = ds->priv;
- - int cpu_port, i;
- -
- - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
- -
- - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
- - if (i == port)
- - continue;
- - if (dsa_is_cpu_port(ds, i))
- - continue;
- - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
- - continue;
- - /* Remove this port to the portvlan mask of the other ports
- - * in the bridge
- - */
- - regmap_clear_bits(priv->regmap,
- - QCA8K_PORT_LOOKUP_CTRL(i),
- - BIT(port));
- - }
- + int err;
-
- - /* Set the cpu port to be the only one in the portvlan mask of
- - * this port
- - */
- - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
- - QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
- + err = qca8k_update_port_member(priv, port, bridge.dev, false);
- + if (err)
- + dev_err(priv->dev,
- + "Failed to update switch config for bridge leave: %d\n",
- + err);
- }
-
- void qca8k_port_fast_age(struct dsa_switch *ds, int port)
|