Skip to contentSkip to conversation

net: dsa: mxl862xx: add support for bridge offloading

PATCH Superseded Daniel Golle 3 participants 16 messages Mar 22 – Mar 25

Subsystems (4)

v6 of 9 Superseded Latest is v9 →

lore
Share & tools
lore

Daniel Golle

author maintainer
#0 lore raw

v6 cover net: dsa: mxl862xx: add support for bridge offloading

As a next step to complete the mxl862xx DSA driver, add support for offloading forwarding between bridged ports to the switch hardware.

This works pretty much without any big surprises, apart from two subtleties:
* per-port control over flooding behavior has to be implemented by (ab)using a 0-rate QoS meters as stopper in lack of any better option.
* STP state transition unconditionally enables learning on a port even if it was previously explicitely disabled (a firmware bug)

Note that as the driver is still lacking all VLAN features (which are going to be added next), at this point some of the bridge_vlan_aware.sh tests are failing after applying this series.

This is expected and cannot be avoided without implementing port_vlan_filtering + port_vlan_add/del. And adding both bridge and VLAN offloading at the same time would be too much for anyone to review, so VLAN support is going to be submitted in a follow-up series immediately after this series has been accepted.

All other relevant selftests (including bridge_vlan_unaware.sh) are still passing.

Inspired by the comments received from Paolo Abeni as reply to v5 the driver now no longer caches bridge port membership in the driver, but instead two small changes to DSA now allow it to easily iterate over bridge members, and store the firmware bridge ID in the driver-private void *priv added to struct dsa_bridge.

Changes since v5:
* add new DSA helpers to interate over bridge members
* add driver-private pointer to struct dsa_bridge
* eliminate struct mxl862xx_bridge and driver-private bridge list, store firmware bridge FID in new dsa_bridge->priv instead
* rework sync_bridge_members() to use dsa_bridge_for_each_member() instead of for_each_set_bit() on driver-private portmap
* rework port_bridge_join/leave to use dsa_bridge.priv for first- member detection and dsa_bridge_ports() for empty-bridge check
* derive active FID from dp->bridge->priv in set_bridge_port()
* simplify allocate_bridge()/free_bridge() to take struct dsa_bridge pointer directly, drop kzalloc/kfree/list management
* simplify get_fid() to read db.bridge.priv directly
* remove mxl862xx_find_bridge()
* remove unnecessary default bridge config call in setup()

Changes since v4:
* move link-local check before dsa_strip_etype_header()
* introduce port_map helpers
* properly implement port_mdb_{add,del} operations

Changes since v3:
* add missing cpu_to_le32 in mxl862xx_bridge_config_fwd()
* use little-endian 32-bit type for (unused) age_timer API field
* better comment in port_set_host_flood() documenting architectural limitation
* fix typo in comment "matche" should be "matches"
* few whitespace fixes

Changes since v2:
* refactor .port_bridge_join and .port_bridge_leave as requested by Vladimir Oltean
* include linux/etherdevice.h which was missing and causing build to fail (it accidentally slipped into a follow-up patch)
* remove left-over manual reset of learning state for port leaving bridge
* remove unnecessary call to mxl862xx_port_fast_age() for port leaving bridge
* add kernel-doc comments in mxl862xx.h instead of sporadic inline comments covering only some of the struct members
* some other minor cosmetics (linebreaks, whitespace) here and there

Changes since v1:
* don't set dsa_default_offload_fwd_mark() on link-local frames
* fix kernel-doc comments in API header
* use bitfield helpers for compound tci field in fdb API
* add missing endian conversion for mxl862xx_stp_port_cfg.port_state as well as mxl862xx_mac_table_read.tci (spotted by AI review)
* drop manually resetting port learning state on bridge<->standalone transitions, DSA framework takes care of that
* don't abort updating bridge ports on error, return error at the end
* report error in mxl862xx_port_bridge_leave()
* create mxl862xx_get_fid() helper and use it in mxl862xx_port_fdb_add() and mxl862xx_port_fdb_del()
* propagete error of callback function in mxl862xx_port_fdb_dump()
* manually mxl862xx_port_fast_age() in mxl862xx_port_stp_state_set() to avoid FDB poisoning due to race condition

