[PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper

Daniel Golle posted 4 patches 1 week, 5 days ago
There is a newer version of this series
[PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Daniel Golle 1 week, 5 days ago
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.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v6: new patch

 include/net/dsa.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

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)
+{
+	struct dsa_port *dp;
+	u32 mask = 0;
+
+	dsa_bridge_for_each_member(dp, ds, bridge)
+		mask |= BIT(dp->index);
+
+	return mask;
+}
+
 typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
 			      bool is_static, void *data);
 struct dsa_switch_ops {
-- 
2.53.0
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by kernel test robot 1 week, 3 days ago
Hi Daniel,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Daniel-Golle/net-dsa-add-driver-private-pointer-to-struct-dsa_bridge/20260323-041502
base:   net-next/main
patch link:    https://lore.kernel.org/r/ff936ce4ad3044102c367c55e7a455ab0020e4b7.1774136876.git.daniel%40makrotopia.org
patch subject: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20260325/202603250450.uUuzfUx3-lkp@intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260325/202603250450.uUuzfUx3-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603250450.uUuzfUx3-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/net/dsa/yt921x.c:2158:1: error: conflicting types for 'dsa_bridge_ports'
   dsa_bridge_ports(struct dsa_switch *ds, const struct net_device *bdev)
   ^
   include/net/dsa.h:845:19: note: previous definition is here
   static inline u32 dsa_bridge_ports(struct dsa_switch *ds,
                     ^
>> drivers/net/dsa/yt921x.c:2213:38: error: incompatible pointer types passing 'struct net_device *' to parameter of type 'const struct dsa_bridge *' [-Werror,-Wincompatible-pointer-types]
                           ports_mask = dsa_bridge_ports(ds, bdev);
                                                             ^~~~
   include/net/dsa.h:846:33: note: passing argument to parameter 'bridge' here
                                      const struct dsa_bridge *bridge)
                                                               ^
   drivers/net/dsa/yt921x.c:2285:36: error: incompatible pointer types passing 'struct net_device *' to parameter of type 'const struct dsa_bridge *' [-Werror,-Wincompatible-pointer-types]
           ports_mask = dsa_bridge_ports(ds, bridge.dev);
                                             ^~~~~~~~~~
   include/net/dsa.h:846:33: note: passing argument to parameter 'bridge' here
                                      const struct dsa_bridge *bridge)
                                                               ^
   3 errors generated.


vim +2213 drivers/net/dsa/yt921x.c

