Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
From: Daniel Golle
Date: Sun Mar 22 2026 - 22:30:15 EST
On Sun, Mar 22, 2026 at 12:19:06AM +0000, Daniel Golle wrote:
> Drivers that offload bridges need to iterate over the ports that are
> members of a given bridge, for example to rebuild per-port forwarding
> bitmaps when membership changes. Currently each driver must open-code
> this by combining dsa_switch_for_each_user_port() with a
> dsa_port_offloads_bridge() check, or cache bridge membership within
> the driver.
>
> Add dsa_bridge_for_each_member() to express this pattern directly, and
> a dsa_bridge_ports() helper that returns a bitmask of member ports,
> matching the existing dsa_user_ports() and dsa_cpu_ports() helpers.
> [...]
> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index 1c6f6c3b88e86..4f43d518f3de3 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -838,6 +838,22 @@ static inline bool dsa_port_tree_same(const struct dsa_port *a,
> return a->ds->dst == b->ds->dst;
> }
>
> +#define dsa_bridge_for_each_member(_dp, _ds, _bridge) \
> + dsa_switch_for_each_user_port((_dp), (_ds)) \
> + if (dsa_port_offloads_bridge((_dp), (_bridge)))
> +
> +static inline u32 dsa_bridge_ports(struct dsa_switch *ds,
> + const struct dsa_bridge *bridge)
> +{
I wasn't aware of the similar and equally named function in
yt921x.c[1]
Patchwork CI has loudly uncovered it and I've learned my lesson to
always test an all-y build when changing even the most innocent
looking things which technically may affect other drivers.
I'll move that function as-is, in a dedicated commit, to
include/net/dsa.h as an inline function instead of the helper
suggested here.
A second commit will introduce the new helper macro
dsa_switch_for_each_bridge_member (modified to use (struct net_device
*) as parameter instead of (struct dsa_bridge *), and make use of it
in dsa_bridge_ports().
I'm also planning to introduce dsa_bridge_for_each_member macro in
addition to that which works on (struct dsa_bridge *) and uses
dsa_switch_for_each_bridge_member.
[1]: https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/dsa/yt921x.c?id=fb78a629b4f0eb399b413f6c093a3da177b3a4eb#n2158
In code, it's going to look like this:
diff --git a/include/net/dsa.h b/include/net/dsa.h
index b43fa7a708c72..c10f05f3e96ed 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -832,15 +832,21 @@ dsa_tree_offloads_bridge_dev(struct dsa_switch_tree *dst,
return false;
}
+#define dsa_switch_for_each_bridge_member(_dp, _ds, _bdev) \
+ dsa_switch_for_each_user_port(_dp, _ds) \
+ if (dsa_port_offloads_bridge_dev(_dp, _bdev))
+
+#define dsa_bridge_for_each_member(_dp, _ds, _db) \
+ dsa_switch_for_each_bridge_member(_dp, _ds, (_db)->dev)
+
static inline u32
dsa_bridge_ports(struct dsa_switch *ds, const struct net_device *bdev)
{
struct dsa_port *dp;
u32 mask = 0;
- dsa_switch_for_each_user_port(dp, ds)
- if (dsa_port_offloads_bridge_dev(dp, bdev))
- mask |= BIT(dp->index);
+ dsa_switch_for_each_bridge_member(dp, ds, bdev)
+ mask |= BIT(dp->index);
return mask;
}
Please let me know if any objections you may have.