Daniel Golle (4):
net: dsa: add driver-private pointer to struct dsa_bridge
net: dsa: add bridge member iteration macro and port mask helper
dsa: tag_mxl862xx: set dsa_default_offload_fwd_mark()
net: dsa: mxl862xx: implement bridge offloading

 drivers/net/dsa/mxl862xx/mxl862xx-api.h | 225 ++++++++-
 drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |  20 +-
 drivers/net/dsa/mxl862xx/mxl862xx.c     | 617 ++++++++++++++++++++++--
 drivers/net/dsa/mxl862xx/mxl862xx.h     | 103 ++++
 include/net/dsa.h                       |  17 +
 net/dsa/tag_mxl862xx.c                  |   3 +
 6 files changed, 951 insertions(+), 34 deletions(-)
Signature · 1 line
2.53.0
author maintainer
#1 lore raw

PATCH v6 1/4 net: dsa: add driver-private pointer to struct dsa_bridge

When a DSA driver offloads a bridge to firmware, it typically receives a firmware-assigned bridge identifier (e.g. a FID) that must be stored and retrieved by subsequent operations. Without a place to store this in the DSA core's bridge structure, drivers must maintain a parallel list of bridge objects and search it on every join, leave, and FDB operation.

Add a void *priv field to struct dsa_bridge so drivers can store their firmware bridge identifier directly, eliminating the need for driver-side bridge tracking structures.

---
v6: new patch

 include/net/dsa.h | 1 +
 1 file changed, 1 insertion(+)
include/net/dsa.h +1 -0
index 6c17446f3dcc2..1c6f6c3b88e86 100644
@@ -234,6 +234,7 @@ struct dsa_bridge {
 	unsigned int num;
 	bool tx_fwd_offload;
 	refcount_t refcount;
+	void *priv;
 };
 
 struct dsa_port {
Signature · 1 line
2.53.0
maintainer
#2 lore raw

Re: [PATCH net-next v6 1/4] net: dsa: add driver-private pointer to struct dsa_bridge

Quoted 5 lines · Daniel Golle

When a DSA driver offloads a bridge to firmware, it typically receives a firmware-assigned bridge identifier (e.g. a FID) that must be stored and retrieved by subsequent operations. Without a place to store this in the DSA core's bridge structure, drivers must maintain a parallel list of bridge objects and search it on every join, leave, and FDB operation.

Why list?

What's wrong with a driver-level array for lookup? The bridge.num is guaranteed to be between 1 and ds->max_num_bridges.

author maintainer
#3 lore raw

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

In reply to Daniel Golle

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.

---
v6: new patch

 include/net/dsa.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/net/dsa.h +16 -0
index 1c6f6c3b88e86..4f43d518f3de3 100644
@@ -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 {
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

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

Quoted 16 lines · Daniel Golle

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

include/net/dsa.h +0 -0
index 1c6f6c3b88e86..4f43d518f3de3 100644

include/net/dsa.h static inline bool dsa_port_tree_same(const struct dsa_port *a, · line 847

Quoted 10 lines
include/net/dsa.h +7 -0
@@ -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:

include/net/dsa.h +9 -3
index b43fa7a708c72..c10f05f3e96ed 100644
@@ -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.

maintainer
#5 lore raw

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

Quoted 2 lines · Daniel Golle

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/

Quoted 3 lines

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.

Quoted 4 lines

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.

Quoted 8 lines

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

author maintainer
#6 lore raw

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

Quoted 30 lines · Vladimir Oltean
Quoted 2 lines · Daniel Golle

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/

Quoted 3 lines

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.

Quoted 4 lines

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.

Quoted 8 lines

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.

Quoted 5 lines

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/[email protected]/

maintainer
#7 lore raw

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

Quoted 2 lines · Daniel Golle

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.

Quoted 4 lines

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/[email protected]/

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.

author maintainer
#8 lore raw

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

Quoted 26 lines · Vladimir Oltean
Quoted 2 lines · Daniel Golle

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.

Quoted 4 lines

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/[email protected]/

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.

Quoted 5 lines

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.

Quoted 3 lines

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.

author maintainer
#9 lore raw

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

In reply to Vladimir Oltean
Quoted 10 lines · Vladimir Oltean
Quoted 3 lines · Daniel Golle

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.

maintainer
#10 lore raw

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

Quoted 12 lines · Daniel Golle
Quoted 10 lines · Vladimir Oltean
Quoted 3 lines · Daniel Golle

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

Quoted 7 lines

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.

author maintainer
#11 lore raw

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

Quoted 15 lines · Vladimir Oltean
Quoted 14 lines · Daniel Golle
Quoted 10 lines · Vladimir Oltean
Quoted 3 lines · Daniel Golle

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() ?

Quoted 8 lines
Quoted 5 lines

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.

#12 lore raw

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

In reply to Daniel Golle
kernel test robot noticed the following build errors:

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/[email protected]/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/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

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  
Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#13 lore raw

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

In reply to Daniel Golle
kernel test robot noticed the following build errors:

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/[email protected]/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/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

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  
Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
author maintainer
#14 lore raw

PATCH v6 3/4 dsa: tag_mxl862xx: set dsa_default_offload_fwd_mark()

In reply to Daniel Golle

The MxL862xx offloads bridge forwarding in hardware, so set dsa_default_offload_fwd_mark() to avoid duplicate forwarding of packets of (eg. flooded) frames arriving at the CPU port.

Link-local frames are directly trapped to the CPU port only, so don't set dsa_default_offload_fwd_mark() on those.

---
v6: no changes
v5: move link-local check before dsa_strip_etype_header()
v4: no changes
v3: no changes
v2: don't set dsa_default_offload_fwd_mark() on link-local frames

---
 net/dsa/tag_mxl862xx.c | 3 +++
 1 file changed, 3 insertions(+)
net/dsa/tag_mxl862xx.c +3 -0
index 01f2158682718..8daefeb8d49df 100644
@@ -86,6 +86,9 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
 		return NULL;
 	}
 
+	if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest)))
+		dsa_default_offload_fwd_mark(skb);
+
 	/* remove the MxL862xx special tag between the MAC addresses and the
 	 * current ethertype field.
 	 */