186623f4aa724c David Yang 2025-10-17  2169  
186623f4aa724c David Yang 2025-10-17  2170  static int
186623f4aa724c David Yang 2025-10-17  2171  yt921x_bridge_flags(struct yt921x_priv *priv, int port,
186623f4aa724c David Yang 2025-10-17  2172  		    struct switchdev_brport_flags flags)
186623f4aa724c David Yang 2025-10-17  2173  {
186623f4aa724c David Yang 2025-10-17  2174  	struct yt921x_port *pp = &priv->ports[port];
186623f4aa724c David Yang 2025-10-17  2175  	bool do_flush;
186623f4aa724c David Yang 2025-10-17  2176  	u32 mask;
186623f4aa724c David Yang 2025-10-17  2177  	int res;
186623f4aa724c David Yang 2025-10-17  2178  
186623f4aa724c David Yang 2025-10-17  2179  	if (flags.mask & BR_LEARNING) {
186623f4aa724c David Yang 2025-10-17  2180  		bool learning = flags.val & BR_LEARNING;
186623f4aa724c David Yang 2025-10-17  2181  
186623f4aa724c David Yang 2025-10-17  2182  		mask = YT921X_PORT_LEARN_DIS;
186623f4aa724c David Yang 2025-10-17  2183  		res = yt921x_reg_toggle_bits(priv, YT921X_PORTn_LEARN(port),
186623f4aa724c David Yang 2025-10-17  2184  					     mask, !learning);
186623f4aa724c David Yang 2025-10-17  2185  		if (res)
186623f4aa724c David Yang 2025-10-17  2186  			return res;
186623f4aa724c David Yang 2025-10-17  2187  	}
186623f4aa724c David Yang 2025-10-17  2188  
186623f4aa724c David Yang 2025-10-17  2189  	/* BR_FLOOD, BR_MCAST_FLOOD: see the comment where ACT_UNK_ACTn_TRAP
186623f4aa724c David Yang 2025-10-17  2190  	 * is set
186623f4aa724c David Yang 2025-10-17  2191  	 */
186623f4aa724c David Yang 2025-10-17  2192  
186623f4aa724c David Yang 2025-10-17  2193  	/* BR_BCAST_FLOOD: we can filter bcast, but cannot trap them */
186623f4aa724c David Yang 2025-10-17  2194  
186623f4aa724c David Yang 2025-10-17  2195  	do_flush = false;
186623f4aa724c David Yang 2025-10-17  2196  	if (flags.mask & BR_HAIRPIN_MODE) {
186623f4aa724c David Yang 2025-10-17  2197  		pp->hairpin = flags.val & BR_HAIRPIN_MODE;
186623f4aa724c David Yang 2025-10-17  2198  		do_flush = true;
186623f4aa724c David Yang 2025-10-17  2199  	}
186623f4aa724c David Yang 2025-10-17  2200  	if (flags.mask & BR_ISOLATED) {
186623f4aa724c David Yang 2025-10-17  2201  		pp->isolated = flags.val & BR_ISOLATED;
186623f4aa724c David Yang 2025-10-17  2202  		do_flush = true;
186623f4aa724c David Yang 2025-10-17  2203  	}
186623f4aa724c David Yang 2025-10-17  2204  	if (do_flush) {
186623f4aa724c David Yang 2025-10-17  2205  		struct dsa_switch *ds = &priv->ds;
186623f4aa724c David Yang 2025-10-17  2206  		struct dsa_port *dp = dsa_to_port(ds, port);
186623f4aa724c David Yang 2025-10-17  2207  		struct net_device *bdev;
186623f4aa724c David Yang 2025-10-17  2208  
186623f4aa724c David Yang 2025-10-17  2209  		bdev = dsa_port_bridge_dev_get(dp);
186623f4aa724c David Yang 2025-10-17  2210  		if (bdev) {
186623f4aa724c David Yang 2025-10-17  2211  			u32 ports_mask;
186623f4aa724c David Yang 2025-10-17  2212  
186623f4aa724c David Yang 2025-10-17 @2213  			ports_mask = dsa_bridge_ports(ds, bdev);
186623f4aa724c David Yang 2025-10-17  2214  			ports_mask |= priv->cpu_ports_mask;
186623f4aa724c David Yang 2025-10-17  2215  			res = yt921x_bridge(priv, ports_mask);
186623f4aa724c David Yang 2025-10-17  2216  			if (res)
186623f4aa724c David Yang 2025-10-17  2217  				return res;
186623f4aa724c David Yang 2025-10-17  2218  		}
186623f4aa724c David Yang 2025-10-17  2219  	}
186623f4aa724c David Yang 2025-10-17  2220  
186623f4aa724c David Yang 2025-10-17  2221  	return 0;
186623f4aa724c David Yang 2025-10-17  2222  }
186623f4aa724c David Yang 2025-10-17  2223  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by kernel test robot 1 week, 4 days ago
Hi Daniel,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Daniel-Golle/net-dsa-add-driver-private-pointer-to-struct-dsa_bridge/20260323-041502
base:   net-next/main
patch link:    https://lore.kernel.org/r/ff936ce4ad3044102c367c55e7a455ab0020e4b7.1774136876.git.daniel%40makrotopia.org
patch subject: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
config: arm-randconfig-002-20260323 (https://download.01.org/0day-ci/archive/20260323/202603231807.3CRfrjTg-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project c911b8492374942bf4cfe35411e90a35d3837f6a)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260323/202603231807.3CRfrjTg-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603231807.3CRfrjTg-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/net/dsa/yt921x.c:2158:1: error: conflicting types for 'dsa_bridge_ports'
    2158 | dsa_bridge_ports(struct dsa_switch *ds, const struct net_device *bdev)
         | ^
   include/net/dsa.h:845:19: note: previous definition is here
     845 | static inline u32 dsa_bridge_ports(struct dsa_switch *ds,
         |                   ^
>> drivers/net/dsa/yt921x.c:2213:38: error: incompatible pointer types passing 'struct net_device *' to parameter of type 'const struct dsa_bridge *' [-Wincompatible-pointer-types]
    2213 |                         ports_mask = dsa_bridge_ports(ds, bdev);
         |                                                           ^~~~
   include/net/dsa.h:846:33: note: passing argument to parameter 'bridge' here
     846 |                                    const struct dsa_bridge *bridge)
         |                                                             ^
   drivers/net/dsa/yt921x.c:2285:36: error: incompatible pointer types passing 'struct net_device *' to parameter of type 'const struct dsa_bridge *' [-Wincompatible-pointer-types]
    2285 |         ports_mask = dsa_bridge_ports(ds, bridge.dev);
         |                                           ^~~~~~~~~~
   include/net/dsa.h:846:33: note: passing argument to parameter 'bridge' here
     846 |                                    const struct dsa_bridge *bridge)
         |                                                             ^
   3 errors generated.