Signature · 1 line
2.53.0
author maintainer
#15 lore raw

PATCH v6 4/4 net: dsa: mxl862xx: implement bridge offloading

In reply to Daniel Golle

Implement joining and leaving bridges as well as add, delete and dump operations on isolated FDBs, port MDB membership management, and setting a port's STP state.

The switch supports a maximum of 63 bridges, however, up to 12 may be used as "single-port bridges" to isolate standalone ports. Allowing up to 48 bridges to be offloaded seems more than enough on that hardware, hence that is set as max_num_bridges.

A total of 128 bridge ports are supported in the bridge portmap, and virtual bridge ports have to be used eg. for link-aggregation, hence potentially exceeding the number of hardware ports.

The firmware-assigned bridge identifier (FID) for each offloaded bridge is stored in dsa_bridge.priv, avoiding the need for a driver-private bridge tracking structure. Bridge member portmaps are rebuilt on join/leave using dsa_bridge_for_each_member().

As there are now more users of the BRIDGEPORT_CONFIG_SET API and the state of each port is cached locally, introduce a helper function mxl862xx_set_bridge_port(struct dsa_switch *ds, int port) which is then used to replace the direct calls to the API in mxl862xx_setup_cpu_bridge() and mxl862xx_add_single_port_bridge().

Note that there is no convenient way to control flooding on per-port level, so the driver is using a 0-rate QoS meter setup as a stopper in lack of any better option. This works, but allows a single 64-byte packet to pass once after reset. While this limitation doesn't seem to be a problem in practice, it has the effect that the bridge_vlan_unaware.sh selftest only passes the FDB test the 2nd time the test is run after boot (and any subsequent time after that, of course).

---
v6:
* eliminate struct mxl862xx_bridge and driver-private bridge list, store firmware bridge FID in new dsa_bridge->priv instead
* rework sync_bridge_members() to use dsa_bridge_for_each_member() instead of for_each_set_bit() on driver-private portmap
* rework port_bridge_join/leave to use dsa_bridge.priv for first- member detection and dsa_bridge_ports() for empty-bridge check
* derive active FID from dp->bridge->priv in set_bridge_port()
* simplify allocate_bridge()/free_bridge() to take struct dsa_bridge pointer directly, drop kzalloc/kfree/list management
* simplify get_fid() to read db.bridge.priv directly
* remove mxl862xx_find_bridge()
* remove unnecessary default bridge config call in setup()

v5:
* introduce port_map helpers
* properly implement port_mdb_{add,del} operations

v4:
* add missing cpu_to_le32 in mxl862xx_bridge_config_fwd()
* use little-endian 32-bit type for (unused) age_timer API field
* better comment in port_set_host_flood() documenting architectural limitation
* fix typo in comment "matche" should be "matches"
* few whitespace fixes

v3:
* refactor .port_bridge_join and .port_bridge_leave as requested by Vladimir Oltean
* include linux/etherdevice.h which was missing and causing build to fail (it accidentally slipped into a follow-up patch)
* remove left-over manual reset of learning state for port leaving bridge
* remove unnecessary call to mxl862xx_port_fast_age() for port leaving bridge
* add kernel-doc comments in mxl862xx.h instead of sporadic inline comments covering only some of the struct members
* some other minor cosmetics (linebreaks, whitespace) here and there

v2:
* fix kernel-doc comments in API header
* use bitfield helpers for compound tci field in fdb API
* add missing endian conversion for mxl862xx_stp_port_cfg.port_state as well as mxl862xx_mac_table_read.tci (spotted by AI review)
* drop manually resetting port learning state on bridge<->standalone transitions, DSA framework takes care of that
* don't abort updating bridge ports on error, return error at the end
* report error in mxl862xx_port_bridge_leave()
* create mxl862xx_get_fid() helper and use it in mxl862xx_port_fdb_add() and mxl862xx_port_fdb_del()
* propagete error of callback function in mxl862xx_port_fdb_dump()
* manually mxl862xx_port_fast_age() in mxl862xx_port_stp_state_set() to avoid FDB poisoning due to race condition

---
 drivers/net/dsa/mxl862xx/mxl862xx-api.h | 225 ++++++++-
 drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |  20 +-
 drivers/net/dsa/mxl862xx/mxl862xx.c     | 617 ++++++++++++++++++++++--
 drivers/net/dsa/mxl862xx/mxl862xx.h     | 103 ++++
 4 files changed, 931 insertions(+), 34 deletions(-)
drivers/net/dsa/mxl862xx/mxl862xx-api.h +224 -1
index a9f599dbca25b..8677763544d78 100644
@@ -3,6 +3,7 @@
 #ifndef __MXL862XX_API_H
 #define __MXL862XX_API_H
 