vim +/dsa_bridge_ports +2158 drivers/net/dsa/yt921x.c

186623f4aa724c David Yang 2025-10-17  2156  
186623f4aa724c David Yang 2025-10-17  2157  static u32
186623f4aa724c David Yang 2025-10-17 @2158  dsa_bridge_ports(struct dsa_switch *ds, const struct net_device *bdev)
186623f4aa724c David Yang 2025-10-17  2159  {
186623f4aa724c David Yang 2025-10-17  2160  	struct dsa_port *dp;
186623f4aa724c David Yang 2025-10-17  2161  	u32 mask = 0;
186623f4aa724c David Yang 2025-10-17  2162  
186623f4aa724c David Yang 2025-10-17  2163  	dsa_switch_for_each_user_port(dp, ds)
186623f4aa724c David Yang 2025-10-17  2164  		if (dsa_port_offloads_bridge_dev(dp, bdev))
186623f4aa724c David Yang 2025-10-17  2165  			mask |= BIT(dp->index);
186623f4aa724c David Yang 2025-10-17  2166  
186623f4aa724c David Yang 2025-10-17  2167  	return mask;
186623f4aa724c David Yang 2025-10-17  2168  }
186623f4aa724c David Yang 2025-10-17  2169  
186623f4aa724c David Yang 2025-10-17  2170  static int
186623f4aa724c David Yang 2025-10-17  2171  yt921x_bridge_flags(struct yt921x_priv *priv, int port,
186623f4aa724c David Yang 2025-10-17  2172  		    struct switchdev_brport_flags flags)
186623f4aa724c David Yang 2025-10-17  2173  {
186623f4aa724c David Yang 2025-10-17  2174  	struct yt921x_port *pp = &priv->ports[port];
186623f4aa724c David Yang 2025-10-17  2175  	bool do_flush;
186623f4aa724c David Yang 2025-10-17  2176  	u32 mask;
186623f4aa724c David Yang 2025-10-17  2177  	int res;
186623f4aa724c David Yang 2025-10-17  2178  
186623f4aa724c David Yang 2025-10-17  2179  	if (flags.mask & BR_LEARNING) {
186623f4aa724c David Yang 2025-10-17  2180  		bool learning = flags.val & BR_LEARNING;
186623f4aa724c David Yang 2025-10-17  2181  
186623f4aa724c David Yang 2025-10-17  2182  		mask = YT921X_PORT_LEARN_DIS;
186623f4aa724c David Yang 2025-10-17  2183  		res = yt921x_reg_toggle_bits(priv, YT921X_PORTn_LEARN(port),
186623f4aa724c David Yang 2025-10-17  2184  					     mask, !learning);
186623f4aa724c David Yang 2025-10-17  2185  		if (res)
186623f4aa724c David Yang 2025-10-17  2186  			return res;
186623f4aa724c David Yang 2025-10-17  2187  	}
186623f4aa724c David Yang 2025-10-17  2188  
186623f4aa724c David Yang 2025-10-17  2189  	/* BR_FLOOD, BR_MCAST_FLOOD: see the comment where ACT_UNK_ACTn_TRAP
186623f4aa724c David Yang 2025-10-17  2190  	 * is set
186623f4aa724c David Yang 2025-10-17  2191  	 */
186623f4aa724c David Yang 2025-10-17  2192  
186623f4aa724c David Yang 2025-10-17  2193  	/* BR_BCAST_FLOOD: we can filter bcast, but cannot trap them */
186623f4aa724c David Yang 2025-10-17  2194  
186623f4aa724c David Yang 2025-10-17  2195  	do_flush = false;
186623f4aa724c David Yang 2025-10-17  2196  	if (flags.mask & BR_HAIRPIN_MODE) {
186623f4aa724c David Yang 2025-10-17  2197  		pp->hairpin = flags.val & BR_HAIRPIN_MODE;
186623f4aa724c David Yang 2025-10-17  2198  		do_flush = true;
186623f4aa724c David Yang 2025-10-17  2199  	}
186623f4aa724c David Yang 2025-10-17  2200  	if (flags.mask & BR_ISOLATED) {
186623f4aa724c David Yang 2025-10-17  2201  		pp->isolated = flags.val & BR_ISOLATED;
186623f4aa724c David Yang 2025-10-17  2202  		do_flush = true;
186623f4aa724c David Yang 2025-10-17  2203  	}
186623f4aa724c David Yang 2025-10-17  2204  	if (do_flush) {
186623f4aa724c David Yang 2025-10-17  2205  		struct dsa_switch *ds = &priv->ds;
186623f4aa724c David Yang 2025-10-17  2206  		struct dsa_port *dp = dsa_to_port(ds, port);
186623f4aa724c David Yang 2025-10-17  2207  		struct net_device *bdev;
186623f4aa724c David Yang 2025-10-17  2208  
186623f4aa724c David Yang 2025-10-17  2209  		bdev = dsa_port_bridge_dev_get(dp);
186623f4aa724c David Yang 2025-10-17  2210  		if (bdev) {
186623f4aa724c David Yang 2025-10-17  2211  			u32 ports_mask;
186623f4aa724c David Yang 2025-10-17  2212  
186623f4aa724c David Yang 2025-10-17 @2213  			ports_mask = dsa_bridge_ports(ds, bdev);
186623f4aa724c David Yang 2025-10-17  2214  			ports_mask |= priv->cpu_ports_mask;
186623f4aa724c David Yang 2025-10-17  2215  			res = yt921x_bridge(priv, ports_mask);
186623f4aa724c David Yang 2025-10-17  2216  			if (res)
186623f4aa724c David Yang 2025-10-17  2217  				return res;
186623f4aa724c David Yang 2025-10-17  2218  		}
186623f4aa724c David Yang 2025-10-17  2219  	}
186623f4aa724c David Yang 2025-10-17  2220  
186623f4aa724c David Yang 2025-10-17  2221  	return 0;
186623f4aa724c David Yang 2025-10-17  2222  }
186623f4aa724c David Yang 2025-10-17  2223  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Daniel Golle 1 week, 4 days ago
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.
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Vladimir Oltean 1 week, 4 days ago
On Mon, Mar 23, 2026 at 02:29:41AM +0000, Daniel Golle wrote:
> I wasn't aware of the similar and equally named function in
> yt921x.c[1]

Yeah, I did request from the beginning for it to be moved to
include/net/dsa.h, but I didn't follow through with the request (I guess
I forgot):
https://lore.kernel.org/netdev/20250825212357.3acgen2qezuy533y@skbuf/

> 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.

Since all DSA drivers are all in the same folder, technically you may be
excused if you just enable all those when working on infra, instead of
allyesconfig.

> 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.

I don't like the dsa_bridge_for_each_member() name. You are likely
not considering cross-chip bridging, where a bridge spans multiple
dsa_switch structures. That is also a serious reason why your
bridge->priv design is not viable (two switches can't lay their eggs
in the same basket without overwriting each other).
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Daniel Golle 1 week, 3 days ago
On Mon, Mar 23, 2026 at 06:31:04PM +0200, Vladimir Oltean wrote:
> On Mon, Mar 23, 2026 at 02:29:41AM +0000, Daniel Golle wrote:
> > 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.
> 
> I don't like the dsa_bridge_for_each_member() name. You are likely
> not considering cross-chip bridging, where a bridge spans multiple
> dsa_switch structures. That is also a serious reason why your
> bridge->priv design is not viable (two switches can't lay their eggs
> in the same basket without overwriting each other).

dsa_bridge_for_each_local_member() ?

dsa_switch_for_each_dsa_bridge_member()
(but that's too close to dsa_switch_for_each_bridge_member imho)

I was planning to have both, dsa_switch and dsa_bridge as parameters,
of course, limiting the scope to a single dsa_switch.
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Vladimir Oltean 1 week, 2 days ago
On Tue, Mar 24, 2026 at 11:31:30PM +0000, Daniel Golle wrote:
> On Mon, Mar 23, 2026 at 06:31:04PM +0200, Vladimir Oltean wrote:
> > On Mon, Mar 23, 2026 at 02:29:41AM +0000, Daniel Golle wrote:
> > > 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.
> > 
> > I don't like the dsa_bridge_for_each_member() name. You are likely
> > not considering cross-chip bridging, where a bridge spans multiple
> > dsa_switch structures. That is also a serious reason why your
> > bridge->priv design is not viable (two switches can't lay their eggs
> > in the same basket without overwriting each other).
> 
> dsa_bridge_for_each_local_member() ?
> 
> dsa_switch_for_each_dsa_bridge_member()
> (but that's too close to dsa_switch_for_each_bridge_member imho)
> 
> I was planning to have both, dsa_switch and dsa_bridge as parameters,
> of course, limiting the scope to a single dsa_switch.

I'm not sure that we do need two iterators. Just
dsa_switch_for_each_bridge_member() should be fine.
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Daniel Golle 1 week, 2 days ago
On Wed, Mar 25, 2026 at 10:34:27AM +0200, Vladimir Oltean wrote:
> On Tue, Mar 24, 2026 at 11:31:30PM +0000, Daniel Golle wrote:
> > On Mon, Mar 23, 2026 at 06:31:04PM +0200, Vladimir Oltean wrote:
> > > On Mon, Mar 23, 2026 at 02:29:41AM +0000, Daniel Golle wrote:
> > > > 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.
> > > 
> > > I don't like the dsa_bridge_for_each_member() name. You are likely
> > > not considering cross-chip bridging, where a bridge spans multiple
> > > dsa_switch structures. That is also a serious reason why your
> > > bridge->priv design is not viable (two switches can't lay their eggs
> > > in the same basket without overwriting each other).
> > 
> > dsa_bridge_for_each_local_member() ?
> > 
> > dsa_switch_for_each_dsa_bridge_member()
> > (but that's too close to dsa_switch_for_each_bridge_member imho)
> > 
> > I was planning to have both, dsa_switch and dsa_bridge as parameters,
> > of course, limiting the scope to a single dsa_switch.
> 
> I'm not sure that we do need two iterators. Just
> dsa_switch_for_each_bridge_member() should be fine.

Just for convenience. In my case, all callers always have a reference
to 'struct dsa_bridge *', so instead of having the callers dereference
'struct net_device *' from that, have a macro that does it for me.
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Daniel Golle 1 week, 4 days ago
On Mon, Mar 23, 2026 at 06:31:04PM +0200, Vladimir Oltean wrote:
> On Mon, Mar 23, 2026 at 02:29:41AM +0000, Daniel Golle wrote:
> > I wasn't aware of the similar and equally named function in
> > yt921x.c[1]
> 
> Yeah, I did request from the beginning for it to be moved to
> include/net/dsa.h, but I didn't follow through with the request (I guess
> I forgot):
> https://lore.kernel.org/netdev/20250825212357.3acgen2qezuy533y@skbuf/
> 
> > 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.
> 
> Since all DSA drivers are all in the same folder, technically you may be
> excused if you just enable all those when working on infra, instead of
> allyesconfig.
> 
> > 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.
> 
> I don't like the dsa_bridge_for_each_member() name. You are likely
> not considering cross-chip bridging, where a bridge spans multiple
> dsa_switch structures. That is also a serious reason why your
> bridge->priv design is not viable (two switches can't lay their eggs
> in the same basket without overwriting each other).

That means the driver *does* have to track a mapping between DSA
bridges and hardware/firmware bridges on that specific switch somehow.

Or is there another existing structure in DSA I'm not aware of and
which could be used to implement Paolo's suggestion:

https://lore.kernel.org/netdev/fe46d64b-1b12-48b6-b663-e7d5122b7b8a@redhat.com/
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Vladimir Oltean 1 week, 4 days ago
On Mon, Mar 23, 2026 at 04:45:18PM +0000, Daniel Golle wrote:
> That means the driver *does* have to track a mapping between DSA
> bridges and hardware/firmware bridges on that specific switch somehow.

That's correct. From DSA's perspective, it's not an mxlbridge, it's just
a bridge with at least one DSA switch port under it, which is given a
kernel-wide identifier. The ports can hold a single reference to the
common bridge, but the common bridge cannot hold a single back-reference
to individual ports. And holding multiple references would severely
complicate the implementation.

Even if you don't implement accelerated cross-switch bridging, you can
still have two mxl ports belonging to different switches that are both
put by the user under the same bridge. And both switch driver instances
would want to allocate a potentially different bridge ID, and surely
maintain a different portmap, for that same bridge.

> Or is there another existing structure in DSA I'm not aware of and
> which could be used to implement Paolo's suggestion:
> 
> https://lore.kernel.org/netdev/fe46d64b-1b12-48b6-b663-e7d5122b7b8a@redhat.com/

The API was intended so that you could either use the bridge.num directly,
transform it through some linear formula or as an index into a privately
maintained array of data structures with switch-specific meaning.

I didn't question why you maintain a parallel list of dynamically
allocated mxlbridge structures instead of just having an array of
MXL862XX_MAX_BRIDGES * sizeof(u16) for the bridge identifiers, plus
maintain a separate portmap instead of walking through the DSA data
structures, but now that Paolo brought it up: why?

I see in v6 you're halfway there with the conversion, you got rid of the
portmap and you could just use the array for the rest.
Re: [PATCH net-next v6 2/4] net: dsa: add bridge member iteration macro and port mask helper
Posted by Daniel Golle 1 week, 4 days ago
On Mon, Mar 23, 2026 at 11:15:36PM +0200, Vladimir Oltean wrote:
> On Mon, Mar 23, 2026 at 04:45:18PM +0000, Daniel Golle wrote:
> > That means the driver *does* have to track a mapping between DSA
> > bridges and hardware/firmware bridges on that specific switch somehow.
> 
> That's correct. From DSA's perspective, it's not an mxlbridge, it's just
> a bridge with at least one DSA switch port under it, which is given a
> kernel-wide identifier. The ports can hold a single reference to the
> common bridge, but the common bridge cannot hold a single back-reference
> to individual ports. And holding multiple references would severely
> complicate the implementation.
> 
> Even if you don't implement accelerated cross-switch bridging, you can
> still have two mxl ports belonging to different switches that are both
> put by the user under the same bridge. And both switch driver instances
> would want to allocate a potentially different bridge ID, and surely
> maintain a different portmap, for that same bridge.
> 
> > Or is there another existing structure in DSA I'm not aware of and
> > which could be used to implement Paolo's suggestion:
> > 
> > https://lore.kernel.org/netdev/fe46d64b-1b12-48b6-b663-e7d5122b7b8a@redhat.com/
> 
> The API was intended so that you could either use the bridge.num directly,
> transform it through some linear formula or as an index into a privately
> maintained array of data structures with switch-specific meaning.
> 
> I didn't question why you maintain a parallel list of dynamically
> allocated mxlbridge structures instead of just having an array of
> MXL862XX_MAX_BRIDGES * sizeof(u16) for the bridge identifiers, plus
> maintain a separate portmap instead of walking through the DSA data
> structures, but now that Paolo brought it up: why?

The firmware requires bridges to be allocated, and the bridge
allocation firmware API returns the ID we got to use.

Maintaing a simple array ((ds->max_num_bridges + 1) * sizeof(u16))
to map DSA bridge num to firmware bridge ID in the driver works
fine, of course.

Regarding the request not to maintain a separate portmap for each
bridge (which was my initial approach) but instead walk through DSA
data:

My guess was the intention is to avoid duplciating data, as in: if
there is only one copy, we can be sure it's not stale or
out-of-sync...? But that's just my guess, only Paolo can tell his
reasons for having requested that.

> 
> I see in v6 you're halfway there with the conversion, you got rid of the
> portmap and you could just use the array for the rest.

Ack. I'll do that and post v7.