+#include <linux/bits.h>
 #include <linux/if_ether.h>
 
 /**
@@ -34,6 +35,168 @@ struct mxl862xx_register_mod {
 	__le16 mask;
 } __packed;
 
+/**
+ * enum mxl862xx_mac_table_filter - Source/Destination MAC address filtering
+ *
+ * @MXL862XX_MAC_FILTER_NONE: no filter
+ * @MXL862XX_MAC_FILTER_SRC: source address filter
+ * @MXL862XX_MAC_FILTER_DEST: destination address filter
+ * @MXL862XX_MAC_FILTER_BOTH: both source and destination filter
+ */
+enum mxl862xx_mac_table_filter {
+	MXL862XX_MAC_FILTER_NONE = 0,
+	MXL862XX_MAC_FILTER_SRC = BIT(0),
+	MXL862XX_MAC_FILTER_DEST = BIT(1),
+	MXL862XX_MAC_FILTER_BOTH = BIT(0) | BIT(1),
+};
+
+#define MXL862XX_TCI_VLAN_ID		GENMASK(11, 0)
+#define MXL862XX_TCI_VLAN_CFI_DEI	BIT(12)
+#define MXL862XX_TCI_VLAN_PRI		GENMASK(15, 13)
+
+/* Set in port_id to use port_map[] as a portmap bitmap instead of a single
+ * port ID. When clear, port_id selects one port; when set, the firmware
+ * ignores the lower bits of port_id and writes port_map[] directly into
+ * the PCE bridge port map.
+ */
+#define MXL862XX_PORTMAP_FLAG		BIT(31)
+
+/**
+ * struct mxl862xx_mac_table_add - MAC Table Entry to be added
+ * @fid: Filtering Identifier (FID) (not supported by all switches)
+ * @port_id: Ethernet Port number
+ * @port_map: Bridge Port Map
+ * @sub_if_id: Sub-Interface Identifier Destination
+ * @age_timer: Aging Time in seconds
+ * @vlan_id: STAG VLAN Id
+ * @static_entry: Static Entry (value will be aged out if not set to static)
+ * @traffic_class: Egress queue traffic class
+ * @mac: MAC Address to add to the table
+ * @filter_flag: See &enum mxl862xx_mac_table_filter
+ * @igmp_controlled: Packet is marked as IGMP controlled if destination MAC
+ *                   address matches MAC in this entry
+ * @associated_mac: Associated Mac address
+ * @tci: TCI for B-Step
+ *	Bit [0:11] - VLAN ID
+ *	Bit [12] - VLAN CFI/DEI
+ *	Bit [13:15] - VLAN PRI
+ */
+struct mxl862xx_mac_table_add {
+	__le16 fid;
+	__le32 port_id;
+	__le16 port_map[8];
+	__le16 sub_if_id;
+	__le32 age_timer;
+	__le16 vlan_id;
+	u8 static_entry;
+	u8 traffic_class;
+	u8 mac[ETH_ALEN];
+	u8 filter_flag;
+	u8 igmp_controlled;
+	u8 associated_mac[ETH_ALEN];
+	__le16 tci;
+} __packed;
+
+/**
+ * struct mxl862xx_mac_table_remove - MAC Table Entry to be removed
+ * @fid: Filtering Identifier (FID)
+ * @mac: MAC Address to be removed from the table.
+ * @filter_flag: See &enum mxl862xx_mac_table_filter
+ * @tci: TCI for B-Step
+ *	Bit [0:11] - VLAN ID
+ *	Bit [12] - VLAN CFI/DEI
+ *	Bit [13:15] - VLAN PRI
+ */
+struct mxl862xx_mac_table_remove {
+	__le16 fid;
+	u8 mac[ETH_ALEN];
+	u8 filter_flag;
+	__le16 tci;
+} __packed;
+
+/**
+ * struct mxl862xx_mac_table_read - MAC Table Entry to be read
+ * @initial: Restart the get operation from the beginning of the table
+ * @last: Indicates that the read operation returned last entry
+ * @fid: Get the MAC table entry belonging to the given Filtering Identifier
+ * @port_id: The Bridge Port ID
+ * @port_map: Bridge Port Map
+ * @age_timer: Aging Time
+ * @vlan_id: STAG VLAN Id
+ * @static_entry: Indicates if this is a Static Entry
+ * @sub_if_id: Sub-Interface Identifier Destination
+ * @mac: MAC Address. Filled out by the switch API implementation.
+ * @filter_flag: See &enum mxl862xx_mac_table_filter
+ * @igmp_controlled: Packet is marked as IGMP controlled if destination MAC
+ *                   address matches the MAC in this entry
+ * @entry_changed: Indicate if the Entry has Changed
+ * @associated_mac: Associated MAC address
+ * @hit_status: MAC Table Hit Status Update
+ * @tci: TCI for B-Step
+ *	Bit [0:11] - VLAN ID
+ *	Bit [12] - VLAN CFI/DEI
+ *	Bit [13:15] - VLAN PRI
+ * @first_bridge_port_id: The port this MAC address has first been learned.
+ *                        This is used for loop detection.
+ */
+struct mxl862xx_mac_table_read {
+	u8 initial;
+	u8 last;
+	__le16 fid;
+	__le32 port_id;
+	__le16 port_map[8];
+	__le32 age_timer;
+	__le16 vlan_id;
+	u8 static_entry;
+	__le16 sub_if_id;
+	u8 mac[ETH_ALEN];
+	u8 filter_flag;
+	u8 igmp_controlled;
+	u8 entry_changed;
+	u8 associated_mac[ETH_ALEN];
+	u8 hit_status;
+	__le16 tci;
+	__le16 first_bridge_port_id;
+} __packed;
+
+/**
+ * struct mxl862xx_mac_table_query - MAC Table Entry key-based lookup
+ * @mac: MAC Address to search for (input)
+ * @fid: Filtering Identifier (input)
+ * @found: Set by firmware: 1 if entry was found, 0 if not
+ * @port_id: Bridge Port ID (output; MSB set if portmap mode)
+ * @port_map: Bridge Port Map (output; valid for static entries)
+ * @sub_if_id: Sub-Interface Identifier Destination
+ * @age_timer: Aging Time
+ * @vlan_id: STAG VLAN Id
+ * @static_entry: Indicates if this is a Static Entry
+ * @filter_flag: See &enum mxl862xx_mac_table_filter (input+output)
+ * @igmp_controlled: IGMP controlled flag
+ * @entry_changed: Entry changed flag
+ * @associated_mac: Associated MAC address
+ * @hit_status: MAC Table Hit Status Update
+ * @tci: TCI (VLAN ID + CFI/DEI + PRI) (input)
+ * @first_bridge_port_id: First learned bridge port
+ */
+struct mxl862xx_mac_table_query {
+	u8 mac[ETH_ALEN];
+	__le16 fid;
+	u8 found;
+	__le32 port_id;
+	__le16 port_map[8];
+	__le16 sub_if_id;
+	__le32 age_timer;
+	__le16 vlan_id;
+	u8 static_entry;
+	u8 filter_flag;
+	u8 igmp_controlled;
+	u8 entry_changed;
+	u8 associated_mac[ETH_ALEN];
+	u8 hit_status;
+	__le16 tci;
+	__le16 first_bridge_port_id;
+} __packed;
+
 /**
  * enum mxl862xx_mac_clear_type - MAC table clear type
  * @MXL862XX_MAC_CLEAR_PHY_PORT: clear dynamic entries based on port_id
@@ -138,6 +301,40 @@ enum mxl862xx_bridge_port_egress_meter {
 	MXL862XX_BRIDGE_PORT_EGRESS_METER_MAX,
 };
 
+/**
+ * struct mxl862xx_qos_meter_cfg - Rate meter configuration
+ * @enable: Enable/disable meter
+ * @meter_id: Meter ID (assigned by firmware on alloc)
+ * @meter_name: Meter name string
+ * @meter_type: Meter algorithm type (srTCM = 0, trTCM = 1)
+ * @cbs: Committed Burst Size (in bytes)
+ * @res1: Reserved
+ * @ebs: Excess Burst Size (in bytes)
+ * @res2: Reserved
+ * @rate: Committed Information Rate (in kbit/s)
+ * @pi_rate: Peak Information Rate (in kbit/s)
+ * @colour_blind_mode: Colour-blind mode enable
+ * @pkt_mode: Packet mode enable
+ * @local_overhd: Local overhead accounting enable
+ * @local_overhd_val: Local overhead accounting value
+ */
+struct mxl862xx_qos_meter_cfg {
+	u8 enable;
+	__le16 meter_id;
+	char meter_name[32];
+	__le32 meter_type;
+	__le32 cbs;
+	__le32 res1;
+	__le32 ebs;
+	__le32 res2;
+	__le32 rate;
+	__le32 pi_rate;
+	u8 colour_blind_mode;
+	u8 pkt_mode;
+	u8 local_overhd;
+	__le16 local_overhd_val;
+} __packed;
+
 /**
  * enum mxl862xx_bridge_forward_mode - Bridge forwarding type of packet
  * @MXL862XX_BRIDGE_FORWARD_FLOOD: Packet is flooded to port members of
@@ -456,7 +653,7 @@ struct mxl862xx_pmapper {
  */
 struct mxl862xx_bridge_port_config {
 	__le16 bridge_port_id;
-	__le32 mask; /* enum mxl862xx_bridge_port_config_mask  */
+	__le32 mask; /* enum mxl862xx_bridge_port_config_mask */
 	__le16 bridge_id;
 	u8 ingress_extended_vlan_enable;
 	__le16 ingress_extended_vlan_block_id;
@@ -658,6 +855,32 @@ struct mxl862xx_ctp_port_assignment {
 	__le16 bridge_port_id;
 } __packed;
 
+/**
+ * enum mxl862xx_stp_port_state - Spanning Tree Protocol port states
+ * @MXL862XX_STP_PORT_STATE_FORWARD: Forwarding state
+ * @MXL862XX_STP_PORT_STATE_DISABLE: Disabled/Discarding state
+ * @MXL862XX_STP_PORT_STATE_LEARNING: Learning state
+ * @MXL862XX_STP_PORT_STATE_BLOCKING: Blocking/Listening
+ */
+enum mxl862xx_stp_port_state {
+	MXL862XX_STP_PORT_STATE_FORWARD = 0,
+	MXL862XX_STP_PORT_STATE_DISABLE,
+	MXL862XX_STP_PORT_STATE_LEARNING,
+	MXL862XX_STP_PORT_STATE_BLOCKING,
+};
+
+/**
+ * struct mxl862xx_stp_port_cfg - Configures the Spanning Tree Protocol state
+ * @port_id: Port number
+ * @fid: Filtering Identifier (FID)
+ * @port_state: See &enum mxl862xx_stp_port_state
+ */
+struct mxl862xx_stp_port_cfg {
+	__le16 port_id;
+	__le16 fid;
+	__le32 port_state; /* enum mxl862xx_stp_port_state */
+} __packed;
+
 /**
  * struct mxl862xx_sys_fw_image_version - Firmware version information
  * @iv_major: firmware major version
drivers/net/dsa/mxl862xx/mxl862xx-cmd.h +16 -4
index f6852ade64e7c..9f6c5bf9fdf21 100644
@@ -15,12 +15,15 @@
 #define MXL862XX_BRDG_MAGIC		0x300
 #define MXL862XX_BRDGPORT_MAGIC		0x400
 #define MXL862XX_CTP_MAGIC		0x500
+#define MXL862XX_QOS_MAGIC		0x600
 #define MXL862XX_SWMAC_MAGIC		0xa00
+#define MXL862XX_STP_MAGIC		0xf00
 #define MXL862XX_SS_MAGIC		0x1600
 #define GPY_GPY2XX_MAGIC		0x1800
 #define SYS_MISC_MAGIC			0x1900
 
 #define MXL862XX_COMMON_CFGGET		(MXL862XX_COMMON_MAGIC + 0x9)
+#define MXL862XX_COMMON_CFGSET		(MXL862XX_COMMON_MAGIC + 0xa)
 #define MXL862XX_COMMON_REGISTERMOD	(MXL862XX_COMMON_MAGIC + 0x11)
 
 #define MXL862XX_BRIDGE_ALLOC		(MXL862XX_BRDG_MAGIC + 0x1)
@@ -35,14 +38,23 @@
 
 #define MXL862XX_CTP_PORTASSIGNMENTSET	(MXL862XX_CTP_MAGIC + 0x3)
 
+#define MXL862XX_QOS_METERCFGSET	(MXL862XX_QOS_MAGIC + 0x2)
+#define MXL862XX_QOS_METERALLOC		(MXL862XX_QOS_MAGIC + 0x2a)
+
+#define MXL862XX_MAC_TABLEENTRYADD	(MXL862XX_SWMAC_MAGIC + 0x2)
+#define MXL862XX_MAC_TABLEENTRYREAD	(MXL862XX_SWMAC_MAGIC + 0x3)
+#define MXL862XX_MAC_TABLEENTRYQUERY	(MXL862XX_SWMAC_MAGIC + 0x4)
+#define MXL862XX_MAC_TABLEENTRYREMOVE	(MXL862XX_SWMAC_MAGIC + 0x5)
 #define MXL862XX_MAC_TABLECLEARCOND	(MXL862XX_SWMAC_MAGIC + 0x8)
 
-#define MXL862XX_SS_SPTAG_SET		(MXL862XX_SS_MAGIC + 0x02)
+#define MXL862XX_SS_SPTAG_SET		(MXL862XX_SS_MAGIC + 0x2)
+
+#define MXL862XX_STP_PORTCFGSET		(MXL862XX_STP_MAGIC + 0x2)
 
-#define INT_GPHY_READ			(GPY_GPY2XX_MAGIC + 0x01)
-#define INT_GPHY_WRITE			(GPY_GPY2XX_MAGIC + 0x02)
+#define INT_GPHY_READ			(GPY_GPY2XX_MAGIC + 0x1)
+#define INT_GPHY_WRITE			(GPY_GPY2XX_MAGIC + 0x2)
 
-#define SYS_MISC_FW_VERSION		(SYS_MISC_MAGIC + 0x02)
+#define SYS_MISC_FW_VERSION		(SYS_MISC_MAGIC + 0x2)
 
 #define MMD_API_MAXIMUM_ID		0x7fff
 
drivers/net/dsa/mxl862xx/mxl862xx.c +588 -29

696 lines not on this page · raw message

drivers/net/dsa/mxl862xx/mxl862xx.h +103 -0

113 lines not on this page · raw message

Signature · 1 line
2.53.0