Просмотр исходного кода

kernel: update MxL862xx DSA driver

Introduce fix which prevents the kernel from crashing in case the mxl862xx
driver fails to probe due to outdated firmware running on the switch.
Cancel all pending work and prevent rescheduling of counter polling in case
the driver errors out during probe.

Signed-off-by: Daniel Golle <[email protected]>
Daniel Golle 1 неделя назад
Родитель
Сommit
5ee6ddb461
54 измененных файлов с 735 добавлено и 763 удалено
  1. 37 0
      target/linux/generic/pending-6.12/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch
  2. 2 2
      target/linux/generic/pending-6.12/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch
  3. 2 2
      target/linux/generic/pending-6.12/760-02-net-dsa-add-bridge-member-iteration-macro.patch
  4. 2 2
      target/linux/generic/pending-6.12/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch
  5. 34 37
      target/linux/generic/pending-6.12/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch
  6. 17 106
      target/linux/generic/pending-6.12/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch
  7. 4 4
      target/linux/generic/pending-6.12/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch
  8. 100 22
      target/linux/generic/pending-6.12/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch
  9. 11 11
      target/linux/generic/pending-6.12/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch
  10. 4 4
      target/linux/generic/pending-6.12/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch
  11. 2 2
      target/linux/generic/pending-6.12/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch
  12. 7 7
      target/linux/generic/pending-6.12/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch
  13. 5 5
      target/linux/generic/pending-6.12/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch
  14. 3 3
      target/linux/generic/pending-6.12/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch
  15. 3 3
      target/linux/generic/pending-6.12/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch
  16. 3 3
      target/linux/generic/pending-6.12/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch
  17. 66 102
      target/linux/generic/pending-6.12/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch
  18. 16 16
      target/linux/generic/pending-6.12/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch
  19. 7 7
      target/linux/generic/pending-6.12/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch
  20. 3 3
      target/linux/generic/pending-6.12/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch
  21. 2 2
      target/linux/generic/pending-6.12/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch
  22. 4 4
      target/linux/generic/pending-6.12/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch
  23. 4 4
      target/linux/generic/pending-6.12/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch
  24. 18 19
      target/linux/generic/pending-6.12/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch
  25. 6 6
      target/linux/generic/pending-6.12/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch
  26. 3 3
      target/linux/generic/pending-6.12/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch
  27. 2 2
      target/linux/generic/pending-6.12/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch
  28. 37 0
      target/linux/generic/pending-6.18/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch
  29. 3 3
      target/linux/generic/pending-6.18/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch
  30. 2 2
      target/linux/generic/pending-6.18/760-02-net-dsa-add-bridge-member-iteration-macro.patch
  31. 2 2
      target/linux/generic/pending-6.18/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch
  32. 34 37
      target/linux/generic/pending-6.18/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch
  33. 17 106
      target/linux/generic/pending-6.18/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch
  34. 4 4
      target/linux/generic/pending-6.18/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch
  35. 100 22
      target/linux/generic/pending-6.18/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch
  36. 11 11
      target/linux/generic/pending-6.18/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch
  37. 4 4
      target/linux/generic/pending-6.18/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch
  38. 2 2
      target/linux/generic/pending-6.18/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch
  39. 7 7
      target/linux/generic/pending-6.18/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch
  40. 5 5
      target/linux/generic/pending-6.18/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch
  41. 3 3
      target/linux/generic/pending-6.18/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch
  42. 3 3
      target/linux/generic/pending-6.18/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch
  43. 3 3
      target/linux/generic/pending-6.18/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch
  44. 66 102
      target/linux/generic/pending-6.18/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch
  45. 16 16
      target/linux/generic/pending-6.18/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch
  46. 7 7
      target/linux/generic/pending-6.18/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch
  47. 3 3
      target/linux/generic/pending-6.18/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch
  48. 2 2
      target/linux/generic/pending-6.18/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch
  49. 4 4
      target/linux/generic/pending-6.18/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch
  50. 4 4
      target/linux/generic/pending-6.18/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch
  51. 18 19
      target/linux/generic/pending-6.18/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch
  52. 6 6
      target/linux/generic/pending-6.18/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch
  53. 3 3
      target/linux/generic/pending-6.18/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch
  54. 2 2
      target/linux/generic/pending-6.18/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch

+ 37 - 0
target/linux/generic/pending-6.12/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch

@@ -0,0 +1,37 @@
+From 3fd163f5bb88de426ca9847549f94b4296170ef0 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Mon, 30 Mar 2026 23:40:53 +0100
+Subject: [PATCH] net: dsa: mxl862xx: cancel pending work on probe error
+
+Call mxl862xx_host_shutdown() in case dsa_register_switch() returns
+an error, so any still pending crc_err_work get canceled.
+
+Fixes: a319d0c8c8ced ("net: dsa: mxl862xx: add CRC for MDIO communication)"
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ drivers/net/dsa/mxl862xx/mxl862xx.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/dsa/mxl862xx/mxl862xx.c
++++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
+@@ -407,6 +407,7 @@ static int mxl862xx_probe(struct mdio_de
+ 	struct device *dev = &mdiodev->dev;
+ 	struct mxl862xx_priv *priv;
+ 	struct dsa_switch *ds;
++	int err;
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv)
+@@ -428,7 +429,11 @@ static int mxl862xx_probe(struct mdio_de
+ 
+ 	dev_set_drvdata(dev, ds);
+ 
+-	return dsa_register_switch(ds);
++	err = dsa_register_switch(ds);
++	if (err)
++		mxl862xx_host_shutdown(priv);
++
++	return err;
+ }
+ 
+ static void mxl862xx_remove(struct mdio_device *mdiodev)

+ 2 - 2
target/linux/generic/pending-6.12/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch

@@ -1,7 +1,7 @@
-From de6dd19a3edd1dc6400fecf77610e438441a02ac Mon Sep 17 00:00:00 2001
+From cd698f1ae94c16499e2714b31dd6048e6f9f068d Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:54:11 +0000
-Subject: [PATCH 10/35] net: dsa: move dsa_bridge_ports() helper to dsa.h
+Subject: [PATCH 01/26] net: dsa: move dsa_bridge_ports() helper to dsa.h
 
 The yt921x driver contains a helper to create a bitmap of ports
 which are members of a bridge.

+ 2 - 2
target/linux/generic/pending-6.12/760-02-net-dsa-add-bridge-member-iteration-macro.patch

@@ -1,7 +1,7 @@
-From 880cde7abf58cb1316382ae7f59aac93c313e8fe Mon Sep 17 00:00:00 2001
+From c161533e1605a7282563c139323a3913890fdb72 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:54:41 +0000
-Subject: [PATCH 11/35] net: dsa: add bridge member iteration macro
+Subject: [PATCH 02/26] net: dsa: add bridge member iteration macro
 
 Drivers that offload bridges need to iterate over the ports that are
 members of a given bridge, for example to rebuild per-port forwarding

+ 2 - 2
target/linux/generic/pending-6.12/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch

@@ -1,7 +1,7 @@
-From 149bb02d5bf031a1eb85f91377f54913de3a08ff Mon Sep 17 00:00:00 2001
+From 753efe27a9afee52c4ad42098a9b9278366d63cc Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:54:52 +0000
-Subject: [PATCH 12/35] dsa: tag_mxl862xx: set dsa_default_offload_fwd_mark()
+Subject: [PATCH 03/26] dsa: tag_mxl862xx: set dsa_default_offload_fwd_mark()
 
 The MxL862xx offloads bridge forwarding in hardware, so set
 dsa_default_offload_fwd_mark() to avoid duplicate forwarding of

+ 34 - 37
target/linux/generic/pending-6.12/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch

@@ -1,7 +1,7 @@
-From 5acdee6df2fbd4a9b02045694227f25cb1d4e5e0 Mon Sep 17 00:00:00 2001
+From ce0664ff8f75c3ab01101c3f0f8569924d948775 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:55:08 +0000
-Subject: [PATCH 13/35] net: dsa: mxl862xx: implement bridge offloading
+Subject: [PATCH 04/26] net: dsa: mxl862xx: implement bridge offloading
 
 Implement joining and leaving bridges as well as add, delete and dump
 operations on isolated FDBs, port MDB membership management, and
@@ -39,9 +39,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 ---
  drivers/net/dsa/mxl862xx/mxl862xx-api.h | 225 ++++++-
  drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |  20 +-
- drivers/net/dsa/mxl862xx/mxl862xx.c     | 752 ++++++++++++++++++++++--
+ drivers/net/dsa/mxl862xx/mxl862xx.c     | 743 ++++++++++++++++++++++--
  drivers/net/dsa/mxl862xx/mxl862xx.h     | 133 +++++
- 4 files changed, 1087 insertions(+), 43 deletions(-)
+ 4 files changed, 1076 insertions(+), 45 deletions(-)
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx-api.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx-api.h
@@ -384,7 +384,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static enum dsa_tag_protocol mxl862xx_get_tag_protocol(struct dsa_switch *ds,
  						       int port,
  						       enum dsa_tag_protocol m)
-@@ -168,6 +182,225 @@ static int mxl862xx_setup_mdio(struct ds
+@@ -168,6 +182,213 @@ static int mxl862xx_setup_mdio(struct ds
  	return ret;
  }
  
@@ -535,18 +535,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return ret;
 +}
 +
-+/**
-+ * mxl862xx_allocate_bridge - Allocate a firmware bridge instance
-+ * @priv: driver private data
-+ * @bridge_id: output -- firmware bridge ID assigned by the firmware
-+ *
-+ * Newly allocated bridges default to flooding all traffic classes
-+ * (unknown unicast, multicast, broadcast).  Callers that need
-+ * different forwarding behavior must call mxl862xx_bridge_config_fwd()
-+ * after allocation.
-+ *
-+ * Return: 0 on success, negative errno on failure.
-+ */
 +static int mxl862xx_allocate_bridge(struct mxl862xx_priv *priv, u16 *bridge_id)
 +{
 +	struct mxl862xx_bridge_alloc br_alloc = {};
@@ -610,7 +598,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_setup(struct dsa_switch *ds)
  {
  	struct mxl862xx_priv *priv = ds->priv;
-@@ -181,6 +414,10 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -181,6 +402,10 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -621,7 +609,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return mxl862xx_setup_mdio(ds);
  }
  
-@@ -260,66 +497,87 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -260,66 +485,87 @@ static int mxl862xx_configure_sp_tag_pro
  
  static int mxl862xx_setup_cpu_bridge(struct dsa_switch *ds, int port)
  {
@@ -744,7 +732,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	struct dsa_port *dp = dsa_to_port(ds, port);
  	bool is_cpu_port = dsa_port_is_cpu(dp);
  	int ret;
-@@ -352,7 +610,31 @@ static int mxl862xx_port_setup(struct ds
+@@ -352,7 +598,31 @@ static int mxl862xx_port_setup(struct ds
  		return mxl862xx_setup_cpu_bridge(ds, port);
  
  	/* setup single-port bridge for user ports */
@@ -777,7 +765,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static void mxl862xx_phylink_get_caps(struct dsa_switch *ds, int port,
-@@ -365,14 +647,385 @@ static void mxl862xx_phylink_get_caps(st
+@@ -365,14 +635,383 @@ static void mxl862xx_phylink_get_caps(st
  		  config->supported_interfaces);
  }
  
@@ -942,7 +930,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	mxl862xx_fw_portmap_clear_bit(qparam.port_map, port);
 +
 +	if (mxl862xx_fw_portmap_is_empty(qparam.port_map)) {
-+		/* No ports left  remove the entry entirely */
++		/* No ports left -- remove the entry entirely */
 +		rparam.fid = cpu_to_le16(fid);
 +		rparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
 +		ether_addr_copy(rparam.mac, mdb->addr);
@@ -1033,7 +1021,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +/* Deferred work handler for host flood configuration.
 + *
 + * port_set_host_flood is called from atomic context (under
-+ * netif_addr_lock), so firmware calls must be deferred.  The worker
++ * netif_addr_lock), so firmware calls must be deferred. The worker
 + * acquires rtnl_lock() to serialize with DSA callbacks that access the
 + * same driver state.
 + */
@@ -1058,9 +1046,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	mc = p->host_flood_mc;
 +
 +	/* The hardware controls unknown-unicast/multicast forwarding per FID
-+	 * (bridge), not per source port.  For bridged ports all members share
++	 * (bridge), not per source port. For bridged ports all members share
 +	 * one FID, so we cannot selectively suppress flooding to the CPU for
-+	 * one source port while allowing it for another.  Silently ignore the
++	 * one source port while allowing it for another. Silently ignore the
 +	 * request -- the excess flooding towards the CPU is harmless.
 +	 */
 +	if (!dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
@@ -1098,7 +1086,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	struct mxl862xx_priv *priv = ds->priv;
 +	unsigned long old_block = priv->ports[port].flood_block;
 +	unsigned long block = old_block;
-+	bool need_update = false;
 +	int ret;
 +
 +	if (flags.mask & BR_FLOOD) {
@@ -1128,8 +1115,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	if (flags.mask & BR_LEARNING)
 +		priv->ports[port].learning = !!(flags.val & BR_LEARNING);
 +
-+	need_update = (block != old_block) || (flags.mask & BR_LEARNING);
-+	if (need_update) {
++	if ((block != old_block) || (flags.mask & BR_LEARNING)) {
 +		priv->ports[port].flood_block = block;
 +		ret = mxl862xx_set_bridge_port(ds, port);
 +		if (ret)
@@ -1163,15 +1149,16 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
  
  static void mxl862xx_phylink_mac_config(struct phylink_config *config,
-@@ -407,6 +1060,7 @@ static int mxl862xx_probe(struct mdio_de
+@@ -407,7 +1046,7 @@ static int mxl862xx_probe(struct mdio_de
  	struct device *dev = &mdiodev->dev;
  	struct mxl862xx_priv *priv;
  	struct dsa_switch *ds;
-+	int i;
+-	int err;
++	int err, i;
  
  	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  	if (!priv)
-@@ -424,8 +1078,17 @@ static int mxl862xx_probe(struct mdio_de
+@@ -425,14 +1064,25 @@ static int mxl862xx_probe(struct mdio_de
  	ds->ops = &mxl862xx_switch_ops;
  	ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops;
  	ds->num_ports = MXL862XX_MAX_PORTS;
@@ -1188,8 +1175,18 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dev_set_drvdata(dev, ds);
  
- 	return dsa_register_switch(ds);
-@@ -435,6 +1098,7 @@ static void mxl862xx_remove(struct mdio_
+ 	err = dsa_register_switch(ds);
+-	if (err)
++	if (err) {
+ 		mxl862xx_host_shutdown(priv);
+-
++		for (i = 0; i < MXL862XX_MAX_PORTS; i++)
++			cancel_work_sync(&priv->ports[i].host_flood_work);
++	}
+ 	return err;
+ }
+ 
+@@ -440,6 +1090,7 @@ static void mxl862xx_remove(struct mdio_
  {
  	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
  	struct mxl862xx_priv *priv;
@@ -1197,14 +1194,14 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	if (!ds)
  		return;
-@@ -444,12 +1108,21 @@ static void mxl862xx_remove(struct mdio_
+@@ -449,12 +1100,21 @@ static void mxl862xx_remove(struct mdio_
  	dsa_unregister_switch(ds);
  
  	mxl862xx_host_shutdown(priv);
 +
-+	/* Cancel any pending host flood work.  dsa_unregister_switch()
++	/* Cancel any pending host flood work. dsa_unregister_switch()
 +	 * has already called port_teardown (which sets setup_done=false),
-+	 * but a worker could still be blocked on rtnl_lock().  Since we
++	 * but a worker could still be blocked on rtnl_lock(). Since we
 +	 * are now outside RTNL, cancel_work_sync() will not deadlock.
 +	 */
 +	for (i = 0; i < MXL862XX_MAX_PORTS; i++)
@@ -1219,7 +1216,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	if (!ds)
  		return;
-@@ -460,6 +1133,9 @@ static void mxl862xx_shutdown(struct mdi
+@@ -465,6 +1125,9 @@ static void mxl862xx_shutdown(struct mdi
  
  	mxl862xx_host_shutdown(priv);
  

+ 17 - 106
target/linux/generic/pending-6.12/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch

@@ -1,7 +1,7 @@
-From 7286ac4f850339aac37dd52633f4a70816b621a8 Mon Sep 17 00:00:00 2001
+From 0d88d02cc9dccad01ff88f54e1beee867107b942 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 10 Mar 2026 02:36:00 +0000
-Subject: [PATCH 14/35] net: dsa: mxl862xx: implement VLAN functionality
+Subject: [PATCH 05/26] net: dsa: mxl862xx: implement VLAN functionality
 
 Add VLAN support using both the Extended VLAN (EVLAN) engine and the
 VLAN Filter (VF) engine in a hybrid architecture that allows a higher
@@ -35,11 +35,11 @@ VLAN Filter blocks across ports with identical VID sets.
 
 Signed-off-by: Daniel Golle <[email protected]>
 ---
- drivers/net/dsa/mxl862xx/mxl862xx-api.h | 329 ++++++++
+ drivers/net/dsa/mxl862xx/mxl862xx-api.h | 329 +++++++++
  drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |  12 +
- drivers/net/dsa/mxl862xx/mxl862xx.c     | 960 +++++++++++++++++++++++-
- drivers/net/dsa/mxl862xx/mxl862xx.h     | 110 ++-
- 4 files changed, 1386 insertions(+), 25 deletions(-)
+ drivers/net/dsa/mxl862xx/mxl862xx.c     | 915 +++++++++++++++++++++++-
+ drivers/net/dsa/mxl862xx/mxl862xx.h     | 104 ++-
+ 4 files changed, 1344 insertions(+), 16 deletions(-)
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx-api.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx-api.h
@@ -577,7 +577,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	mxl862xx_fw_portmap_from_bitmap(br_port_cfg.bridge_port_map, p->portmap);
  
  	for (i = 0; i < ARRAY_SIZE(mxl862xx_flood_meters); i++) {
-@@ -329,13 +472,131 @@ static int mxl862xx_sync_bridge_members(
+@@ -329,6 +472,91 @@ static int mxl862xx_sync_bridge_members(
  	return ret;
  }
  
@@ -609,11 +609,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return 0;
 +}
 +
-+/**
-+ * mxl862xx_vf_init - Initialize per-port VF block software state
-+ * @vf: VLAN Filter block to initialize
-+ * @size: block size (entries per port)
-+ */
 +static void mxl862xx_vf_init(struct mxl862xx_vf_block *vf, u16 size)
 +{
 +	vf->allocated = false;
@@ -623,15 +618,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	INIT_LIST_HEAD(&vf->vids);
 +}
 +
-+/**
-+ * mxl862xx_vf_block_alloc - Allocate a VLAN Filter block from firmware
-+ * @priv: driver private data
-+ * @size: number of entries to allocate
-+ * @block_id: output -- block ID assigned by firmware
-+ *
-+ * Allocates a contiguous VLAN Filter block and configures it to discard
-+ * unmatched tagged frames (VID membership enforcement).
-+ */
 +static int mxl862xx_vf_block_alloc(struct mxl862xx_priv *priv,
 +				   u16 size, u16 *block_id)
 +{
@@ -650,15 +636,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return 0;
 +}
 +
-+/**
-+ * mxl862xx_vf_entry_discard - Write a DISCARD entry to plug an unused slot
-+ * @priv: driver private data
-+ * @block_id: HW VLAN Filter block ID
-+ * @index: entry index within the block
-+ *
-+ * Unwritten VLAN Filter entries default to VID=0 / ALLOW which would
-+ * leak VID 0 traffic. This writes a DISCARD entry to plug the slot.
-+ */
 +static int mxl862xx_vf_entry_discard(struct mxl862xx_priv *priv,
 +				     u16 block_id, u16 index)
 +{
@@ -673,16 +650,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return MXL862XX_API_WRITE(priv, MXL862XX_VLANFILTER_SET, cfg);
 +}
 +
-+/**
-+ * mxl862xx_vf_alloc - Allocate the port's VF HW block
-+ * @priv: driver private data
-+ * @vf: VLAN Filter block (must have been initialized via mxl862xx_vf_init)
-+ *
-+ * Allocates the block and writes a DISCARD sentinel at index 0 so that
-+ * when active_count is 0, the single-entry scan window blocks VID-0
-+ * (which would otherwise match the zeroed-out default and be allowed).
-+ * Called once per port from port_setup.
-+ */
 +static int mxl862xx_vf_alloc(struct mxl862xx_priv *priv,
 +			     struct mxl862xx_vf_block *vf)
 +{
@@ -699,18 +666,10 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return mxl862xx_vf_entry_discard(priv, vf->block_id, 0);
 +}
 +
- /**
-  * mxl862xx_allocate_bridge - Allocate a firmware bridge instance
-  * @priv: driver private data
-  * @bridge_id: output -- firmware bridge ID assigned by the firmware
-  *
-  * Newly allocated bridges default to flooding all traffic classes
-- * (unknown unicast, multicast, broadcast).  Callers that need
-+ * (unknown unicast, multicast, broadcast). Callers that need
-  * different forwarding behavior must call mxl862xx_bridge_config_fwd()
-  * after allocation.
-  *
-@@ -404,6 +665,9 @@ static int mxl862xx_add_single_port_brid
+ static int mxl862xx_allocate_bridge(struct mxl862xx_priv *priv, u16 *bridge_id)
+ {
+ 	struct mxl862xx_bridge_alloc br_alloc = {};
+@@ -392,6 +620,9 @@ static int mxl862xx_add_single_port_brid
  static int mxl862xx_setup(struct dsa_switch *ds)
  {
  	struct mxl862xx_priv *priv = ds->priv;
@@ -720,7 +679,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	int ret;
  
  	ret = mxl862xx_reset(priv);
-@@ -414,6 +678,50 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -402,6 +633,50 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -771,7 +730,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	ret = mxl862xx_setup_drop_meter(ds);
  	if (ret)
  		return ret;
-@@ -495,27 +803,616 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -483,27 +758,616 @@ static int mxl862xx_configure_sp_tag_pro
  	return MXL862XX_API_WRITE(ds->priv, MXL862XX_SS_SPTAG_SET, tag);
  }
  
@@ -1392,7 +1351,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_bridge_join(struct dsa_switch *ds, int port,
  				     const struct dsa_bridge bridge,
  				     bool *tx_fwd_offload,
-@@ -565,6 +1462,22 @@ static void mxl862xx_port_bridge_leave(s
+@@ -553,6 +1417,22 @@ static void mxl862xx_port_bridge_leave(s
  	bitmap_zero(p->portmap, MXL862XX_MAX_BRIDGE_PORTS);
  	__set_bit(dp->cpu_dp->index, p->portmap);
  	p->flood_block = 0;
@@ -1415,7 +1374,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	err = mxl862xx_set_bridge_port(ds, port);
  	if (err)
  		dev_err(ds->dev,
-@@ -614,6 +1527,28 @@ static int mxl862xx_port_setup(struct ds
+@@ -602,6 +1482,28 @@ static int mxl862xx_port_setup(struct ds
  	if (ret)
  		return ret;
  
@@ -1444,37 +1403,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	priv->ports[port].setup_done = true;
  
  	return 0;
-@@ -808,7 +1743,7 @@ static int mxl862xx_port_mdb_del(struct
- 	mxl862xx_fw_portmap_clear_bit(qparam.port_map, port);
- 
- 	if (mxl862xx_fw_portmap_is_empty(qparam.port_map)) {
--		/* No ports left — remove the entry entirely */
-+		/* No ports left -- remove the entry entirely */
- 		rparam.fid = cpu_to_le16(fid);
- 		rparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
- 		ether_addr_copy(rparam.mac, mdb->addr);
-@@ -899,7 +1834,7 @@ static void mxl862xx_port_stp_state_set(
- /* Deferred work handler for host flood configuration.
-  *
-  * port_set_host_flood is called from atomic context (under
-- * netif_addr_lock), so firmware calls must be deferred.  The worker
-+ * netif_addr_lock), so firmware calls must be deferred. The worker
-  * acquires rtnl_lock() to serialize with DSA callbacks that access the
-  * same driver state.
-  */
-@@ -924,9 +1859,9 @@ static void mxl862xx_host_flood_work_fn(
- 	mc = p->host_flood_mc;
- 
- 	/* The hardware controls unknown-unicast/multicast forwarding per FID
--	 * (bridge), not per source port.  For bridged ports all members share
-+	 * (bridge), not per source port. For bridged ports all members share
- 	 * one FID, so we cannot selectively suppress flooding to the CPU for
--	 * one source port while allowing it for another.  Silently ignore the
-+	 * one source port while allowing it for another. Silently ignore the
- 	 * request -- the excess flooding towards the CPU is harmless.
- 	 */
- 	if (!dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
-@@ -1026,6 +1961,9 @@ static const struct dsa_switch_ops mxl86
+@@ -1012,6 +1914,9 @@ static const struct dsa_switch_ops mxl86
  	.port_fdb_dump = mxl862xx_port_fdb_dump,
  	.port_mdb_add = mxl862xx_port_mdb_add,
  	.port_mdb_del = mxl862xx_port_mdb_del,
@@ -1484,15 +1413,6 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
  
  static void mxl862xx_phylink_mac_config(struct phylink_config *config,
-@@ -1111,7 +2049,7 @@ static void mxl862xx_remove(struct mdio_
- 
- 	/* Cancel any pending host flood work.  dsa_unregister_switch()
- 	 * has already called port_teardown (which sets setup_done=false),
--	 * but a worker could still be blocked on rtnl_lock().  Since we
-+	 * but a worker could still be blocked on rtnl_lock(). Since we
- 	 * are now outside RTNL, cancel_work_sync() will not deadlock.
- 	 */
- 	for (i = 0; i < MXL862XX_MAX_PORTS; i++)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
 @@ -13,6 +13,8 @@ struct mxl862xx_priv;
@@ -1504,7 +1424,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  /* Number of __le16 words in a firmware portmap (128-bit bitmap). */
  #define MXL862XX_FW_PORTMAP_WORDS	(MXL862XX_MAX_BRIDGE_PORTS / 16)
-@@ -86,12 +88,72 @@ static inline bool mxl862xx_fw_portmap_i
+@@ -86,6 +88,66 @@ static inline bool mxl862xx_fw_portmap_i
  }
  
  /**
@@ -1571,15 +1491,6 @@ Signed-off-by: Daniel Golle <[email protected]>
   * struct mxl862xx_port - per-port state tracked by the driver
   * @priv:                back-pointer to switch private data; needed by
   *                       deferred work handlers to access ds and priv
-- * @fid:                 firmware FID for the permanent single-port bridge;
-- *                       kept alive for the lifetime of the port so traffic is
-- *                       never forwarded while the port is unbridged
-+ * @fid:                 firmware FID for the permanent single-port bridge; kept
-+ *                       alive for the lifetime of the port so traffic is never
-+ *                       forwarded while the port is unbridged
-  * @portmap:             bitmap of switch port indices that share the current
-  *                       bridge with this port
-  * @flood_block:         bitmask of firmware meter indices that are currently
 @@ -101,6 +163,11 @@ static inline bool mxl862xx_fw_portmap_i
   * @setup_done:          set at end of port_setup, cleared at start of
   *                       port_teardown; guards deferred work against

+ 4 - 4
target/linux/generic/pending-6.12/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch

@@ -1,7 +1,7 @@
-From 03b583e774835f771dd7c3c265be5903f008e8e5 Mon Sep 17 00:00:00 2001
+From 0067d79d10becfc5779fb50d5c0ac152cc5dc303 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Sun, 22 Mar 2026 00:57:33 +0000
-Subject: [PATCH 15/35] net: dsa: mxl862xx: add ethtool statistics support
+Subject: [PATCH 06/26] net: dsa: mxl862xx: add ethtool statistics support
 
 The MxL862xx firmware exposes per-port RMON counters through the
 RMON_PORT_GET command, covering standard IEEE 802.3 MAC statistics
@@ -257,7 +257,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #define MXL862XX_SDMA_PCTRLP(p)		(0xbc0 + ((p) * 0x6))
  #define MXL862XX_SDMA_PCTRL_EN		BIT(0)
  
-@@ -1940,6 +1998,110 @@ static int mxl862xx_port_bridge_flags(st
+@@ -1893,6 +1951,110 @@ static int mxl862xx_port_bridge_flags(st
  	return 0;
  }
  
@@ -368,7 +368,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static const struct dsa_switch_ops mxl862xx_switch_ops = {
  	.get_tag_protocol = mxl862xx_get_tag_protocol,
  	.setup = mxl862xx_setup,
-@@ -1964,6 +2126,12 @@ static const struct dsa_switch_ops mxl86
+@@ -1917,6 +2079,12 @@ static const struct dsa_switch_ops mxl86
  	.port_vlan_filtering = mxl862xx_port_vlan_filtering,
  	.port_vlan_add = mxl862xx_port_vlan_add,
  	.port_vlan_del = mxl862xx_port_vlan_del,

+ 100 - 22
target/linux/generic/pending-6.12/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch

@@ -1,7 +1,7 @@
-From 8b66d20f7e5226f4854a39cfb9f25a0591a5bb83 Mon Sep 17 00:00:00 2001
+From bab5a69e3872a693069e430a1fa0d2825ea83b4f Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 04:14:38 +0000
-Subject: [PATCH 16/35] net: dsa: mxl862xx: implement .get_stats64
+Subject: [PATCH 07/26] net: dsa: mxl862xx: implement .get_stats64
 
 Poll free-running firmware RMON counters every 2 seconds and accumulate
 deltas into 64-bit per-port statistics. 32-bit packet counters wrap
@@ -11,10 +11,49 @@ that counters are always up to date when queried.
 
 Signed-off-by: Daniel Golle <[email protected]>
 ---
- drivers/net/dsa/mxl862xx/mxl862xx.c | 167 ++++++++++++++++++++++++++++
- drivers/net/dsa/mxl862xx/mxl862xx.h |  51 +++++++++
- 2 files changed, 218 insertions(+)
+ drivers/net/dsa/mxl862xx/mxl862xx-host.c |   8 +-
+ drivers/net/dsa/mxl862xx/mxl862xx.c      | 174 +++++++++++++++++++++++
+ drivers/net/dsa/mxl862xx/mxl862xx.h      |  63 +++++++-
+ 3 files changed, 238 insertions(+), 7 deletions(-)
 
+--- a/drivers/net/dsa/mxl862xx/mxl862xx-host.c
++++ b/drivers/net/dsa/mxl862xx/mxl862xx-host.c
+@@ -48,7 +48,7 @@ static void mxl862xx_crc_err_work_fn(str
+ 		dev_close(dp->conduit);
+ 	rtnl_unlock();
+ 
+-	clear_bit(0, &priv->crc_err);
++	clear_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags);
+ }
+ 
+ /* Firmware CRC error codes (outside normal Zephyr errno range). */
+@@ -247,7 +247,7 @@ static int mxl862xx_issue_cmd(struct mxl
+ 
+ 	ret = mxl862xx_crc6_verify(ctrl_enc, len_enc, &fw_result);
+ 	if (ret) {
+-		if (!test_and_set_bit(0, &priv->crc_err))
++		if (!test_and_set_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags))
+ 			schedule_work(&priv->crc_err_work);
+ 		return -EIO;
+ 	}
+@@ -314,7 +314,7 @@ static int mxl862xx_send_cmd(struct mxl8
+ 	if (ret < 0) {
+ 		if ((ret == MXL862XX_FW_CRC6_ERR ||
+ 		     ret == MXL862XX_FW_CRC16_ERR) &&
+-		    !test_and_set_bit(0, &priv->crc_err))
++		    !test_and_set_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags))
+ 			schedule_work(&priv->crc_err_work);
+ 		if (!quiet)
+ 			dev_err(&priv->mdiodev->dev,
+@@ -458,7 +458,7 @@ int mxl862xx_api_wrap(struct mxl862xx_pr
+ 	}
+ 
+ 	if (crc16(0xffff, (const u8 *)data, size) != crc) {
+-		if (!test_and_set_bit(0, &priv->crc_err))
++		if (!test_and_set_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags))
+ 			schedule_work(&priv->crc_err_work);
+ 		ret = -EIO;
+ 		goto out;
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
 @@ -30,6 +30,12 @@
@@ -30,7 +69,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  struct mxl862xx_mib_desc {
  	unsigned int size;
  	unsigned int offset;
-@@ -784,6 +790,9 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -739,6 +745,9 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -40,7 +79,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return mxl862xx_setup_mdio(ds);
  }
  
-@@ -2102,6 +2111,156 @@ static void mxl862xx_get_pause_stats(str
+@@ -2055,6 +2064,158 @@ static void mxl862xx_get_pause_stats(str
  	pause_stats->rx_pause_frames = le32_to_cpu(cnt.rx_good_pause_pkts);
  }
  
@@ -160,8 +199,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	dsa_switch_for_each_available_port(dp, ds)
 +		mxl862xx_stats_poll(ds, dp->index);
 +
-+	schedule_delayed_work(&priv->stats_work,
-+			      MXL862XX_STATS_POLL_INTERVAL);
++	if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags))
++		schedule_delayed_work(&priv->stats_work,
++				      MXL862XX_STATS_POLL_INTERVAL);
 +}
 +
 +static void mxl862xx_get_stats64(struct dsa_switch *ds, int port,
@@ -189,15 +229,16 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	spin_unlock_bh(&priv->ports[port].stats_lock);
 +
 +	/* Trigger a fresh poll so the next read sees up-to-date counters.
-+	 * No-op if the work is already pending or running.
++	 * No-op if the work is already pending, running, or teardown started.
 +	 */
-+	schedule_delayed_work(&priv->stats_work, 0);
++	if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags))
++		schedule_delayed_work(&priv->stats_work, 0);
 +}
 +
  static const struct dsa_switch_ops mxl862xx_switch_ops = {
  	.get_tag_protocol = mxl862xx_get_tag_protocol,
  	.setup = mxl862xx_setup,
-@@ -2132,6 +2291,7 @@ static const struct dsa_switch_ops mxl86
+@@ -2085,6 +2246,7 @@ static const struct dsa_switch_ops mxl86
  	.get_eth_mac_stats = mxl862xx_get_eth_mac_stats,
  	.get_eth_ctrl_stats = mxl862xx_get_eth_ctrl_stats,
  	.get_pause_stats = mxl862xx_get_pause_stats,
@@ -205,7 +246,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
  
  static void mxl862xx_phylink_mac_config(struct phylink_config *config,
-@@ -2193,8 +2353,11 @@ static int mxl862xx_probe(struct mdio_de
+@@ -2146,16 +2308,22 @@ static int mxl862xx_probe(struct mdio_de
  		priv->ports[i].priv = priv;
  		INIT_WORK(&priv->ports[i].host_flood_work,
  			  mxl862xx_host_flood_work_fn);
@@ -216,20 +257,33 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dev_set_drvdata(dev, ds);
  
- 	return dsa_register_switch(ds);
-@@ -2213,6 +2376,8 @@ static void mxl862xx_remove(struct mdio_
+ 	err = dsa_register_switch(ds);
+ 	if (err) {
++		set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
++		cancel_delayed_work_sync(&priv->stats_work);
+ 		mxl862xx_host_shutdown(priv);
+ 		for (i = 0; i < MXL862XX_MAX_PORTS; i++)
+ 			cancel_work_sync(&priv->ports[i].host_flood_work);
+ 	}
++
+ 	return err;
+ }
  
- 	dsa_unregister_switch(ds);
+@@ -2170,6 +2338,9 @@ static void mxl862xx_remove(struct mdio_
+ 
+ 	priv = ds->priv;
  
++	set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
 +	cancel_delayed_work_sync(&priv->stats_work);
 +
- 	mxl862xx_host_shutdown(priv);
+ 	dsa_unregister_switch(ds);
  
- 	/* Cancel any pending host flood work.  dsa_unregister_switch()
-@@ -2237,6 +2402,8 @@ static void mxl862xx_shutdown(struct mdi
+ 	mxl862xx_host_shutdown(priv);
+@@ -2196,6 +2367,9 @@ static void mxl862xx_shutdown(struct mdi
  
  	dsa_switch_shutdown(ds);
  
++	set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
 +	cancel_delayed_work_sync(&priv->stats_work);
 +
  	mxl862xx_host_shutdown(priv);
@@ -296,7 +350,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   */
  struct mxl862xx_port {
  	struct mxl862xx_priv *priv;
-@@ -195,6 +240,9 @@ struct mxl862xx_port {
+@@ -195,16 +240,25 @@ struct mxl862xx_port {
  	bool host_flood_uc;
  	bool host_flood_mc;
  	struct work_struct host_flood_work;
@@ -305,8 +359,26 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	spinlock_t stats_lock;
  };
  
++/* Bit indices for struct mxl862xx_priv::flags */
++#define MXL862XX_FLAG_CRC_ERR		0
++#define MXL862XX_FLAG_WORK_STOPPED	1
++
  /**
-@@ -216,6 +264,8 @@ struct mxl862xx_port {
+  * struct mxl862xx_priv - driver private data for an MxL862xx switch
+  * @ds:                 pointer to the DSA switch instance
+  * @mdiodev:            MDIO device used to communicate with the switch firmware
+  * @crc_err_work:       deferred work for shutting down all ports on MDIO CRC
+  *                      errors
+- * @crc_err:            set atomically before CRC-triggered shutdown, cleared
+- *                      after
++ * @flags:              atomic status flags; %MXL862XX_FLAG_CRC_ERR is set
++ *                      before CRC-triggered shutdown and cleared after;
++ *                      %MXL862XX_FLAG_WORK_STOPPED is set before cancelling
++ *                      stats_work to prevent rescheduling during teardown
+  * @drop_meter:         index of the single shared zero-rate firmware meter
+  *                      used to unconditionally drop traffic (used to block
+  *                      flooding)
+@@ -216,18 +270,21 @@ struct mxl862xx_port {
   * @evlan_ingress_size: per-port ingress Extended VLAN block size
   * @evlan_egress_size:  per-port egress Extended VLAN block size
   * @vf_block_size:      per-port VLAN Filter block size
@@ -315,7 +387,13 @@ Signed-off-by: Daniel Golle <[email protected]>
   */
  struct mxl862xx_priv {
  	struct dsa_switch *ds;
-@@ -228,6 +278,7 @@ struct mxl862xx_priv {
+ 	struct mdio_device *mdiodev;
+ 	struct work_struct crc_err_work;
+-	unsigned long crc_err;
++	unsigned long flags;
+ 	u16 drop_meter;
+ 	struct mxl862xx_port ports[MXL862XX_MAX_PORTS];
+ 	u16 bridges[MXL862XX_MAX_BRIDGES + 1];
  	u16 evlan_ingress_size;
  	u16 evlan_egress_size;
  	u16 vf_block_size;

+ 11 - 11
target/linux/generic/pending-6.12/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch

@@ -1,7 +1,7 @@
-From fecfbea928cd762b19ff17aa16fb1ab143d73db1 Mon Sep 17 00:00:00 2001
+From da12469e73282da814163125153f381823e33f20 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 17:56:35 +0000
-Subject: [PATCH 17/35] net: dsa: mxl862xx: store firmware version for feature
+Subject: [PATCH 08/26] net: dsa: mxl862xx: store firmware version for feature
  gating
 
 Query the firmware version at init (already done in wait_ready),
@@ -40,10 +40,11 @@ Signed-off-by: Daniel Golle <[email protected]>
  #include <linux/mdio.h>
  #include <linux/workqueue.h>
  #include <net/dsa.h>
-@@ -246,6 +247,38 @@ struct mxl862xx_port {
+@@ -245,6 +246,38 @@ struct mxl862xx_port {
+ 	spinlock_t stats_lock;
  };
  
- /**
++/**
 + * union mxl862xx_fw_version - firmware version for comparison and display
 + * @major: firmware major version
 + * @minor: firmware minor version
@@ -75,11 +76,10 @@ Signed-off-by: Daniel Golle <[email protected]>
 +#define MXL862XX_FW_VER_MIN(priv, maj, min, rev) \
 +	((priv)->fw_version.raw >= MXL862XX_FW_VER(maj, min, rev))
 +
-+/**
-  * struct mxl862xx_priv - driver private data for an MxL862xx switch
-  * @ds:                 pointer to the DSA switch instance
-  * @mdiodev:            MDIO device used to communicate with the switch firmware
-@@ -256,6 +289,8 @@ struct mxl862xx_port {
+ /* Bit indices for struct mxl862xx_priv::flags */
+ #define MXL862XX_FLAG_CRC_ERR		0
+ #define MXL862XX_FLAG_WORK_STOPPED	1
+@@ -262,6 +295,8 @@ struct mxl862xx_port {
   * @drop_meter:         index of the single shared zero-rate firmware meter
   *                      used to unconditionally drop traffic (used to block
   *                      flooding)
@@ -88,9 +88,9 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @ports:              per-port state, indexed by switch port number
   * @bridges:            maps DSA bridge number to firmware bridge ID;
   *                      zero means no firmware bridge allocated for that
-@@ -273,6 +308,7 @@ struct mxl862xx_priv {
+@@ -279,6 +314,7 @@ struct mxl862xx_priv {
  	struct work_struct crc_err_work;
- 	unsigned long crc_err;
+ 	unsigned long flags;
  	u16 drop_meter;
 +	union mxl862xx_fw_version fw_version;
  	struct mxl862xx_port ports[MXL862XX_MAX_PORTS];

+ 4 - 4
target/linux/generic/pending-6.12/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch

@@ -1,7 +1,7 @@
-From 3cb224514226928df80e43ca2280c7dca654bdfe Mon Sep 17 00:00:00 2001
+From f7606470d398e4091e1bc405bf2125dc5fc99919 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 21:39:30 +0000
-Subject: [PATCH 18/35] net: dsa: mxl862xx: move phylink stubs to
+Subject: [PATCH 09/26] net: dsa: mxl862xx: move phylink stubs to
  mxl862xx-phylink.c
 
 Move the phylink MAC operations and get_caps callback from mxl862xx.c
@@ -110,7 +110,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  #define MXL862XX_API_WRITE(dev, cmd, data) \
  	mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), false, false)
-@@ -1642,16 +1643,6 @@ static void mxl862xx_port_teardown(struc
+@@ -1597,16 +1598,6 @@ static void mxl862xx_port_teardown(struc
  	priv->ports[port].setup_done = false;
  }
  
@@ -127,7 +127,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_get_fid(struct dsa_switch *ds, struct dsa_db db)
  {
  	struct mxl862xx_priv *priv = ds->priv;
-@@ -2297,33 +2288,6 @@ static const struct dsa_switch_ops mxl86
+@@ -2252,33 +2243,6 @@ static const struct dsa_switch_ops mxl86
  	.get_stats64 = mxl862xx_get_stats64,
  };
  

+ 2 - 2
target/linux/generic/pending-6.12/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch

@@ -1,7 +1,7 @@
-From de41d438c4e90876449715a307dd03fa37338742 Mon Sep 17 00:00:00 2001
+From e583eeeb907f0abeef2082162293a5d63b9fd6fa Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Thu, 26 Mar 2026 01:50:00 +0000
-Subject: [PATCH 19/35] net: dsa: mxl862xx: move API macros to mxl862xx-host.h
+Subject: [PATCH 10/26] net: dsa: mxl862xx: move API macros to mxl862xx-host.h
 
 Move the MXL862XX_API_WRITE, MXL862XX_API_READ and
 MXL862XX_API_READ_QUIET convenience macros from mxl862xx.c to

+ 7 - 7
target/linux/generic/pending-6.12/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch

@@ -1,7 +1,7 @@
-From 88f46eb32d1aed296af2005c3ed8f23a6eea64c3 Mon Sep 17 00:00:00 2001
+From e25f0886853607e4a6d1157ae84e43e8224cf3b7 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Sun, 22 Mar 2026 00:57:44 +0000
-Subject: [PATCH 20/35] net: dsa: mxl862xx: add support for SerDes ports
+Subject: [PATCH 11/26] net: dsa: mxl862xx: add support for SerDes ports
 
 The MxL862xx has two XPCS/SerDes interfaces (XPCS0 for ports 9-12,
 XPCS1 for ports 13-16). Each can operate in various single-lane
@@ -990,7 +990,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #endif /* __MXL862XX_PHYLINK_H */
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -729,7 +729,7 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -684,7 +684,7 @@ static int mxl862xx_setup(struct dsa_swi
  	int n_user_ports = 0, max_vlans;
  	int ingress_finals, vid_rules;
  	struct dsa_port *dp;
@@ -999,7 +999,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	ret = mxl862xx_reset(priv);
  	if (ret)
-@@ -739,6 +739,9 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -694,6 +694,9 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -1034,7 +1034,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * union mxl862xx_fw_version - firmware version for comparison and display
   * @major: firmware major version
   * @minor: firmware minor version
-@@ -291,6 +307,8 @@ union mxl862xx_fw_version {
+@@ -297,6 +313,8 @@ union mxl862xx_fw_version {
   *                      flooding)
   * @fw_version:         cached firmware version, populated at probe and
   *                      compared with MXL862XX_FW_VER_MIN()
@@ -1043,8 +1043,8 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @ports:              per-port state, indexed by switch port number
   * @bridges:            maps DSA bridge number to firmware bridge ID;
   *                      zero means no firmware bridge allocated for that
-@@ -309,6 +327,7 @@ struct mxl862xx_priv {
- 	unsigned long crc_err;
+@@ -315,6 +333,7 @@ struct mxl862xx_priv {
+ 	unsigned long flags;
  	u16 drop_meter;
  	union mxl862xx_fw_version fw_version;
 +	struct mxl862xx_pcs serdes_ports[8];

+ 5 - 5
target/linux/generic/pending-6.12/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch

@@ -1,7 +1,7 @@
-From d40565e2e00fc2c8f04b9c571fcbea2f146db844 Mon Sep 17 00:00:00 2001
+From 24d752291784e30d7329bed15744bbbc6a3e2485 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:14:33 +0000
-Subject: [PATCH 21/35] net: dsa: mxl862xx: add SerDes ethtool statistics
+Subject: [PATCH 12/26] net: dsa: mxl862xx: add SerDes ethtool statistics
 
 Expose SerDes equalization and signal detect parameters as ethtool
 statistics on ports 9-16 (XPCS-backed ports). Uses the XPCS EQ_GET
@@ -239,7 +239,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #endif /* __MXL862XX_PHYLINK_H */
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -2007,6 +2007,8 @@ static void mxl862xx_get_strings(struct
+@@ -1960,6 +1960,8 @@ static void mxl862xx_get_strings(struct
  
  	for (i = 0; i < ARRAY_SIZE(mxl862xx_mib); i++)
  		ethtool_puts(&data, mxl862xx_mib[i].name);
@@ -248,7 +248,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static int mxl862xx_get_sset_count(struct dsa_switch *ds, int port, int sset)
-@@ -2014,7 +2016,7 @@ static int mxl862xx_get_sset_count(struc
+@@ -1967,7 +1969,7 @@ static int mxl862xx_get_sset_count(struc
  	if (sset != ETH_SS_STATS)
  		return 0;
  
@@ -257,7 +257,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static int mxl862xx_read_rmon(struct dsa_switch *ds, int port,
-@@ -2050,6 +2052,8 @@ static void mxl862xx_get_ethtool_stats(s
+@@ -2003,6 +2005,8 @@ static void mxl862xx_get_ethtool_stats(s
  		else
  			*data++ = le64_to_cpu(*(__le64 *)field);
  	}

+ 3 - 3
target/linux/generic/pending-6.12/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch

@@ -1,7 +1,7 @@
-From 54dd5fabc543f8538202367a863eb0e9161bacab Mon Sep 17 00:00:00 2001
+From ee227a5e4c74f599cc1b34578b32214d5873ad2f Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:15:32 +0000
-Subject: [PATCH 22/35] net: dsa: mxl862xx: add SerDes self-test via PRBS and
+Subject: [PATCH 13/26] net: dsa: mxl862xx: add SerDes self-test via PRBS and
  BERT
 
 Implement the dsa_switch_ops.self_test callback for SerDes ports
@@ -198,7 +198,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #endif /* __MXL862XX_PHYLINK_H */
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -2286,6 +2286,7 @@ static const struct dsa_switch_ops mxl86
+@@ -2241,6 +2241,7 @@ static const struct dsa_switch_ops mxl86
  	.get_eth_ctrl_stats = mxl862xx_get_eth_ctrl_stats,
  	.get_pause_stats = mxl862xx_get_pause_stats,
  	.get_stats64 = mxl862xx_get_stats64,

+ 3 - 3
target/linux/generic/pending-6.12/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch

@@ -1,7 +1,7 @@
-From dd62e68cd0bd29934c3efbce687d5e103cc4b331 Mon Sep 17 00:00:00 2001
+From 43eb3eed250ea4e7e83371fcbf2bfb8d626eade6 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:51:13 +0000
-Subject: [PATCH 23/35] net: dsa: mxl862xx: trap link-local frames to the CPU
+Subject: [PATCH 14/26] net: dsa: mxl862xx: trap link-local frames to the CPU
  port
 
 Install per-CTP PCE rules on each user port that trap IEEE 802.1D
@@ -817,7 +817,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_set_bridge_port(struct dsa_switch *ds, int port)
  {
  	struct mxl862xx_bridge_port_config br_port_cfg = {};
-@@ -1594,6 +1658,11 @@ static int mxl862xx_port_setup(struct ds
+@@ -1549,6 +1613,11 @@ static int mxl862xx_port_setup(struct ds
  	if (ret)
  		return ret;
  

+ 3 - 3
target/linux/generic/pending-6.12/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch

@@ -1,7 +1,7 @@
-From 3bba25f7ba35e3bca8230bd37ffb612944dbf301 Mon Sep 17 00:00:00 2001
+From e18f5b235d8df21209c73f4f0bbc00cc3a1973ba Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:51:21 +0000
-Subject: [PATCH 24/35] net: dsa: mxl862xx: warn about old firmware default PCE
+Subject: [PATCH 15/26] net: dsa: mxl862xx: warn about old firmware default PCE
  rules
 
 Firmware versions older than 1.0.80 install global PCE rules at
@@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -854,6 +854,10 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -809,6 +809,10 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  

+ 66 - 102
target/linux/generic/pending-6.12/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch

@@ -1,7 +1,7 @@
-From 1687c5632dfd80461b12425b943e30555faa3dd4 Mon Sep 17 00:00:00 2001
+From 04929904d3a7d824593587e52e3ed21d6f0f109a Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Sun, 22 Mar 2026 00:58:04 +0000
-Subject: [PATCH 25/35] net: dsa: add 802.1Q VLAN-based tag driver for MxL862xx
+Subject: [PATCH 16/26] net: dsa: add 802.1Q VLAN-based tag driver for MxL862xx
 
 The MxL862xx native 8-byte special tag (SpTag) requires firmware
 support on the switch CPU and is not compatible with all SoC Ethernet
@@ -23,12 +23,12 @@ Signed-off-by: Daniel Golle <[email protected]>
  drivers/net/dsa/mxl862xx/mxl862xx-api.h |  221 +++
  drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |    2 +
  drivers/net/dsa/mxl862xx/mxl862xx.c     | 1626 ++++++++++++++++++++---
- drivers/net/dsa/mxl862xx/mxl862xx.h     |   21 +-
+ drivers/net/dsa/mxl862xx/mxl862xx.h     |   13 +
  include/net/dsa.h                       |    2 +
  net/dsa/Kconfig                         |    7 +
  net/dsa/Makefile                        |    1 +
  net/dsa/tag_mxl862xx_8021q.c            |   59 +
- 9 files changed, 1738 insertions(+), 202 deletions(-)
+ 9 files changed, 1736 insertions(+), 196 deletions(-)
  create mode 100644 net/dsa/tag_mxl862xx_8021q.c
 
 --- a/drivers/net/dsa/mxl862xx/Kconfig
@@ -511,7 +511,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  		err = mxl862xx_set_bridge_port(ds, port);
  		if (err)
-@@ -762,7 +909,6 @@ static void mxl862xx_free_bridge(struct
+@@ -717,7 +864,6 @@ static void mxl862xx_free_bridge(struct
  
  static int mxl862xx_add_single_port_bridge(struct dsa_switch *ds, int port)
  {
@@ -519,7 +519,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	struct mxl862xx_priv *priv = ds->priv;
  	int ret;
  
-@@ -774,15 +920,27 @@ static int mxl862xx_add_single_port_brid
+@@ -729,15 +875,27 @@ static int mxl862xx_add_single_port_brid
  
  	priv->ports[port].learning = false;
  	bitmap_zero(priv->ports[port].portmap, MXL862XX_MAX_BRIDGE_PORTS);
@@ -533,7 +533,6 @@ Signed-off-by: Daniel Golle <[email protected]>
  
 -	/* Standalone ports should not flood unknown unicast or multicast
 -	 * towards the CPU by default; only broadcast is needed initially.
--	 */
 +	/* In tag_8021q mode the TX path goes through the bridge engine
 +	 * (CTP ingress EVLAN reassigns to a virtual bridge port which
 +	 * then forwards via the bridge). With learning disabled on
@@ -543,7 +542,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	 * In native SpTag mode, TX bypasses the bridge engine entirely
 +	 * (the special tag selects the egress port directly), so flood
 +	 * control only affects CPU-bound traffic and can be restrictive.
-+	 */
+ 	 */
 +	if (priv->tag_proto == DSA_TAG_PROTO_MXL862_8021Q)
 +		return mxl862xx_bridge_config_fwd(ds, priv->ports[port].fid,
 +						  true, true, true);
@@ -551,7 +550,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return mxl862xx_bridge_config_fwd(ds, priv->ports[port].fid,
  					 false, false, true);
  }
-@@ -790,10 +948,12 @@ static int mxl862xx_add_single_port_brid
+@@ -745,10 +903,12 @@ static int mxl862xx_add_single_port_brid
  static int mxl862xx_setup(struct dsa_switch *ds)
  {
  	struct mxl862xx_priv *priv = ds->priv;
@@ -566,7 +565,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	ret = mxl862xx_reset(priv);
  	if (ret)
-@@ -806,7 +966,7 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -761,7 +921,7 @@ static int mxl862xx_setup(struct dsa_swi
  	for (i = 0; i < 8; i++)
  		mxl862xx_setup_pcs(priv, &priv->serdes_ports[i], i + 9);
  
@@ -575,7 +574,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	 * With VLAN Filter handling VID membership checks:
  	 *   Ingress: only final catchall rules (PVID insertion, 802.1Q
  	 *            accept, non-8021Q TPID handling, discard).
-@@ -814,40 +974,67 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -769,40 +929,67 @@ static int mxl862xx_setup(struct dsa_swi
  	 *            ingress EVLAN rules are needed. (7 entries.)
  	 *   Egress:  2 rules per VID that needs tag stripping (untagged VIDs).
  	 *            No egress final catchalls -- VLAN Filter does the discard.
@@ -657,7 +656,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	}
  
  	ret = mxl862xx_setup_drop_meter(ds);
-@@ -858,6 +1045,68 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -813,6 +1000,68 @@ static int mxl862xx_setup(struct dsa_swi
  		dev_warn(ds->dev, "firmware < 1.0.80 installs global PCE rules "
  			 "that interfere with DSA operation, please update\n");
  
@@ -726,7 +725,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	schedule_delayed_work(&priv->stats_work,
  			      MXL862XX_STATS_POLL_INTERVAL);
  
-@@ -939,6 +1188,52 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -894,6 +1143,52 @@ static int mxl862xx_configure_sp_tag_pro
  }
  
  /**
@@ -779,7 +778,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * mxl862xx_evlan_write_rule - Write a single Extended VLAN rule to hardware
   * @priv: driver private data
   * @block_id: HW Extended VLAN block ID
-@@ -947,6 +1242,7 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -902,6 +1197,7 @@ static int mxl862xx_configure_sp_tag_pro
   * @vid: VLAN ID for VID-specific rules (ignored when !desc->match_vid)
   * @untagged: strip tag on egress for EVLAN_STRIP_IF_UNTAGGED action
   * @pvid: port VLAN ID for PVID insertion rules (0 = no PVID)
@@ -787,7 +786,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   *
   * Translates a compact rule descriptor into a full firmware
   * mxl862xx_extendedvlan_config struct and writes it via the API.
-@@ -954,7 +1250,8 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -909,7 +1205,8 @@ static int mxl862xx_configure_sp_tag_pro
  static int mxl862xx_evlan_write_rule(struct mxl862xx_priv *priv,
  				     u16 block_id, u16 entry_index,
  				     const struct mxl862xx_evlan_rule_desc *desc,
@@ -797,7 +796,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  {
  	struct mxl862xx_extendedvlan_config cfg = {};
  	struct mxl862xx_extendedvlan_filter_vlan *fv;
-@@ -1044,6 +1341,31 @@ static int mxl862xx_evlan_write_rule(str
+@@ -999,6 +1296,31 @@ static int mxl862xx_evlan_write_rule(str
  				cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_DISCARD_UPSTREAM);
  		}
  		break;
@@ -829,7 +828,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	}
  
  	return MXL862XX_API_WRITE(priv, MXL862XX_EXTENDEDVLAN_SET, cfg);
-@@ -1104,7 +1426,7 @@ static int mxl862xx_evlan_write_final_ru
+@@ -1059,7 +1381,7 @@ static int mxl862xx_evlan_write_final_ru
  	for (i = 0; i < n_rules; i++) {
  		ret = mxl862xx_evlan_write_rule(priv, blk->block_id,
  						start_idx + i, &rules[i],
@@ -838,7 +837,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		if (ret)
  			return ret;
  	}
-@@ -1273,6 +1595,27 @@ static int mxl862xx_vf_del_vid(struct mx
+@@ -1228,6 +1550,27 @@ static int mxl862xx_vf_del_vid(struct mx
  }
  
  /**
@@ -866,7 +865,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * mxl862xx_evlan_program_ingress - Write the fixed ingress catchall rules
   * @priv: driver private data
   * @port: port number
-@@ -1323,8 +1666,8 @@ static int mxl862xx_evlan_program_egress
+@@ -1278,8 +1621,8 @@ static int mxl862xx_evlan_program_egress
  	const struct mxl862xx_evlan_rule_desc *vid_rules;
  	struct mxl862xx_vf_vid *vfv;
  	u16 old_active = blk->n_active;
@@ -876,7 +875,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	if (p->vlan_filtering) {
  		vid_rules = vid_accept_standard;
-@@ -1341,13 +1684,23 @@ static int mxl862xx_evlan_program_egress
+@@ -1296,13 +1639,23 @@ static int mxl862xx_evlan_program_egress
  		if (p->vlan_filtering && !vfv->untagged)
  			continue;
  
@@ -901,7 +900,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		if (ret)
  			return ret;
  
-@@ -1356,7 +1709,29 @@ static int mxl862xx_evlan_program_egress
+@@ -1311,7 +1664,29 @@ static int mxl862xx_evlan_program_egress
  							idx++, &vid_rules[1],
  							vfv->vid,
  							vfv->untagged,
@@ -932,7 +931,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  			if (ret)
  				return ret;
  		}
-@@ -1368,8 +1743,7 @@ static int mxl862xx_evlan_program_egress
+@@ -1323,8 +1698,7 @@ static int mxl862xx_evlan_program_egress
  	 */
  	for (i = idx; i < old_active; i++) {
  		ret = mxl862xx_evlan_deactivate_entry(priv,
@@ -942,7 +941,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		if (ret)
  			return ret;
  	}
-@@ -1393,13 +1767,16 @@ static int mxl862xx_port_vlan_filtering(
+@@ -1348,13 +1722,16 @@ static int mxl862xx_port_vlan_filtering(
  
  	/* Reprogram Extended VLAN rules if filtering mode changed */
  	if (changed) {
@@ -964,7 +963,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  		ret = mxl862xx_evlan_program_ingress(priv, port);
  		if (ret)
-@@ -1536,18 +1913,19 @@ static int mxl862xx_setup_cpu_bridge(str
+@@ -1491,18 +1868,19 @@ static int mxl862xx_setup_cpu_bridge(str
  
  	/* include all assigned user ports in the CPU portmap */
  	bitmap_zero(p->portmap, MXL862XX_MAX_BRIDGE_PORTS);
@@ -990,7 +989,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_bridge_join(struct dsa_switch *ds, int port,
  				     const struct dsa_bridge bridge,
  				     bool *tx_fwd_offload,
-@@ -1580,7 +1958,6 @@ static int mxl862xx_port_bridge_join(str
+@@ -1535,7 +1913,6 @@ static int mxl862xx_port_bridge_join(str
  static void mxl862xx_port_bridge_leave(struct dsa_switch *ds, int port,
  				       const struct dsa_bridge bridge)
  {
@@ -998,7 +997,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	struct mxl862xx_priv *priv = ds->priv;
  	struct mxl862xx_port *p = &priv->ports[port];
  	int err;
-@@ -1595,34 +1972,587 @@ static void mxl862xx_port_bridge_leave(s
+@@ -1550,34 +1927,587 @@ static void mxl862xx_port_bridge_leave(s
  	 * single-port bridge
  	 */
  	bitmap_zero(p->portmap, MXL862XX_MAX_BRIDGE_PORTS);
@@ -1010,14 +1009,14 @@ Signed-off-by: Daniel Golle <[email protected]>
 -	/* Detach EVLAN and VF blocks from the bridge port BEFORE freeing
 -	 * them. The firmware tracks a usage count per block and rejects
 -	 * FREE while the count is non-zero.
+-	 *
+-	 * For EVLAN: setting in_use=false makes set_bridge_port send
+-	 * enable=false, which decrements the firmware refcount.
 +	/* Reset VLAN state for standalone mode. Ingress EVLAN is not
 +	 * needed outside a VLAN-aware bridge. Egress EVLAN is
 +	 * reprogrammed below -- in tag_8021q mode it gets the
 +	 * management VID strip catchalls, in SpTag mode it is cleared.
  	 *
--	 * For EVLAN: setting in_use=false makes set_bridge_port send
--	 * enable=false, which decrements the firmware refcount.
--	 *
 -	 * For VF: set_bridge_port sees dp->bridge == NULL (DSA already
 -	 * cleared it) and sends vlan_filter_enable=0, which decrements
 -	 * the firmware VF refcount.
@@ -1597,7 +1596,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_setup(struct dsa_switch *ds, int port)
  {
  	struct mxl862xx_priv *priv = ds->priv;
-@@ -1642,55 +2572,30 @@ static int mxl862xx_port_setup(struct ds
+@@ -1597,55 +2527,30 @@ static int mxl862xx_port_setup(struct ds
  	    dsa_port_is_dsa(dp))
  		return 0;
  
@@ -1660,7 +1659,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return 0;
  }
  
-@@ -1712,7 +2617,7 @@ static void mxl862xx_port_teardown(struc
+@@ -1667,7 +2572,7 @@ static void mxl862xx_port_teardown(struc
  	priv->ports[port].setup_done = false;
  }
  
@@ -1669,7 +1668,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  {
  	struct mxl862xx_priv *priv = ds->priv;
  
-@@ -1730,23 +2635,244 @@ static int mxl862xx_get_fid(struct dsa_s
+@@ -1685,23 +2590,244 @@ static int mxl862xx_get_fid(struct dsa_s
  	}
  }
  
@@ -1702,7 +1701,8 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	if (dsa_is_cpu_port(ds, port) && priv->tag_proto == DSA_TAG_PROTO_MXL862_8021Q &&
 +	    db.type == DSA_DB_PORT) {
 +		bp_cpu = priv->ports[db.dp->index].bridge_port_cpu;
-+
+ 
+-	param.port_id = cpu_to_le32(port);
 +		if (bp_cpu)
 +			return bp_cpu;
 +	}
@@ -1719,8 +1719,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +{
 +	struct mxl862xx_mac_table_add param = {};
 +	struct mxl862xx_priv *priv = ds->priv;
- 
--	param.port_id = cpu_to_le32(port);
++
 +	param.port_id = cpu_to_le32(port_id);
  	param.static_entry = true;
  	param.fid = cpu_to_le16(fid);
@@ -1922,7 +1921,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	if (ret)
  		dev_err(ds->dev, "failed to add FDB entry on port %d\n", port);
  
-@@ -1756,18 +2882,25 @@ static int mxl862xx_port_fdb_add(struct
+@@ -1711,18 +2837,25 @@ static int mxl862xx_port_fdb_add(struct
  static int mxl862xx_port_fdb_del(struct dsa_switch *ds, int port,
  				 const unsigned char *addr, u16 vid, const struct dsa_db db)
  {
@@ -1955,7 +1954,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	if (ret)
  		dev_err(ds->dev, "failed to remove FDB entry on port %d\n", port);
  
-@@ -1806,88 +2939,147 @@ static int mxl862xx_port_fdb_dump(struct
+@@ -1761,88 +2894,147 @@ static int mxl862xx_port_fdb_dump(struct
  	return 0;
  }
  
@@ -2097,7 +2096,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 -	int fid = mxl862xx_get_fid(ds, db), ret;
  	struct mxl862xx_priv *priv = ds->priv;
 +	int fid, ret;
-+
+ 
 +	/* tag_8021q host MDB for bridged ports: clear all VBP bits */
 +	if (priv->tag_proto == DSA_TAG_PROTO_MXL862_8021Q && dsa_is_cpu_port(ds, port) &&
 +	    db.type == DSA_DB_BRIDGE) {
@@ -2107,7 +2106,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +		return mxl862xx_mac_del_host_bridge(ds, mdb->addr,
 +						    mdb->vid, &db.bridge);
 +	}
- 
++
 +	fid = mxl862xx_get_fid(ds, db);
  	if (fid < 0)
  		return fid;
@@ -2154,7 +2153,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	return ret;
  }
-@@ -1975,7 +3167,9 @@ static void mxl862xx_host_flood_work_fn(
+@@ -1930,7 +3122,9 @@ static void mxl862xx_host_flood_work_fn(
  	struct mxl862xx_priv *priv = p->priv;
  	struct dsa_switch *ds = priv->ds;
  	int port = p - priv->ports;
@@ -2164,7 +2163,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	rtnl_lock();
  
-@@ -1988,14 +3182,31 @@ static void mxl862xx_host_flood_work_fn(
+@@ -1943,14 +3137,35 @@ static void mxl862xx_host_flood_work_fn(
  	uc = p->host_flood_uc;
  	mc = p->host_flood_mc;
  
@@ -2195,8 +2194,12 @@ Signed-off-by: Daniel Golle <[email protected]>
 +					port, ERR_PTR(ret));
 +		}
 +	} else {
-+		/* SpTag mode: per-FID forwarding, only works for
-+		 * standalone ports (each has its own FID).
++		/* The hardware controls unknown-unicast/multicast forwarding
++		 * per FID (bridge), not per source port. For bridged ports all
++		 * members share one FID, so we cannot selectively suppress
++		 * flooding to the CPU for one source port while allowing it
++		 * for another. Silently ignore the request -- the excess
++		 * flooding towards the CPU is harmless.
 +		 */
 +		if (!dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
 +			mxl862xx_bridge_config_fwd(ds, p->fid, uc, mc, true);
@@ -2204,7 +2207,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	rtnl_unlock();
  }
-@@ -2330,7 +3541,9 @@ static void mxl862xx_get_stats64(struct
+@@ -2285,7 +3500,9 @@ static void mxl862xx_get_stats64(struct
  
  static const struct dsa_switch_ops mxl862xx_switch_ops = {
  	.get_tag_protocol = mxl862xx_get_tag_protocol,
@@ -2214,7 +2217,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	.port_setup = mxl862xx_port_setup,
  	.port_teardown = mxl862xx_port_teardown,
  	.phylink_get_caps = mxl862xx_phylink_get_caps,
-@@ -2352,6 +3565,8 @@ static const struct dsa_switch_ops mxl86
+@@ -2307,6 +3524,8 @@ static const struct dsa_switch_ops mxl86
  	.port_vlan_filtering = mxl862xx_port_vlan_filtering,
  	.port_vlan_add = mxl862xx_port_vlan_add,
  	.port_vlan_del = mxl862xx_port_vlan_del,
@@ -2223,7 +2226,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	.get_strings = mxl862xx_get_strings,
  	.get_sset_count = mxl862xx_get_sset_count,
  	.get_ethtool_stats = mxl862xx_get_ethtool_stats,
-@@ -2399,6 +3614,8 @@ static int mxl862xx_probe(struct mdio_de
+@@ -2354,6 +3573,8 @@ static int mxl862xx_probe(struct mdio_de
  
  	INIT_DELAYED_WORK(&priv->stats_work, mxl862xx_stats_work_fn);
  
@@ -2231,10 +2234,10 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dev_set_drvdata(dev, ds);
  
- 	return dsa_register_switch(ds);
-@@ -2415,16 +3632,29 @@ static void mxl862xx_remove(struct mdio_
- 
- 	priv = ds->priv;
+ 	err = dsa_register_switch(ds);
+@@ -2382,6 +3603,19 @@ static void mxl862xx_remove(struct mdio_
+ 	set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
+ 	cancel_delayed_work_sync(&priv->stats_work);
  
 +	/* Tear down tag_8021q under RTNL before dsa_unregister_switch().
 +	 * dsa_tag_8021q_unregister() calls vlan_vid_del() which needs
@@ -2251,39 +2254,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dsa_unregister_switch(ds);
  
- 	cancel_delayed_work_sync(&priv->stats_work);
- 
  	mxl862xx_host_shutdown(priv);
- 
--	/* Cancel any pending host flood work.  dsa_unregister_switch()
-+	/* Cancel any pending host flood work. dsa_unregister_switch()
- 	 * has already called port_teardown (which sets setup_done=false),
- 	 * but a worker could still be blocked on rtnl_lock(). Since we
--	 * are now outside RTNL, cancel_work_sync() will not deadlock.
-+	 * are now outside RTNL, cancel_work_sync() won't deadlock.
- 	 */
- 	for (i = 0; i < MXL862XX_MAX_PORTS; i++)
- 		cancel_work_sync(&priv->ports[i].host_flood_work);
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
-@@ -8,8 +8,6 @@
- #include <linux/workqueue.h>
- #include <net/dsa.h>
- 
--struct mxl862xx_priv;
--
- #define MXL862XX_MAX_PORTS		17
- #define MXL862XX_DEFAULT_BRIDGE		0
- #define MXL862XX_MAX_BRIDGES		48
-@@ -20,6 +18,8 @@ struct mxl862xx_priv;
- /* Number of __le16 words in a firmware portmap (128-bit bitmap). */
- #define MXL862XX_FW_PORTMAP_WORDS	(MXL862XX_MAX_BRIDGE_PORTS / 16)
- 
-+struct mxl862xx_priv;
-+
- /**
-  * mxl862xx_fw_portmap_from_bitmap - convert a kernel bitmap to a firmware
-  *                                   portmap (__le16[8])
 @@ -210,6 +210,9 @@ struct mxl862xx_port_stats {
   * @vf:                  per-port VLAN Filter block state
   * @ingress_evlan:       ingress extended VLAN block state
@@ -2317,39 +2290,31 @@ Signed-off-by: Daniel Golle <[email protected]>
  	/* Hardware stats accumulation */
  	struct mxl862xx_port_stats stats;
  	spinlock_t stats_lock;
-@@ -302,6 +311,7 @@ union mxl862xx_fw_version {
-  *                      errors
-  * @crc_err:            set atomically before CRC-triggered shutdown, cleared
-  *                      after
+@@ -308,6 +317,7 @@ union mxl862xx_fw_version {
+  *                      before CRC-triggered shutdown and cleared after;
+  *                      %MXL862XX_FLAG_WORK_STOPPED is set before cancelling
+  *                      stats_work to prevent rescheduling during teardown
 + * @tag_proto:          active DSA tag protocol (native or 8021q)
   * @drop_meter:         index of the single shared zero-rate firmware meter
   *                      used to unconditionally drop traffic (used to block
   *                      flooding)
-@@ -310,12 +320,13 @@ union mxl862xx_fw_version {
-  * @serdes_ports:       SerDes interfaces incl. sub-interfaces in case of
-  *                      10G_QXGMII
-  * @ports:              per-port state, indexed by switch port number
-+ * @evlan_ingress_size: per-port ingress Extended VLAN block size
-+ * @evlan_egress_size:  per-port egress Extended VLAN block size
-+ * @cpu_evlan_ingress_size: CPU port ingress EVLAN block size (tag_8021q)
-  * @bridges:            maps DSA bridge number to firmware bridge ID;
-  *                      zero means no firmware bridge allocated for that
-  *                      DSA bridge number. Indexed by dsa_bridge.num
+@@ -322,6 +332,7 @@ union mxl862xx_fw_version {
   *                      (0 .. ds->max_num_bridges).
-- * @evlan_ingress_size: per-port ingress Extended VLAN block size
-- * @evlan_egress_size:  per-port egress Extended VLAN block size
+  * @evlan_ingress_size: per-port ingress Extended VLAN block size
+  * @evlan_egress_size:  per-port egress Extended VLAN block size
++ * @cpu_evlan_ingress_size: CPU port ingress EVLAN block size (tag_8021q)
   * @vf_block_size:      per-port VLAN Filter block size
   * @stats_work:         periodic work item that polls RMON hardware counters
   *                      and accumulates them into 64-bit per-port stats
-@@ -325,6 +336,7 @@ struct mxl862xx_priv {
+@@ -331,6 +342,7 @@ struct mxl862xx_priv {
  	struct mdio_device *mdiodev;
  	struct work_struct crc_err_work;
- 	unsigned long crc_err;
+ 	unsigned long flags;
 +	enum dsa_tag_protocol tag_proto;
  	u16 drop_meter;
  	union mxl862xx_fw_version fw_version;
  	struct mxl862xx_pcs serdes_ports[8];
-@@ -332,6 +344,7 @@ struct mxl862xx_priv {
+@@ -338,6 +350,7 @@ struct mxl862xx_priv {
  	u16 bridges[MXL862XX_MAX_BRIDGES + 1];
  	u16 evlan_ingress_size;
  	u16 evlan_egress_size;
@@ -2359,16 +2324,15 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
 --- a/include/net/dsa.h
 +++ b/include/net/dsa.h
-@@ -56,6 +56,8 @@ struct tc_action;
+@@ -56,6 +56,7 @@ struct tc_action;
  #define DSA_TAG_PROTO_VSC73XX_8021Q_VALUE	28
  #define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE	29
  #define DSA_TAG_PROTO_MXL862_VALUE		30
 +#define DSA_TAG_PROTO_MXL862_8021Q_VALUE	31
-+
  
  enum dsa_tag_protocol {
  	DSA_TAG_PROTO_NONE		= DSA_TAG_PROTO_NONE_VALUE,
-@@ -89,6 +91,7 @@ enum dsa_tag_protocol {
+@@ -89,6 +90,7 @@ enum dsa_tag_protocol {
  	DSA_TAG_PROTO_LAN937X		= DSA_TAG_PROTO_LAN937X_VALUE,
  	DSA_TAG_PROTO_VSC73XX_8021Q	= DSA_TAG_PROTO_VSC73XX_8021Q_VALUE,
  	DSA_TAG_PROTO_MXL862		= DSA_TAG_PROTO_MXL862_VALUE,

+ 16 - 16
target/linux/generic/pending-6.12/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch

@@ -1,7 +1,7 @@
-From 31359e8b7673e656d0591a9eb5014b45911383ae Mon Sep 17 00:00:00 2001
+From 4e1d854199c166f617b93b7542e863e6a8ad2ccb Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 03:44:41 +0000
-Subject: [PATCH 26/35] net: dsa: mxl862xx: add link aggregation support
+Subject: [PATCH 17/26] net: dsa: mxl862xx: add link aggregation support
 
 Implement LAG offloading via the firmware's trunking engine.  A
 dedicated firmware bridge port is allocated per LAG and remains
@@ -234,7 +234,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return ret;
  }
  
-@@ -1926,6 +2018,408 @@ static int mxl862xx_setup_cpu_bridge(str
+@@ -1881,6 +1973,408 @@ static int mxl862xx_setup_cpu_bridge(str
  	return mxl862xx_set_bridge_port(ds, port);
  }
  
@@ -643,7 +643,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_bridge_join(struct dsa_switch *ds, int port,
  				     const struct dsa_bridge bridge,
  				     bool *tx_fwd_offload,
-@@ -1952,7 +2446,18 @@ static int mxl862xx_port_bridge_join(str
+@@ -1907,7 +2401,18 @@ static int mxl862xx_port_bridge_join(str
  		return 0;
  	}
  
@@ -663,7 +663,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static void mxl862xx_port_bridge_leave(struct dsa_switch *ds, int port,
-@@ -2011,6 +2516,17 @@ static void mxl862xx_port_bridge_leave(s
+@@ -1966,6 +2471,17 @@ static void mxl862xx_port_bridge_leave(s
  			"failed to update CPU VBP for port %d: %pe\n", port,
  			ERR_PTR(err));
  
@@ -681,7 +681,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	if (!dsa_bridge_ports(ds, bridge.dev))
  		mxl862xx_free_bridge(ds, &bridge);
  }
-@@ -2636,18 +3152,17 @@ static int mxl862xx_get_fid(struct dsa_s
+@@ -2591,18 +3107,17 @@ static int mxl862xx_get_fid(struct dsa_s
  }
  
  /**
@@ -707,7 +707,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   */
  static int mxl862xx_fdb_bridge_port(struct dsa_switch *ds, int port,
  				    const struct dsa_db db)
-@@ -2663,7 +3178,7 @@ static int mxl862xx_fdb_bridge_port(stru
+@@ -2618,7 +3133,7 @@ static int mxl862xx_fdb_bridge_port(stru
  			return bp_cpu;
  	}
  
@@ -716,7 +716,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  /**
-@@ -2907,11 +3422,43 @@ static int mxl862xx_port_fdb_del(struct
+@@ -2862,11 +3377,43 @@ static int mxl862xx_port_fdb_del(struct
  	return ret;
  }
  
@@ -760,7 +760,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	u32 entry_port_id;
  	int ret;
  
-@@ -2925,7 +3472,7 @@ static int mxl862xx_port_fdb_dump(struct
+@@ -2880,7 +3427,7 @@ static int mxl862xx_port_fdb_dump(struct
  
  		entry_port_id = le32_to_cpu(param.port_id);
  
@@ -769,7 +769,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  			ret = cb(param.mac, FIELD_GET(MXL862XX_TCI_VLAN_ID,
  						      le16_to_cpu(param.tci)),
  				 param.static_entry, data);
-@@ -3562,6 +4109,11 @@ static const struct dsa_switch_ops mxl86
+@@ -3521,6 +4068,11 @@ static const struct dsa_switch_ops mxl86
  	.port_fdb_dump = mxl862xx_port_fdb_dump,
  	.port_mdb_add = mxl862xx_port_mdb_add,
  	.port_mdb_del = mxl862xx_port_mdb_del,
@@ -781,7 +781,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	.port_vlan_filtering = mxl862xx_port_vlan_filtering,
  	.port_vlan_add = mxl862xx_port_vlan_add,
  	.port_vlan_del = mxl862xx_port_vlan_del,
-@@ -3602,6 +4154,7 @@ static int mxl862xx_probe(struct mdio_de
+@@ -3561,6 +4113,7 @@ static int mxl862xx_probe(struct mdio_de
  	ds->num_ports = MXL862XX_MAX_PORTS;
  	ds->fdb_isolation = true;
  	ds->max_num_bridges = MXL862XX_MAX_BRIDGES;
@@ -791,7 +791,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
-@@ -14,6 +14,19 @@
+@@ -16,6 +16,19 @@ struct mxl862xx_priv;
  #define MXL862XX_MAX_BRIDGE_PORTS	128
  #define MXL862XX_TOTAL_EVLAN_ENTRIES	1024
  #define MXL862XX_TOTAL_VF_ENTRIES	1024
@@ -835,9 +835,9 @@ Signed-off-by: Daniel Golle <[email protected]>
  	/* Hardware stats accumulation */
  	struct mxl862xx_port_stats stats;
  	spinlock_t stats_lock;
-@@ -328,6 +351,15 @@ union mxl862xx_fw_version {
-  *                      DSA bridge number. Indexed by dsa_bridge.num
-  *                      (0 .. ds->max_num_bridges).
+@@ -334,6 +357,15 @@ union mxl862xx_fw_version {
+  * @evlan_egress_size:  per-port egress Extended VLAN block size
+  * @cpu_evlan_ingress_size: CPU port ingress EVLAN block size (tag_8021q)
   * @vf_block_size:      per-port VLAN Filter block size
 + * @lag_bridge_ports:   maps DSA LAG ID to firmware bridge port ID;
 + *                      zero means no bridge port allocated for that LAG.
@@ -851,7 +851,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @stats_work:         periodic work item that polls RMON hardware counters
   *                      and accumulates them into 64-bit per-port stats
   */
-@@ -346,6 +378,8 @@ struct mxl862xx_priv {
+@@ -352,6 +384,8 @@ struct mxl862xx_priv {
  	u16 evlan_egress_size;
  	u16 cpu_evlan_ingress_size;
  	u16 vf_block_size;

+ 7 - 7
target/linux/generic/pending-6.12/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch

@@ -1,7 +1,7 @@
-From fbfa1b0649c578e0d43e3a61617b53a9a722efad Mon Sep 17 00:00:00 2001
+From 5528f38c3d709417625eb7f36628be31727a8221 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 12:05:29 +0000
-Subject: [PATCH 27/35] net: dsa: mxl862xx: add support for mirror port
+Subject: [PATCH 18/26] net: dsa: mxl862xx: add support for mirror port
 
 The MxL862xx hardware supports a single monitor port which can be
 configured to mirror any other port's ingress and/or egress traffic.
@@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #define MXL862XX_TFLOW_PCERULEWRITE	(MXL862XX_TFLOW_MAGIC + 0x2)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -1129,6 +1129,8 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -1084,6 +1084,8 @@ static int mxl862xx_setup(struct dsa_swi
  				      (n_user_ports + n_cpu_ports);
  	}
  
@@ -59,7 +59,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	ret = mxl862xx_setup_drop_meter(ds);
  	if (ret)
  		return ret;
-@@ -2018,6 +2020,120 @@ static int mxl862xx_setup_cpu_bridge(str
+@@ -1973,6 +1975,120 @@ static int mxl862xx_setup_cpu_bridge(str
  	return mxl862xx_set_bridge_port(ds, port);
  }
  
@@ -180,7 +180,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  /**
   * mxl862xx_lag_master_port - Find the LAG master (lowest-numbered member)
   * @ds: DSA switch
-@@ -4109,6 +4225,8 @@ static const struct dsa_switch_ops mxl86
+@@ -4068,6 +4184,8 @@ static const struct dsa_switch_ops mxl86
  	.port_fdb_dump = mxl862xx_port_fdb_dump,
  	.port_mdb_add = mxl862xx_port_mdb_add,
  	.port_mdb_del = mxl862xx_port_mdb_del,
@@ -210,7 +210,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	/* LAG state */
  	struct dsa_lag *lag;
  	bool lag_tx_enabled;
-@@ -360,6 +365,8 @@ union mxl862xx_fw_version {
+@@ -366,6 +371,8 @@ union mxl862xx_fw_version {
   * @trunk_hash:         current global hash field bitmask (6 bits,
   *                      MXL862XX_TRUNK_HASH_*); union of all active LAGs'
   *                      hash requirements
@@ -219,7 +219,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @stats_work:         periodic work item that polls RMON hardware counters
   *                      and accumulates them into 64-bit per-port stats
   */
-@@ -380,6 +387,7 @@ struct mxl862xx_priv {
+@@ -386,6 +393,7 @@ struct mxl862xx_priv {
  	u16 vf_block_size;
  	u16 lag_bridge_ports[MXL862XX_MAX_LAG_IDS + 1];
  	u8 trunk_hash;

+ 3 - 3
target/linux/generic/pending-6.12/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch

@@ -1,7 +1,7 @@
-From 67f82834819b71417b58dc1293c20f71b990264f Mon Sep 17 00:00:00 2001
+From 4059d35a5bbf1901b2e0eb7126369cd713cacfce Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 16:30:08 +0000
-Subject: [PATCH 28/35] net: dsa: wire flash_update devlink callback to drivers
+Subject: [PATCH 19/26] net: dsa: wire flash_update devlink callback to drivers
 
 Add a devlink_flash_update callback to dsa_switch_ops so that DSA
 drivers can support devlink dev flash without open-coding the devlink
@@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 
 --- a/include/net/dsa.h
 +++ b/include/net/dsa.h
-@@ -1186,6 +1186,9 @@ struct dsa_switch_ops {
+@@ -1185,6 +1185,9 @@ struct dsa_switch_ops {
  	int	(*devlink_info_get)(struct dsa_switch *ds,
  				    struct devlink_info_req *req,
  				    struct netlink_ext_ack *extack);

+ 2 - 2
target/linux/generic/pending-6.12/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch

@@ -1,7 +1,7 @@
-From 1a87b829ef3280d646dc480f7b261d9e32896899 Mon Sep 17 00:00:00 2001
+From 0145151dc68aa318d8addb6fe7f12c0967f951da Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 16:30:17 +0000
-Subject: [PATCH 29/35] net: dsa: mxl862xx: add SMDIO clause-22 register access
+Subject: [PATCH 20/26] net: dsa: mxl862xx: add SMDIO clause-22 register access
 
 Add mxl862xx_smdio_read() and mxl862xx_smdio_write() for clause-22
 SMDIO register access. MCUboot rescue mode only exposes clause-22

+ 4 - 4
target/linux/generic/pending-6.12/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch

@@ -1,7 +1,7 @@
-From b7e8f8fd4493b255f0f01fe790a73ad61b5e8ce8 Mon Sep 17 00:00:00 2001
+From bdbca48510e3e96ed9210f20fa4244dd6df5d44a Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 16:30:31 +0000
-Subject: [PATCH 30/35] net: dsa: mxl862xx: add devlink flash_update and
+Subject: [PATCH 21/26] net: dsa: mxl862xx: add devlink flash_update and
  info_get
 
 Implement runtime firmware upgrade via "devlink dev flash" and version
@@ -546,7 +546,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #include "mxl862xx-host.h"
  #include "mxl862xx-phylink.h"
  
-@@ -4245,6 +4246,9 @@ static const struct dsa_switch_ops mxl86
+@@ -4204,6 +4205,9 @@ static const struct dsa_switch_ops mxl86
  	.get_pause_stats = mxl862xx_get_pause_stats,
  	.get_stats64 = mxl862xx_get_stats64,
  	.self_test = mxl862xx_serdes_self_test,
@@ -558,7 +558,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_probe(struct mdio_device *mdiodev)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
-@@ -388,6 +388,8 @@ struct mxl862xx_priv {
+@@ -394,6 +394,8 @@ struct mxl862xx_priv {
  	u16 lag_bridge_ports[MXL862XX_MAX_LAG_IDS + 1];
  	u8 trunk_hash;
  	int mirror_dest;

+ 4 - 4
target/linux/generic/pending-6.12/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch

@@ -1,7 +1,7 @@
-From 2cb9aeb3a8d7ebac20331e0a533dcfbd73fa4237 Mon Sep 17 00:00:00 2001
+From 8deb5be9638f7eb3009ed3eb619eedadee1df523 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 23:42:18 +0000
-Subject: [PATCH 31/35] net: dsa: mxl862xx: implement port MTU configuration
+Subject: [PATCH 22/26] net: dsa: mxl862xx: implement port MTU configuration
 
 The firmware exposes a global max_packet_len register via
 MXL862XX_COMMON_CFGSET. Since this is switch-wide rather than
@@ -25,7 +25,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #include <linux/module.h>
  #include <linux/of_device.h>
  #include <linux/of_mdio.h>
-@@ -3768,6 +3769,53 @@ static int mxl862xx_set_ageing_time(stru
+@@ -3723,6 +3724,53 @@ static int mxl862xx_set_ageing_time(stru
  	return ret;
  }
  
@@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static void mxl862xx_port_stp_state_set(struct dsa_switch *ds, int port,
  					u8 state)
  {
-@@ -4215,6 +4263,8 @@ static const struct dsa_switch_ops mxl86
+@@ -4174,6 +4222,8 @@ static const struct dsa_switch_ops mxl86
  	.port_disable = mxl862xx_port_disable,
  	.port_fast_age = mxl862xx_port_fast_age,
  	.set_ageing_time = mxl862xx_set_ageing_time,

+ 18 - 19
target/linux/generic/pending-6.12/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch

@@ -1,7 +1,7 @@
-From d55ca68eb0d20a66c32d531b0a454871b486c1b1 Mon Sep 17 00:00:00 2001
+From 13a4c918cd9ded7207f38033511ab13f7aff9bd2 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 01:47:19 +0000
-Subject: [PATCH 32/35] net: dsa: mxl862xx: support BR_HAIRPIN_MODE bridge flag
+Subject: [PATCH 23/26] net: dsa: mxl862xx: support BR_HAIRPIN_MODE bridge flag
 
 Implement hairpin mode by including the port's own bridge port ID in
 its forwarding portmap. When hairpin is enabled, bridged frames whose
@@ -18,9 +18,9 @@ bridge member rebuild since only the calling port is affected.
 
 Signed-off-by: Daniel Golle <[email protected]>
 ---
- drivers/net/dsa/mxl862xx/mxl862xx.c | 30 ++++++++++++++++++++++++++++-
+ drivers/net/dsa/mxl862xx/mxl862xx.c | 29 +++++++++++++++++++++++++++--
  drivers/net/dsa/mxl862xx/mxl862xx.h |  6 ++++++
- 2 files changed, 35 insertions(+), 1 deletion(-)
+ 2 files changed, 33 insertions(+), 2 deletions(-)
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
@@ -40,7 +40,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		err = mxl862xx_set_bridge_port(ds, port);
  		if (err)
  			ret = err;
-@@ -3939,7 +3948,7 @@ static int mxl862xx_port_pre_bridge_flag
+@@ -3898,7 +3907,7 @@ static int mxl862xx_port_pre_bridge_flag
  					  struct netlink_ext_ack *extack)
  {
  	if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD |
@@ -49,20 +49,19 @@ Signed-off-by: Daniel Golle <[email protected]>
  		return -EINVAL;
  
  	return 0;
-@@ -3954,6 +3963,7 @@ static int mxl862xx_port_bridge_flags(st
+@@ -3912,6 +3921,7 @@ static int mxl862xx_port_bridge_flags(st
+ 	unsigned long old_block = priv->ports[port].flood_block;
  	unsigned long block = old_block;
- 	bool need_update = false;
  	int ret;
 +	u16 bp;
  
  	if (flags.mask & BR_FLOOD) {
  		if (flags.val & BR_FLOOD)
-@@ -3988,6 +3998,24 @@ static int mxl862xx_port_bridge_flags(st
- 		ret = mxl862xx_set_bridge_port(ds, port);
- 		if (ret)
- 			return ret;
-+	}
-+
+@@ -3940,7 +3950,22 @@ static int mxl862xx_port_bridge_flags(st
+ 	if (flags.mask & BR_LEARNING)
+ 		priv->ports[port].learning = !!(flags.val & BR_LEARNING);
+ 
+-	if ((block != old_block) || (flags.mask & BR_LEARNING)) {
 +	if (flags.mask & BR_HAIRPIN_MODE) {
 +		bp = mxl862xx_lag_bridge_port(priv, port);
 +		priv->ports[port].hairpin = !!(flags.val & BR_HAIRPIN_MODE);
@@ -75,13 +74,13 @@ Signed-off-by: Daniel Golle <[email protected]>
 +			__set_bit(bp, priv->ports[port].portmap);
 +		else
 +			__clear_bit(bp, priv->ports[port].portmap);
++	}
 +
-+		ret = mxl862xx_set_bridge_port(ds, port);
-+		if (ret)
-+			return ret;
- 	}
- 
- 	return 0;
++	if ((block != old_block) ||
++	    (flags.mask & (BR_LEARNING | BR_HAIRPIN_MODE))) {
+ 		priv->ports[port].flood_block = block;
+ 		ret = mxl862xx_set_bridge_port(ds, port);
+ 		if (ret)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
 @@ -241,6 +241,10 @@ struct mxl862xx_port_stats {

+ 6 - 6
target/linux/generic/pending-6.12/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch

@@ -1,7 +1,7 @@
-From 74b6654ba74eb142340de4c51b97c0221cfcae37 Mon Sep 17 00:00:00 2001
+From d49d1f8bee29269def7593f980d0e08bfb5c3ef8 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 01:51:33 +0000
-Subject: [PATCH 33/35] net: dsa: mxl862xx: support BR_ISOLATED bridge flag
+Subject: [PATCH 24/26] net: dsa: mxl862xx: support BR_ISOLATED bridge flag
 
 Implement port isolation by excluding isolated ports from each other's
 forwarding portmaps in sync_bridge_members. Non-isolated ports can
@@ -34,7 +34,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  			if (member != port) {
  				bp = mxl862xx_lag_bridge_port(priv,
  							     member);
-@@ -3948,7 +3956,7 @@ static int mxl862xx_port_pre_bridge_flag
+@@ -3907,7 +3915,7 @@ static int mxl862xx_port_pre_bridge_flag
  					  struct netlink_ext_ack *extack)
  {
  	if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD |
@@ -43,15 +43,15 @@ Signed-off-by: Daniel Golle <[email protected]>
  		return -EINVAL;
  
  	return 0;
-@@ -3962,6 +3970,7 @@ static int mxl862xx_port_bridge_flags(st
+@@ -3920,6 +3928,7 @@ static int mxl862xx_port_bridge_flags(st
+ 	struct mxl862xx_priv *priv = ds->priv;
  	unsigned long old_block = priv->ports[port].flood_block;
  	unsigned long block = old_block;
- 	bool need_update = false;
 +	struct dsa_port *dp;
  	int ret;
  	u16 bp;
  
-@@ -4018,6 +4027,21 @@ static int mxl862xx_port_bridge_flags(st
+@@ -3972,6 +3981,21 @@ static int mxl862xx_port_bridge_flags(st
  			return ret;
  	}
  

+ 3 - 3
target/linux/generic/pending-6.12/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch

@@ -1,7 +1,7 @@
-From 0902a6790750714445c75a66d60f1bc4897126ce Mon Sep 17 00:00:00 2001
+From c2fb7f0df63ac994850f766e7f2eb50c6c5ef2cf Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:17:49 +0000
-Subject: [PATCH 34/35] DO NOT SUBMIT: net: dsa: mxl862xx: re-introduce PCE
+Subject: [PATCH 25/26] DO NOT SUBMIT: net: dsa: mxl862xx: re-introduce PCE
  workaround for old firmware
 
 Re-introduce the mxl862xx_disable_fw_global_rules() function that
@@ -64,7 +64,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  /* Per-CTP offset used for the link-local trap rule. Each port's CTP
   * flow-table block is pre-allocated by the firmware during init (44
-@@ -1154,9 +1191,11 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -1109,9 +1146,11 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  

+ 2 - 2
target/linux/generic/pending-6.12/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch

@@ -1,7 +1,7 @@
-From 0ac876d5b952218ab79ea0a0815cf6fd1290b1d0 Mon Sep 17 00:00:00 2001
+From f0548f842b9ff31f19452a2fc72a16f937d86008 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:19:56 +0000
-Subject: [PATCH 35/35] DO NOT SUBMIT: net: dsa: mxl862xx: legacy SFP API
+Subject: [PATCH 26/26] DO NOT SUBMIT: net: dsa: mxl862xx: legacy SFP API
  fallback for old firmware
 
 Re-introduce the SYS_MISC_SFP_SET-based PCS implementation as a

+ 37 - 0
target/linux/generic/pending-6.18/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch

@@ -0,0 +1,37 @@
+From 3fd163f5bb88de426ca9847549f94b4296170ef0 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Mon, 30 Mar 2026 23:40:53 +0100
+Subject: [PATCH] net: dsa: mxl862xx: cancel pending work on probe error
+
+Call mxl862xx_host_shutdown() in case dsa_register_switch() returns
+an error, so any still pending crc_err_work get canceled.
+
+Fixes: a319d0c8c8ced ("net: dsa: mxl862xx: add CRC for MDIO communication)"
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ drivers/net/dsa/mxl862xx/mxl862xx.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/dsa/mxl862xx/mxl862xx.c
++++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
+@@ -407,6 +407,7 @@ static int mxl862xx_probe(struct mdio_de
+ 	struct device *dev = &mdiodev->dev;
+ 	struct mxl862xx_priv *priv;
+ 	struct dsa_switch *ds;
++	int err;
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv)
+@@ -428,7 +429,11 @@ static int mxl862xx_probe(struct mdio_de
+ 
+ 	dev_set_drvdata(dev, ds);
+ 
+-	return dsa_register_switch(ds);
++	err = dsa_register_switch(ds);
++	if (err)
++		mxl862xx_host_shutdown(priv);
++
++	return err;
+ }
+ 
+ static void mxl862xx_remove(struct mdio_device *mdiodev)

+ 3 - 3
target/linux/generic/pending-6.18/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch

@@ -1,7 +1,7 @@
-From de6dd19a3edd1dc6400fecf77610e438441a02ac Mon Sep 17 00:00:00 2001
+From cd698f1ae94c16499e2714b31dd6048e6f9f068d Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:54:11 +0000
-Subject: [PATCH 10/35] net: dsa: move dsa_bridge_ports() helper to dsa.h
+Subject: [PATCH 01/26] net: dsa: move dsa_bridge_ports() helper to dsa.h
 
 The yt921x driver contains a helper to create a bitmap of ports
 which are members of a bridge.
@@ -12,7 +12,7 @@ can make use of it as well.
 Signed-off-by: Daniel Golle <[email protected]>
 ---
  include/net/dsa.h | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
+ 2 files changed, 13 insertions(+), 13 deletions(-)
 
 --- a/include/net/dsa.h
 +++ b/include/net/dsa.h

+ 2 - 2
target/linux/generic/pending-6.18/760-02-net-dsa-add-bridge-member-iteration-macro.patch

@@ -1,7 +1,7 @@
-From 880cde7abf58cb1316382ae7f59aac93c313e8fe Mon Sep 17 00:00:00 2001
+From c161533e1605a7282563c139323a3913890fdb72 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:54:41 +0000
-Subject: [PATCH 11/35] net: dsa: add bridge member iteration macro
+Subject: [PATCH 02/26] net: dsa: add bridge member iteration macro
 
 Drivers that offload bridges need to iterate over the ports that are
 members of a given bridge, for example to rebuild per-port forwarding

+ 2 - 2
target/linux/generic/pending-6.18/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch

@@ -1,7 +1,7 @@
-From 149bb02d5bf031a1eb85f91377f54913de3a08ff Mon Sep 17 00:00:00 2001
+From 753efe27a9afee52c4ad42098a9b9278366d63cc Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:54:52 +0000
-Subject: [PATCH 12/35] dsa: tag_mxl862xx: set dsa_default_offload_fwd_mark()
+Subject: [PATCH 03/26] dsa: tag_mxl862xx: set dsa_default_offload_fwd_mark()
 
 The MxL862xx offloads bridge forwarding in hardware, so set
 dsa_default_offload_fwd_mark() to avoid duplicate forwarding of

+ 34 - 37
target/linux/generic/pending-6.18/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch

@@ -1,7 +1,7 @@
-From 5acdee6df2fbd4a9b02045694227f25cb1d4e5e0 Mon Sep 17 00:00:00 2001
+From ce0664ff8f75c3ab01101c3f0f8569924d948775 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 17:55:08 +0000
-Subject: [PATCH 13/35] net: dsa: mxl862xx: implement bridge offloading
+Subject: [PATCH 04/26] net: dsa: mxl862xx: implement bridge offloading
 
 Implement joining and leaving bridges as well as add, delete and dump
 operations on isolated FDBs, port MDB membership management, and
@@ -39,9 +39,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 ---
  drivers/net/dsa/mxl862xx/mxl862xx-api.h | 225 ++++++-
  drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |  20 +-
- drivers/net/dsa/mxl862xx/mxl862xx.c     | 752 ++++++++++++++++++++++--
+ drivers/net/dsa/mxl862xx/mxl862xx.c     | 743 ++++++++++++++++++++++--
  drivers/net/dsa/mxl862xx/mxl862xx.h     | 133 +++++
- 4 files changed, 1087 insertions(+), 43 deletions(-)
+ 4 files changed, 1076 insertions(+), 45 deletions(-)
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx-api.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx-api.h
@@ -384,7 +384,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static enum dsa_tag_protocol mxl862xx_get_tag_protocol(struct dsa_switch *ds,
  						       int port,
  						       enum dsa_tag_protocol m)
-@@ -168,6 +182,225 @@ static int mxl862xx_setup_mdio(struct ds
+@@ -168,6 +182,213 @@ static int mxl862xx_setup_mdio(struct ds
  	return ret;
  }
  
@@ -535,18 +535,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return ret;
 +}
 +
-+/**
-+ * mxl862xx_allocate_bridge - Allocate a firmware bridge instance
-+ * @priv: driver private data
-+ * @bridge_id: output -- firmware bridge ID assigned by the firmware
-+ *
-+ * Newly allocated bridges default to flooding all traffic classes
-+ * (unknown unicast, multicast, broadcast).  Callers that need
-+ * different forwarding behavior must call mxl862xx_bridge_config_fwd()
-+ * after allocation.
-+ *
-+ * Return: 0 on success, negative errno on failure.
-+ */
 +static int mxl862xx_allocate_bridge(struct mxl862xx_priv *priv, u16 *bridge_id)
 +{
 +	struct mxl862xx_bridge_alloc br_alloc = {};
@@ -610,7 +598,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_setup(struct dsa_switch *ds)
  {
  	struct mxl862xx_priv *priv = ds->priv;
-@@ -181,6 +414,10 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -181,6 +402,10 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -621,7 +609,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return mxl862xx_setup_mdio(ds);
  }
  
-@@ -260,66 +497,87 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -260,66 +485,87 @@ static int mxl862xx_configure_sp_tag_pro
  
  static int mxl862xx_setup_cpu_bridge(struct dsa_switch *ds, int port)
  {
@@ -744,7 +732,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	struct dsa_port *dp = dsa_to_port(ds, port);
  	bool is_cpu_port = dsa_port_is_cpu(dp);
  	int ret;
-@@ -352,7 +610,31 @@ static int mxl862xx_port_setup(struct ds
+@@ -352,7 +598,31 @@ static int mxl862xx_port_setup(struct ds
  		return mxl862xx_setup_cpu_bridge(ds, port);
  
  	/* setup single-port bridge for user ports */
@@ -777,7 +765,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static void mxl862xx_phylink_get_caps(struct dsa_switch *ds, int port,
-@@ -365,14 +647,385 @@ static void mxl862xx_phylink_get_caps(st
+@@ -365,14 +635,383 @@ static void mxl862xx_phylink_get_caps(st
  		  config->supported_interfaces);
  }
  
@@ -942,7 +930,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	mxl862xx_fw_portmap_clear_bit(qparam.port_map, port);
 +
 +	if (mxl862xx_fw_portmap_is_empty(qparam.port_map)) {
-+		/* No ports left  remove the entry entirely */
++		/* No ports left -- remove the entry entirely */
 +		rparam.fid = cpu_to_le16(fid);
 +		rparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
 +		ether_addr_copy(rparam.mac, mdb->addr);
@@ -1033,7 +1021,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +/* Deferred work handler for host flood configuration.
 + *
 + * port_set_host_flood is called from atomic context (under
-+ * netif_addr_lock), so firmware calls must be deferred.  The worker
++ * netif_addr_lock), so firmware calls must be deferred. The worker
 + * acquires rtnl_lock() to serialize with DSA callbacks that access the
 + * same driver state.
 + */
@@ -1058,9 +1046,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	mc = p->host_flood_mc;
 +
 +	/* The hardware controls unknown-unicast/multicast forwarding per FID
-+	 * (bridge), not per source port.  For bridged ports all members share
++	 * (bridge), not per source port. For bridged ports all members share
 +	 * one FID, so we cannot selectively suppress flooding to the CPU for
-+	 * one source port while allowing it for another.  Silently ignore the
++	 * one source port while allowing it for another. Silently ignore the
 +	 * request -- the excess flooding towards the CPU is harmless.
 +	 */
 +	if (!dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
@@ -1098,7 +1086,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	struct mxl862xx_priv *priv = ds->priv;
 +	unsigned long old_block = priv->ports[port].flood_block;
 +	unsigned long block = old_block;
-+	bool need_update = false;
 +	int ret;
 +
 +	if (flags.mask & BR_FLOOD) {
@@ -1128,8 +1115,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	if (flags.mask & BR_LEARNING)
 +		priv->ports[port].learning = !!(flags.val & BR_LEARNING);
 +
-+	need_update = (block != old_block) || (flags.mask & BR_LEARNING);
-+	if (need_update) {
++	if ((block != old_block) || (flags.mask & BR_LEARNING)) {
 +		priv->ports[port].flood_block = block;
 +		ret = mxl862xx_set_bridge_port(ds, port);
 +		if (ret)
@@ -1163,15 +1149,16 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
  
  static void mxl862xx_phylink_mac_config(struct phylink_config *config,
-@@ -407,6 +1060,7 @@ static int mxl862xx_probe(struct mdio_de
+@@ -407,7 +1046,7 @@ static int mxl862xx_probe(struct mdio_de
  	struct device *dev = &mdiodev->dev;
  	struct mxl862xx_priv *priv;
  	struct dsa_switch *ds;
-+	int i;
+-	int err;
++	int err, i;
  
  	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  	if (!priv)
-@@ -424,8 +1078,17 @@ static int mxl862xx_probe(struct mdio_de
+@@ -425,14 +1064,25 @@ static int mxl862xx_probe(struct mdio_de
  	ds->ops = &mxl862xx_switch_ops;
  	ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops;
  	ds->num_ports = MXL862XX_MAX_PORTS;
@@ -1188,8 +1175,18 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dev_set_drvdata(dev, ds);
  
- 	return dsa_register_switch(ds);
-@@ -435,6 +1098,7 @@ static void mxl862xx_remove(struct mdio_
+ 	err = dsa_register_switch(ds);
+-	if (err)
++	if (err) {
+ 		mxl862xx_host_shutdown(priv);
+-
++		for (i = 0; i < MXL862XX_MAX_PORTS; i++)
++			cancel_work_sync(&priv->ports[i].host_flood_work);
++	}
+ 	return err;
+ }
+ 
+@@ -440,6 +1090,7 @@ static void mxl862xx_remove(struct mdio_
  {
  	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
  	struct mxl862xx_priv *priv;
@@ -1197,14 +1194,14 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	if (!ds)
  		return;
-@@ -444,12 +1108,21 @@ static void mxl862xx_remove(struct mdio_
+@@ -449,12 +1100,21 @@ static void mxl862xx_remove(struct mdio_
  	dsa_unregister_switch(ds);
  
  	mxl862xx_host_shutdown(priv);
 +
-+	/* Cancel any pending host flood work.  dsa_unregister_switch()
++	/* Cancel any pending host flood work. dsa_unregister_switch()
 +	 * has already called port_teardown (which sets setup_done=false),
-+	 * but a worker could still be blocked on rtnl_lock().  Since we
++	 * but a worker could still be blocked on rtnl_lock(). Since we
 +	 * are now outside RTNL, cancel_work_sync() will not deadlock.
 +	 */
 +	for (i = 0; i < MXL862XX_MAX_PORTS; i++)
@@ -1219,7 +1216,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	if (!ds)
  		return;
-@@ -460,6 +1133,9 @@ static void mxl862xx_shutdown(struct mdi
+@@ -465,6 +1125,9 @@ static void mxl862xx_shutdown(struct mdi
  
  	mxl862xx_host_shutdown(priv);
  

+ 17 - 106
target/linux/generic/pending-6.18/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch

@@ -1,7 +1,7 @@
-From 7286ac4f850339aac37dd52633f4a70816b621a8 Mon Sep 17 00:00:00 2001
+From 0d88d02cc9dccad01ff88f54e1beee867107b942 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 10 Mar 2026 02:36:00 +0000
-Subject: [PATCH 14/35] net: dsa: mxl862xx: implement VLAN functionality
+Subject: [PATCH 05/26] net: dsa: mxl862xx: implement VLAN functionality
 
 Add VLAN support using both the Extended VLAN (EVLAN) engine and the
 VLAN Filter (VF) engine in a hybrid architecture that allows a higher
@@ -35,11 +35,11 @@ VLAN Filter blocks across ports with identical VID sets.
 
 Signed-off-by: Daniel Golle <[email protected]>
 ---
- drivers/net/dsa/mxl862xx/mxl862xx-api.h | 329 ++++++++
+ drivers/net/dsa/mxl862xx/mxl862xx-api.h | 329 +++++++++
  drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |  12 +
- drivers/net/dsa/mxl862xx/mxl862xx.c     | 960 +++++++++++++++++++++++-
- drivers/net/dsa/mxl862xx/mxl862xx.h     | 110 ++-
- 4 files changed, 1386 insertions(+), 25 deletions(-)
+ drivers/net/dsa/mxl862xx/mxl862xx.c     | 915 +++++++++++++++++++++++-
+ drivers/net/dsa/mxl862xx/mxl862xx.h     | 104 ++-
+ 4 files changed, 1344 insertions(+), 16 deletions(-)
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx-api.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx-api.h
@@ -577,7 +577,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	mxl862xx_fw_portmap_from_bitmap(br_port_cfg.bridge_port_map, p->portmap);
  
  	for (i = 0; i < ARRAY_SIZE(mxl862xx_flood_meters); i++) {
-@@ -329,13 +472,131 @@ static int mxl862xx_sync_bridge_members(
+@@ -329,6 +472,91 @@ static int mxl862xx_sync_bridge_members(
  	return ret;
  }
  
@@ -609,11 +609,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return 0;
 +}
 +
-+/**
-+ * mxl862xx_vf_init - Initialize per-port VF block software state
-+ * @vf: VLAN Filter block to initialize
-+ * @size: block size (entries per port)
-+ */
 +static void mxl862xx_vf_init(struct mxl862xx_vf_block *vf, u16 size)
 +{
 +	vf->allocated = false;
@@ -623,15 +618,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	INIT_LIST_HEAD(&vf->vids);
 +}
 +
-+/**
-+ * mxl862xx_vf_block_alloc - Allocate a VLAN Filter block from firmware
-+ * @priv: driver private data
-+ * @size: number of entries to allocate
-+ * @block_id: output -- block ID assigned by firmware
-+ *
-+ * Allocates a contiguous VLAN Filter block and configures it to discard
-+ * unmatched tagged frames (VID membership enforcement).
-+ */
 +static int mxl862xx_vf_block_alloc(struct mxl862xx_priv *priv,
 +				   u16 size, u16 *block_id)
 +{
@@ -650,15 +636,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return 0;
 +}
 +
-+/**
-+ * mxl862xx_vf_entry_discard - Write a DISCARD entry to plug an unused slot
-+ * @priv: driver private data
-+ * @block_id: HW VLAN Filter block ID
-+ * @index: entry index within the block
-+ *
-+ * Unwritten VLAN Filter entries default to VID=0 / ALLOW which would
-+ * leak VID 0 traffic. This writes a DISCARD entry to plug the slot.
-+ */
 +static int mxl862xx_vf_entry_discard(struct mxl862xx_priv *priv,
 +				     u16 block_id, u16 index)
 +{
@@ -673,16 +650,6 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return MXL862XX_API_WRITE(priv, MXL862XX_VLANFILTER_SET, cfg);
 +}
 +
-+/**
-+ * mxl862xx_vf_alloc - Allocate the port's VF HW block
-+ * @priv: driver private data
-+ * @vf: VLAN Filter block (must have been initialized via mxl862xx_vf_init)
-+ *
-+ * Allocates the block and writes a DISCARD sentinel at index 0 so that
-+ * when active_count is 0, the single-entry scan window blocks VID-0
-+ * (which would otherwise match the zeroed-out default and be allowed).
-+ * Called once per port from port_setup.
-+ */
 +static int mxl862xx_vf_alloc(struct mxl862xx_priv *priv,
 +			     struct mxl862xx_vf_block *vf)
 +{
@@ -699,18 +666,10 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	return mxl862xx_vf_entry_discard(priv, vf->block_id, 0);
 +}
 +
- /**
-  * mxl862xx_allocate_bridge - Allocate a firmware bridge instance
-  * @priv: driver private data
-  * @bridge_id: output -- firmware bridge ID assigned by the firmware
-  *
-  * Newly allocated bridges default to flooding all traffic classes
-- * (unknown unicast, multicast, broadcast).  Callers that need
-+ * (unknown unicast, multicast, broadcast). Callers that need
-  * different forwarding behavior must call mxl862xx_bridge_config_fwd()
-  * after allocation.
-  *
-@@ -404,6 +665,9 @@ static int mxl862xx_add_single_port_brid
+ static int mxl862xx_allocate_bridge(struct mxl862xx_priv *priv, u16 *bridge_id)
+ {
+ 	struct mxl862xx_bridge_alloc br_alloc = {};
+@@ -392,6 +620,9 @@ static int mxl862xx_add_single_port_brid
  static int mxl862xx_setup(struct dsa_switch *ds)
  {
  	struct mxl862xx_priv *priv = ds->priv;
@@ -720,7 +679,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	int ret;
  
  	ret = mxl862xx_reset(priv);
-@@ -414,6 +678,50 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -402,6 +633,50 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -771,7 +730,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	ret = mxl862xx_setup_drop_meter(ds);
  	if (ret)
  		return ret;
-@@ -495,27 +803,616 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -483,27 +758,616 @@ static int mxl862xx_configure_sp_tag_pro
  	return MXL862XX_API_WRITE(ds->priv, MXL862XX_SS_SPTAG_SET, tag);
  }
  
@@ -1392,7 +1351,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_bridge_join(struct dsa_switch *ds, int port,
  				     const struct dsa_bridge bridge,
  				     bool *tx_fwd_offload,
-@@ -565,6 +1462,22 @@ static void mxl862xx_port_bridge_leave(s
+@@ -553,6 +1417,22 @@ static void mxl862xx_port_bridge_leave(s
  	bitmap_zero(p->portmap, MXL862XX_MAX_BRIDGE_PORTS);
  	__set_bit(dp->cpu_dp->index, p->portmap);
  	p->flood_block = 0;
@@ -1415,7 +1374,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	err = mxl862xx_set_bridge_port(ds, port);
  	if (err)
  		dev_err(ds->dev,
-@@ -614,6 +1527,28 @@ static int mxl862xx_port_setup(struct ds
+@@ -602,6 +1482,28 @@ static int mxl862xx_port_setup(struct ds
  	if (ret)
  		return ret;
  
@@ -1444,37 +1403,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	priv->ports[port].setup_done = true;
  
  	return 0;
-@@ -808,7 +1743,7 @@ static int mxl862xx_port_mdb_del(struct
- 	mxl862xx_fw_portmap_clear_bit(qparam.port_map, port);
- 
- 	if (mxl862xx_fw_portmap_is_empty(qparam.port_map)) {
--		/* No ports left — remove the entry entirely */
-+		/* No ports left -- remove the entry entirely */
- 		rparam.fid = cpu_to_le16(fid);
- 		rparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
- 		ether_addr_copy(rparam.mac, mdb->addr);
-@@ -899,7 +1834,7 @@ static void mxl862xx_port_stp_state_set(
- /* Deferred work handler for host flood configuration.
-  *
-  * port_set_host_flood is called from atomic context (under
-- * netif_addr_lock), so firmware calls must be deferred.  The worker
-+ * netif_addr_lock), so firmware calls must be deferred. The worker
-  * acquires rtnl_lock() to serialize with DSA callbacks that access the
-  * same driver state.
-  */
-@@ -924,9 +1859,9 @@ static void mxl862xx_host_flood_work_fn(
- 	mc = p->host_flood_mc;
- 
- 	/* The hardware controls unknown-unicast/multicast forwarding per FID
--	 * (bridge), not per source port.  For bridged ports all members share
-+	 * (bridge), not per source port. For bridged ports all members share
- 	 * one FID, so we cannot selectively suppress flooding to the CPU for
--	 * one source port while allowing it for another.  Silently ignore the
-+	 * one source port while allowing it for another. Silently ignore the
- 	 * request -- the excess flooding towards the CPU is harmless.
- 	 */
- 	if (!dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
-@@ -1026,6 +1961,9 @@ static const struct dsa_switch_ops mxl86
+@@ -1012,6 +1914,9 @@ static const struct dsa_switch_ops mxl86
  	.port_fdb_dump = mxl862xx_port_fdb_dump,
  	.port_mdb_add = mxl862xx_port_mdb_add,
  	.port_mdb_del = mxl862xx_port_mdb_del,
@@ -1484,15 +1413,6 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
  
  static void mxl862xx_phylink_mac_config(struct phylink_config *config,
-@@ -1111,7 +2049,7 @@ static void mxl862xx_remove(struct mdio_
- 
- 	/* Cancel any pending host flood work.  dsa_unregister_switch()
- 	 * has already called port_teardown (which sets setup_done=false),
--	 * but a worker could still be blocked on rtnl_lock().  Since we
-+	 * but a worker could still be blocked on rtnl_lock(). Since we
- 	 * are now outside RTNL, cancel_work_sync() will not deadlock.
- 	 */
- 	for (i = 0; i < MXL862XX_MAX_PORTS; i++)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
 @@ -13,6 +13,8 @@ struct mxl862xx_priv;
@@ -1504,7 +1424,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  /* Number of __le16 words in a firmware portmap (128-bit bitmap). */
  #define MXL862XX_FW_PORTMAP_WORDS	(MXL862XX_MAX_BRIDGE_PORTS / 16)
-@@ -86,12 +88,72 @@ static inline bool mxl862xx_fw_portmap_i
+@@ -86,6 +88,66 @@ static inline bool mxl862xx_fw_portmap_i
  }
  
  /**
@@ -1571,15 +1491,6 @@ Signed-off-by: Daniel Golle <[email protected]>
   * struct mxl862xx_port - per-port state tracked by the driver
   * @priv:                back-pointer to switch private data; needed by
   *                       deferred work handlers to access ds and priv
-- * @fid:                 firmware FID for the permanent single-port bridge;
-- *                       kept alive for the lifetime of the port so traffic is
-- *                       never forwarded while the port is unbridged
-+ * @fid:                 firmware FID for the permanent single-port bridge; kept
-+ *                       alive for the lifetime of the port so traffic is never
-+ *                       forwarded while the port is unbridged
-  * @portmap:             bitmap of switch port indices that share the current
-  *                       bridge with this port
-  * @flood_block:         bitmask of firmware meter indices that are currently
 @@ -101,6 +163,11 @@ static inline bool mxl862xx_fw_portmap_i
   * @setup_done:          set at end of port_setup, cleared at start of
   *                       port_teardown; guards deferred work against

+ 4 - 4
target/linux/generic/pending-6.18/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch

@@ -1,7 +1,7 @@
-From 03b583e774835f771dd7c3c265be5903f008e8e5 Mon Sep 17 00:00:00 2001
+From 0067d79d10becfc5779fb50d5c0ac152cc5dc303 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Sun, 22 Mar 2026 00:57:33 +0000
-Subject: [PATCH 15/35] net: dsa: mxl862xx: add ethtool statistics support
+Subject: [PATCH 06/26] net: dsa: mxl862xx: add ethtool statistics support
 
 The MxL862xx firmware exposes per-port RMON counters through the
 RMON_PORT_GET command, covering standard IEEE 802.3 MAC statistics
@@ -257,7 +257,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #define MXL862XX_SDMA_PCTRLP(p)		(0xbc0 + ((p) * 0x6))
  #define MXL862XX_SDMA_PCTRL_EN		BIT(0)
  
-@@ -1940,6 +1998,110 @@ static int mxl862xx_port_bridge_flags(st
+@@ -1893,6 +1951,110 @@ static int mxl862xx_port_bridge_flags(st
  	return 0;
  }
  
@@ -368,7 +368,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static const struct dsa_switch_ops mxl862xx_switch_ops = {
  	.get_tag_protocol = mxl862xx_get_tag_protocol,
  	.setup = mxl862xx_setup,
-@@ -1964,6 +2126,12 @@ static const struct dsa_switch_ops mxl86
+@@ -1917,6 +2079,12 @@ static const struct dsa_switch_ops mxl86
  	.port_vlan_filtering = mxl862xx_port_vlan_filtering,
  	.port_vlan_add = mxl862xx_port_vlan_add,
  	.port_vlan_del = mxl862xx_port_vlan_del,

+ 100 - 22
target/linux/generic/pending-6.18/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch

@@ -1,7 +1,7 @@
-From 8b66d20f7e5226f4854a39cfb9f25a0591a5bb83 Mon Sep 17 00:00:00 2001
+From bab5a69e3872a693069e430a1fa0d2825ea83b4f Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 04:14:38 +0000
-Subject: [PATCH 16/35] net: dsa: mxl862xx: implement .get_stats64
+Subject: [PATCH 07/26] net: dsa: mxl862xx: implement .get_stats64
 
 Poll free-running firmware RMON counters every 2 seconds and accumulate
 deltas into 64-bit per-port statistics. 32-bit packet counters wrap
@@ -11,10 +11,49 @@ that counters are always up to date when queried.
 
 Signed-off-by: Daniel Golle <[email protected]>
 ---
- drivers/net/dsa/mxl862xx/mxl862xx.c | 167 ++++++++++++++++++++++++++++
- drivers/net/dsa/mxl862xx/mxl862xx.h |  51 +++++++++
- 2 files changed, 218 insertions(+)
+ drivers/net/dsa/mxl862xx/mxl862xx-host.c |   8 +-
+ drivers/net/dsa/mxl862xx/mxl862xx.c      | 174 +++++++++++++++++++++++
+ drivers/net/dsa/mxl862xx/mxl862xx.h      |  63 +++++++-
+ 3 files changed, 238 insertions(+), 7 deletions(-)
 
+--- a/drivers/net/dsa/mxl862xx/mxl862xx-host.c
++++ b/drivers/net/dsa/mxl862xx/mxl862xx-host.c
+@@ -48,7 +48,7 @@ static void mxl862xx_crc_err_work_fn(str
+ 		dev_close(dp->conduit);
+ 	rtnl_unlock();
+ 
+-	clear_bit(0, &priv->crc_err);
++	clear_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags);
+ }
+ 
+ /* Firmware CRC error codes (outside normal Zephyr errno range). */
+@@ -247,7 +247,7 @@ static int mxl862xx_issue_cmd(struct mxl
+ 
+ 	ret = mxl862xx_crc6_verify(ctrl_enc, len_enc, &fw_result);
+ 	if (ret) {
+-		if (!test_and_set_bit(0, &priv->crc_err))
++		if (!test_and_set_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags))
+ 			schedule_work(&priv->crc_err_work);
+ 		return -EIO;
+ 	}
+@@ -314,7 +314,7 @@ static int mxl862xx_send_cmd(struct mxl8
+ 	if (ret < 0) {
+ 		if ((ret == MXL862XX_FW_CRC6_ERR ||
+ 		     ret == MXL862XX_FW_CRC16_ERR) &&
+-		    !test_and_set_bit(0, &priv->crc_err))
++		    !test_and_set_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags))
+ 			schedule_work(&priv->crc_err_work);
+ 		if (!quiet)
+ 			dev_err(&priv->mdiodev->dev,
+@@ -458,7 +458,7 @@ int mxl862xx_api_wrap(struct mxl862xx_pr
+ 	}
+ 
+ 	if (crc16(0xffff, (const u8 *)data, size) != crc) {
+-		if (!test_and_set_bit(0, &priv->crc_err))
++		if (!test_and_set_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags))
+ 			schedule_work(&priv->crc_err_work);
+ 		ret = -EIO;
+ 		goto out;
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
 @@ -30,6 +30,12 @@
@@ -30,7 +69,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  struct mxl862xx_mib_desc {
  	unsigned int size;
  	unsigned int offset;
-@@ -784,6 +790,9 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -739,6 +745,9 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -40,7 +79,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return mxl862xx_setup_mdio(ds);
  }
  
-@@ -2102,6 +2111,156 @@ static void mxl862xx_get_pause_stats(str
+@@ -2055,6 +2064,158 @@ static void mxl862xx_get_pause_stats(str
  	pause_stats->rx_pause_frames = le32_to_cpu(cnt.rx_good_pause_pkts);
  }
  
@@ -160,8 +199,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	dsa_switch_for_each_available_port(dp, ds)
 +		mxl862xx_stats_poll(ds, dp->index);
 +
-+	schedule_delayed_work(&priv->stats_work,
-+			      MXL862XX_STATS_POLL_INTERVAL);
++	if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags))
++		schedule_delayed_work(&priv->stats_work,
++				      MXL862XX_STATS_POLL_INTERVAL);
 +}
 +
 +static void mxl862xx_get_stats64(struct dsa_switch *ds, int port,
@@ -189,15 +229,16 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	spin_unlock_bh(&priv->ports[port].stats_lock);
 +
 +	/* Trigger a fresh poll so the next read sees up-to-date counters.
-+	 * No-op if the work is already pending or running.
++	 * No-op if the work is already pending, running, or teardown started.
 +	 */
-+	schedule_delayed_work(&priv->stats_work, 0);
++	if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags))
++		schedule_delayed_work(&priv->stats_work, 0);
 +}
 +
  static const struct dsa_switch_ops mxl862xx_switch_ops = {
  	.get_tag_protocol = mxl862xx_get_tag_protocol,
  	.setup = mxl862xx_setup,
-@@ -2132,6 +2291,7 @@ static const struct dsa_switch_ops mxl86
+@@ -2085,6 +2246,7 @@ static const struct dsa_switch_ops mxl86
  	.get_eth_mac_stats = mxl862xx_get_eth_mac_stats,
  	.get_eth_ctrl_stats = mxl862xx_get_eth_ctrl_stats,
  	.get_pause_stats = mxl862xx_get_pause_stats,
@@ -205,7 +246,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
  
  static void mxl862xx_phylink_mac_config(struct phylink_config *config,
-@@ -2193,8 +2353,11 @@ static int mxl862xx_probe(struct mdio_de
+@@ -2146,16 +2308,22 @@ static int mxl862xx_probe(struct mdio_de
  		priv->ports[i].priv = priv;
  		INIT_WORK(&priv->ports[i].host_flood_work,
  			  mxl862xx_host_flood_work_fn);
@@ -216,20 +257,33 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dev_set_drvdata(dev, ds);
  
- 	return dsa_register_switch(ds);
-@@ -2213,6 +2376,8 @@ static void mxl862xx_remove(struct mdio_
+ 	err = dsa_register_switch(ds);
+ 	if (err) {
++		set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
++		cancel_delayed_work_sync(&priv->stats_work);
+ 		mxl862xx_host_shutdown(priv);
+ 		for (i = 0; i < MXL862XX_MAX_PORTS; i++)
+ 			cancel_work_sync(&priv->ports[i].host_flood_work);
+ 	}
++
+ 	return err;
+ }
  
- 	dsa_unregister_switch(ds);
+@@ -2170,6 +2338,9 @@ static void mxl862xx_remove(struct mdio_
+ 
+ 	priv = ds->priv;
  
++	set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
 +	cancel_delayed_work_sync(&priv->stats_work);
 +
- 	mxl862xx_host_shutdown(priv);
+ 	dsa_unregister_switch(ds);
  
- 	/* Cancel any pending host flood work.  dsa_unregister_switch()
-@@ -2237,6 +2402,8 @@ static void mxl862xx_shutdown(struct mdi
+ 	mxl862xx_host_shutdown(priv);
+@@ -2196,6 +2367,9 @@ static void mxl862xx_shutdown(struct mdi
  
  	dsa_switch_shutdown(ds);
  
++	set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
 +	cancel_delayed_work_sync(&priv->stats_work);
 +
  	mxl862xx_host_shutdown(priv);
@@ -296,7 +350,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   */
  struct mxl862xx_port {
  	struct mxl862xx_priv *priv;
-@@ -195,6 +240,9 @@ struct mxl862xx_port {
+@@ -195,16 +240,25 @@ struct mxl862xx_port {
  	bool host_flood_uc;
  	bool host_flood_mc;
  	struct work_struct host_flood_work;
@@ -305,8 +359,26 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	spinlock_t stats_lock;
  };
  
++/* Bit indices for struct mxl862xx_priv::flags */
++#define MXL862XX_FLAG_CRC_ERR		0
++#define MXL862XX_FLAG_WORK_STOPPED	1
++
  /**
-@@ -216,6 +264,8 @@ struct mxl862xx_port {
+  * struct mxl862xx_priv - driver private data for an MxL862xx switch
+  * @ds:                 pointer to the DSA switch instance
+  * @mdiodev:            MDIO device used to communicate with the switch firmware
+  * @crc_err_work:       deferred work for shutting down all ports on MDIO CRC
+  *                      errors
+- * @crc_err:            set atomically before CRC-triggered shutdown, cleared
+- *                      after
++ * @flags:              atomic status flags; %MXL862XX_FLAG_CRC_ERR is set
++ *                      before CRC-triggered shutdown and cleared after;
++ *                      %MXL862XX_FLAG_WORK_STOPPED is set before cancelling
++ *                      stats_work to prevent rescheduling during teardown
+  * @drop_meter:         index of the single shared zero-rate firmware meter
+  *                      used to unconditionally drop traffic (used to block
+  *                      flooding)
+@@ -216,18 +270,21 @@ struct mxl862xx_port {
   * @evlan_ingress_size: per-port ingress Extended VLAN block size
   * @evlan_egress_size:  per-port egress Extended VLAN block size
   * @vf_block_size:      per-port VLAN Filter block size
@@ -315,7 +387,13 @@ Signed-off-by: Daniel Golle <[email protected]>
   */
  struct mxl862xx_priv {
  	struct dsa_switch *ds;
-@@ -228,6 +278,7 @@ struct mxl862xx_priv {
+ 	struct mdio_device *mdiodev;
+ 	struct work_struct crc_err_work;
+-	unsigned long crc_err;
++	unsigned long flags;
+ 	u16 drop_meter;
+ 	struct mxl862xx_port ports[MXL862XX_MAX_PORTS];
+ 	u16 bridges[MXL862XX_MAX_BRIDGES + 1];
  	u16 evlan_ingress_size;
  	u16 evlan_egress_size;
  	u16 vf_block_size;

+ 11 - 11
target/linux/generic/pending-6.18/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch

@@ -1,7 +1,7 @@
-From fecfbea928cd762b19ff17aa16fb1ab143d73db1 Mon Sep 17 00:00:00 2001
+From da12469e73282da814163125153f381823e33f20 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 17:56:35 +0000
-Subject: [PATCH 17/35] net: dsa: mxl862xx: store firmware version for feature
+Subject: [PATCH 08/26] net: dsa: mxl862xx: store firmware version for feature
  gating
 
 Query the firmware version at init (already done in wait_ready),
@@ -40,10 +40,11 @@ Signed-off-by: Daniel Golle <[email protected]>
  #include <linux/mdio.h>
  #include <linux/workqueue.h>
  #include <net/dsa.h>
-@@ -246,6 +247,38 @@ struct mxl862xx_port {
+@@ -245,6 +246,38 @@ struct mxl862xx_port {
+ 	spinlock_t stats_lock;
  };
  
- /**
++/**
 + * union mxl862xx_fw_version - firmware version for comparison and display
 + * @major: firmware major version
 + * @minor: firmware minor version
@@ -75,11 +76,10 @@ Signed-off-by: Daniel Golle <[email protected]>
 +#define MXL862XX_FW_VER_MIN(priv, maj, min, rev) \
 +	((priv)->fw_version.raw >= MXL862XX_FW_VER(maj, min, rev))
 +
-+/**
-  * struct mxl862xx_priv - driver private data for an MxL862xx switch
-  * @ds:                 pointer to the DSA switch instance
-  * @mdiodev:            MDIO device used to communicate with the switch firmware
-@@ -256,6 +289,8 @@ struct mxl862xx_port {
+ /* Bit indices for struct mxl862xx_priv::flags */
+ #define MXL862XX_FLAG_CRC_ERR		0
+ #define MXL862XX_FLAG_WORK_STOPPED	1
+@@ -262,6 +295,8 @@ struct mxl862xx_port {
   * @drop_meter:         index of the single shared zero-rate firmware meter
   *                      used to unconditionally drop traffic (used to block
   *                      flooding)
@@ -88,9 +88,9 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @ports:              per-port state, indexed by switch port number
   * @bridges:            maps DSA bridge number to firmware bridge ID;
   *                      zero means no firmware bridge allocated for that
-@@ -273,6 +308,7 @@ struct mxl862xx_priv {
+@@ -279,6 +314,7 @@ struct mxl862xx_priv {
  	struct work_struct crc_err_work;
- 	unsigned long crc_err;
+ 	unsigned long flags;
  	u16 drop_meter;
 +	union mxl862xx_fw_version fw_version;
  	struct mxl862xx_port ports[MXL862XX_MAX_PORTS];

+ 4 - 4
target/linux/generic/pending-6.18/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch

@@ -1,7 +1,7 @@
-From 3cb224514226928df80e43ca2280c7dca654bdfe Mon Sep 17 00:00:00 2001
+From f7606470d398e4091e1bc405bf2125dc5fc99919 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 21:39:30 +0000
-Subject: [PATCH 18/35] net: dsa: mxl862xx: move phylink stubs to
+Subject: [PATCH 09/26] net: dsa: mxl862xx: move phylink stubs to
  mxl862xx-phylink.c
 
 Move the phylink MAC operations and get_caps callback from mxl862xx.c
@@ -110,7 +110,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  #define MXL862XX_API_WRITE(dev, cmd, data) \
  	mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), false, false)
-@@ -1642,16 +1643,6 @@ static void mxl862xx_port_teardown(struc
+@@ -1597,16 +1598,6 @@ static void mxl862xx_port_teardown(struc
  	priv->ports[port].setup_done = false;
  }
  
@@ -127,7 +127,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_get_fid(struct dsa_switch *ds, struct dsa_db db)
  {
  	struct mxl862xx_priv *priv = ds->priv;
-@@ -2297,33 +2288,6 @@ static const struct dsa_switch_ops mxl86
+@@ -2252,33 +2243,6 @@ static const struct dsa_switch_ops mxl86
  	.get_stats64 = mxl862xx_get_stats64,
  };
  

+ 2 - 2
target/linux/generic/pending-6.18/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch

@@ -1,7 +1,7 @@
-From de41d438c4e90876449715a307dd03fa37338742 Mon Sep 17 00:00:00 2001
+From e583eeeb907f0abeef2082162293a5d63b9fd6fa Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Thu, 26 Mar 2026 01:50:00 +0000
-Subject: [PATCH 19/35] net: dsa: mxl862xx: move API macros to mxl862xx-host.h
+Subject: [PATCH 10/26] net: dsa: mxl862xx: move API macros to mxl862xx-host.h
 
 Move the MXL862XX_API_WRITE, MXL862XX_API_READ and
 MXL862XX_API_READ_QUIET convenience macros from mxl862xx.c to

+ 7 - 7
target/linux/generic/pending-6.18/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch

@@ -1,7 +1,7 @@
-From 88f46eb32d1aed296af2005c3ed8f23a6eea64c3 Mon Sep 17 00:00:00 2001
+From e25f0886853607e4a6d1157ae84e43e8224cf3b7 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Sun, 22 Mar 2026 00:57:44 +0000
-Subject: [PATCH 20/35] net: dsa: mxl862xx: add support for SerDes ports
+Subject: [PATCH 11/26] net: dsa: mxl862xx: add support for SerDes ports
 
 The MxL862xx has two XPCS/SerDes interfaces (XPCS0 for ports 9-12,
 XPCS1 for ports 13-16). Each can operate in various single-lane
@@ -1007,7 +1007,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #endif /* __MXL862XX_PHYLINK_H */
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -729,7 +729,7 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -684,7 +684,7 @@ static int mxl862xx_setup(struct dsa_swi
  	int n_user_ports = 0, max_vlans;
  	int ingress_finals, vid_rules;
  	struct dsa_port *dp;
@@ -1016,7 +1016,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	ret = mxl862xx_reset(priv);
  	if (ret)
-@@ -739,6 +739,9 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -694,6 +694,9 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  
@@ -1051,7 +1051,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * union mxl862xx_fw_version - firmware version for comparison and display
   * @major: firmware major version
   * @minor: firmware minor version
-@@ -291,6 +307,8 @@ union mxl862xx_fw_version {
+@@ -297,6 +313,8 @@ union mxl862xx_fw_version {
   *                      flooding)
   * @fw_version:         cached firmware version, populated at probe and
   *                      compared with MXL862XX_FW_VER_MIN()
@@ -1060,8 +1060,8 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @ports:              per-port state, indexed by switch port number
   * @bridges:            maps DSA bridge number to firmware bridge ID;
   *                      zero means no firmware bridge allocated for that
-@@ -309,6 +327,7 @@ struct mxl862xx_priv {
- 	unsigned long crc_err;
+@@ -315,6 +333,7 @@ struct mxl862xx_priv {
+ 	unsigned long flags;
  	u16 drop_meter;
  	union mxl862xx_fw_version fw_version;
 +	struct mxl862xx_pcs serdes_ports[8];

+ 5 - 5
target/linux/generic/pending-6.18/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch

@@ -1,7 +1,7 @@
-From d40565e2e00fc2c8f04b9c571fcbea2f146db844 Mon Sep 17 00:00:00 2001
+From 24d752291784e30d7329bed15744bbbc6a3e2485 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:14:33 +0000
-Subject: [PATCH 21/35] net: dsa: mxl862xx: add SerDes ethtool statistics
+Subject: [PATCH 12/26] net: dsa: mxl862xx: add SerDes ethtool statistics
 
 Expose SerDes equalization and signal detect parameters as ethtool
 statistics on ports 9-16 (XPCS-backed ports). Uses the XPCS EQ_GET
@@ -239,7 +239,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #endif /* __MXL862XX_PHYLINK_H */
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -2007,6 +2007,8 @@ static void mxl862xx_get_strings(struct
+@@ -1960,6 +1960,8 @@ static void mxl862xx_get_strings(struct
  
  	for (i = 0; i < ARRAY_SIZE(mxl862xx_mib); i++)
  		ethtool_puts(&data, mxl862xx_mib[i].name);
@@ -248,7 +248,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static int mxl862xx_get_sset_count(struct dsa_switch *ds, int port, int sset)
-@@ -2014,7 +2016,7 @@ static int mxl862xx_get_sset_count(struc
+@@ -1967,7 +1969,7 @@ static int mxl862xx_get_sset_count(struc
  	if (sset != ETH_SS_STATS)
  		return 0;
  
@@ -257,7 +257,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static int mxl862xx_read_rmon(struct dsa_switch *ds, int port,
-@@ -2050,6 +2052,8 @@ static void mxl862xx_get_ethtool_stats(s
+@@ -2003,6 +2005,8 @@ static void mxl862xx_get_ethtool_stats(s
  		else
  			*data++ = le64_to_cpu(*(__le64 *)field);
  	}

+ 3 - 3
target/linux/generic/pending-6.18/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch

@@ -1,7 +1,7 @@
-From 54dd5fabc543f8538202367a863eb0e9161bacab Mon Sep 17 00:00:00 2001
+From ee227a5e4c74f599cc1b34578b32214d5873ad2f Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:15:32 +0000
-Subject: [PATCH 22/35] net: dsa: mxl862xx: add SerDes self-test via PRBS and
+Subject: [PATCH 13/26] net: dsa: mxl862xx: add SerDes self-test via PRBS and
  BERT
 
 Implement the dsa_switch_ops.self_test callback for SerDes ports
@@ -198,7 +198,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #endif /* __MXL862XX_PHYLINK_H */
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -2286,6 +2286,7 @@ static const struct dsa_switch_ops mxl86
+@@ -2241,6 +2241,7 @@ static const struct dsa_switch_ops mxl86
  	.get_eth_ctrl_stats = mxl862xx_get_eth_ctrl_stats,
  	.get_pause_stats = mxl862xx_get_pause_stats,
  	.get_stats64 = mxl862xx_get_stats64,

+ 3 - 3
target/linux/generic/pending-6.18/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch

@@ -1,7 +1,7 @@
-From dd62e68cd0bd29934c3efbce687d5e103cc4b331 Mon Sep 17 00:00:00 2001
+From 43eb3eed250ea4e7e83371fcbf2bfb8d626eade6 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:51:13 +0000
-Subject: [PATCH 23/35] net: dsa: mxl862xx: trap link-local frames to the CPU
+Subject: [PATCH 14/26] net: dsa: mxl862xx: trap link-local frames to the CPU
  port
 
 Install per-CTP PCE rules on each user port that trap IEEE 802.1D
@@ -817,7 +817,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_set_bridge_port(struct dsa_switch *ds, int port)
  {
  	struct mxl862xx_bridge_port_config br_port_cfg = {};
-@@ -1594,6 +1658,11 @@ static int mxl862xx_port_setup(struct ds
+@@ -1549,6 +1613,11 @@ static int mxl862xx_port_setup(struct ds
  	if (ret)
  		return ret;
  

+ 3 - 3
target/linux/generic/pending-6.18/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch

@@ -1,7 +1,7 @@
-From 3bba25f7ba35e3bca8230bd37ffb612944dbf301 Mon Sep 17 00:00:00 2001
+From e18f5b235d8df21209c73f4f0bbc00cc3a1973ba Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:51:21 +0000
-Subject: [PATCH 24/35] net: dsa: mxl862xx: warn about old firmware default PCE
+Subject: [PATCH 15/26] net: dsa: mxl862xx: warn about old firmware default PCE
  rules
 
 Firmware versions older than 1.0.80 install global PCE rules at
@@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -854,6 +854,10 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -809,6 +809,10 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  

+ 66 - 102
target/linux/generic/pending-6.18/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch

@@ -1,7 +1,7 @@
-From 1687c5632dfd80461b12425b943e30555faa3dd4 Mon Sep 17 00:00:00 2001
+From 04929904d3a7d824593587e52e3ed21d6f0f109a Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Sun, 22 Mar 2026 00:58:04 +0000
-Subject: [PATCH 25/35] net: dsa: add 802.1Q VLAN-based tag driver for MxL862xx
+Subject: [PATCH 16/26] net: dsa: add 802.1Q VLAN-based tag driver for MxL862xx
 
 The MxL862xx native 8-byte special tag (SpTag) requires firmware
 support on the switch CPU and is not compatible with all SoC Ethernet
@@ -23,12 +23,12 @@ Signed-off-by: Daniel Golle <[email protected]>
  drivers/net/dsa/mxl862xx/mxl862xx-api.h |  221 +++
  drivers/net/dsa/mxl862xx/mxl862xx-cmd.h |    2 +
  drivers/net/dsa/mxl862xx/mxl862xx.c     | 1626 ++++++++++++++++++++---
- drivers/net/dsa/mxl862xx/mxl862xx.h     |   21 +-
+ drivers/net/dsa/mxl862xx/mxl862xx.h     |   13 +
  include/net/dsa.h                       |    2 +
  net/dsa/Kconfig                         |    7 +
  net/dsa/Makefile                        |    1 +
  net/dsa/tag_mxl862xx_8021q.c            |   59 +
- 9 files changed, 1738 insertions(+), 202 deletions(-)
+ 9 files changed, 1736 insertions(+), 196 deletions(-)
  create mode 100644 net/dsa/tag_mxl862xx_8021q.c
 
 --- a/drivers/net/dsa/mxl862xx/Kconfig
@@ -511,7 +511,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  		err = mxl862xx_set_bridge_port(ds, port);
  		if (err)
-@@ -762,7 +909,6 @@ static void mxl862xx_free_bridge(struct
+@@ -717,7 +864,6 @@ static void mxl862xx_free_bridge(struct
  
  static int mxl862xx_add_single_port_bridge(struct dsa_switch *ds, int port)
  {
@@ -519,7 +519,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	struct mxl862xx_priv *priv = ds->priv;
  	int ret;
  
-@@ -774,15 +920,27 @@ static int mxl862xx_add_single_port_brid
+@@ -729,15 +875,27 @@ static int mxl862xx_add_single_port_brid
  
  	priv->ports[port].learning = false;
  	bitmap_zero(priv->ports[port].portmap, MXL862XX_MAX_BRIDGE_PORTS);
@@ -533,7 +533,6 @@ Signed-off-by: Daniel Golle <[email protected]>
  
 -	/* Standalone ports should not flood unknown unicast or multicast
 -	 * towards the CPU by default; only broadcast is needed initially.
--	 */
 +	/* In tag_8021q mode the TX path goes through the bridge engine
 +	 * (CTP ingress EVLAN reassigns to a virtual bridge port which
 +	 * then forwards via the bridge). With learning disabled on
@@ -543,7 +542,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	 * In native SpTag mode, TX bypasses the bridge engine entirely
 +	 * (the special tag selects the egress port directly), so flood
 +	 * control only affects CPU-bound traffic and can be restrictive.
-+	 */
+ 	 */
 +	if (priv->tag_proto == DSA_TAG_PROTO_MXL862_8021Q)
 +		return mxl862xx_bridge_config_fwd(ds, priv->ports[port].fid,
 +						  true, true, true);
@@ -551,7 +550,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return mxl862xx_bridge_config_fwd(ds, priv->ports[port].fid,
  					 false, false, true);
  }
-@@ -790,10 +948,12 @@ static int mxl862xx_add_single_port_brid
+@@ -745,10 +903,12 @@ static int mxl862xx_add_single_port_brid
  static int mxl862xx_setup(struct dsa_switch *ds)
  {
  	struct mxl862xx_priv *priv = ds->priv;
@@ -566,7 +565,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	ret = mxl862xx_reset(priv);
  	if (ret)
-@@ -806,7 +966,7 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -761,7 +921,7 @@ static int mxl862xx_setup(struct dsa_swi
  	for (i = 0; i < 8; i++)
  		mxl862xx_setup_pcs(priv, &priv->serdes_ports[i], i + 9);
  
@@ -575,7 +574,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	 * With VLAN Filter handling VID membership checks:
  	 *   Ingress: only final catchall rules (PVID insertion, 802.1Q
  	 *            accept, non-8021Q TPID handling, discard).
-@@ -814,40 +974,67 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -769,40 +929,67 @@ static int mxl862xx_setup(struct dsa_swi
  	 *            ingress EVLAN rules are needed. (7 entries.)
  	 *   Egress:  2 rules per VID that needs tag stripping (untagged VIDs).
  	 *            No egress final catchalls -- VLAN Filter does the discard.
@@ -657,7 +656,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	}
  
  	ret = mxl862xx_setup_drop_meter(ds);
-@@ -858,6 +1045,68 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -813,6 +1000,68 @@ static int mxl862xx_setup(struct dsa_swi
  		dev_warn(ds->dev, "firmware < 1.0.80 installs global PCE rules "
  			 "that interfere with DSA operation, please update\n");
  
@@ -726,7 +725,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	schedule_delayed_work(&priv->stats_work,
  			      MXL862XX_STATS_POLL_INTERVAL);
  
-@@ -939,6 +1188,52 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -894,6 +1143,52 @@ static int mxl862xx_configure_sp_tag_pro
  }
  
  /**
@@ -779,7 +778,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * mxl862xx_evlan_write_rule - Write a single Extended VLAN rule to hardware
   * @priv: driver private data
   * @block_id: HW Extended VLAN block ID
-@@ -947,6 +1242,7 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -902,6 +1197,7 @@ static int mxl862xx_configure_sp_tag_pro
   * @vid: VLAN ID for VID-specific rules (ignored when !desc->match_vid)
   * @untagged: strip tag on egress for EVLAN_STRIP_IF_UNTAGGED action
   * @pvid: port VLAN ID for PVID insertion rules (0 = no PVID)
@@ -787,7 +786,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   *
   * Translates a compact rule descriptor into a full firmware
   * mxl862xx_extendedvlan_config struct and writes it via the API.
-@@ -954,7 +1250,8 @@ static int mxl862xx_configure_sp_tag_pro
+@@ -909,7 +1205,8 @@ static int mxl862xx_configure_sp_tag_pro
  static int mxl862xx_evlan_write_rule(struct mxl862xx_priv *priv,
  				     u16 block_id, u16 entry_index,
  				     const struct mxl862xx_evlan_rule_desc *desc,
@@ -797,7 +796,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  {
  	struct mxl862xx_extendedvlan_config cfg = {};
  	struct mxl862xx_extendedvlan_filter_vlan *fv;
-@@ -1044,6 +1341,31 @@ static int mxl862xx_evlan_write_rule(str
+@@ -999,6 +1296,31 @@ static int mxl862xx_evlan_write_rule(str
  				cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_DISCARD_UPSTREAM);
  		}
  		break;
@@ -829,7 +828,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	}
  
  	return MXL862XX_API_WRITE(priv, MXL862XX_EXTENDEDVLAN_SET, cfg);
-@@ -1104,7 +1426,7 @@ static int mxl862xx_evlan_write_final_ru
+@@ -1059,7 +1381,7 @@ static int mxl862xx_evlan_write_final_ru
  	for (i = 0; i < n_rules; i++) {
  		ret = mxl862xx_evlan_write_rule(priv, blk->block_id,
  						start_idx + i, &rules[i],
@@ -838,7 +837,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		if (ret)
  			return ret;
  	}
-@@ -1273,6 +1595,27 @@ static int mxl862xx_vf_del_vid(struct mx
+@@ -1228,6 +1550,27 @@ static int mxl862xx_vf_del_vid(struct mx
  }
  
  /**
@@ -866,7 +865,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * mxl862xx_evlan_program_ingress - Write the fixed ingress catchall rules
   * @priv: driver private data
   * @port: port number
-@@ -1323,8 +1666,8 @@ static int mxl862xx_evlan_program_egress
+@@ -1278,8 +1621,8 @@ static int mxl862xx_evlan_program_egress
  	const struct mxl862xx_evlan_rule_desc *vid_rules;
  	struct mxl862xx_vf_vid *vfv;
  	u16 old_active = blk->n_active;
@@ -876,7 +875,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	if (p->vlan_filtering) {
  		vid_rules = vid_accept_standard;
-@@ -1341,13 +1684,23 @@ static int mxl862xx_evlan_program_egress
+@@ -1296,13 +1639,23 @@ static int mxl862xx_evlan_program_egress
  		if (p->vlan_filtering && !vfv->untagged)
  			continue;
  
@@ -901,7 +900,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		if (ret)
  			return ret;
  
-@@ -1356,7 +1709,29 @@ static int mxl862xx_evlan_program_egress
+@@ -1311,7 +1664,29 @@ static int mxl862xx_evlan_program_egress
  							idx++, &vid_rules[1],
  							vfv->vid,
  							vfv->untagged,
@@ -932,7 +931,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  			if (ret)
  				return ret;
  		}
-@@ -1368,8 +1743,7 @@ static int mxl862xx_evlan_program_egress
+@@ -1323,8 +1698,7 @@ static int mxl862xx_evlan_program_egress
  	 */
  	for (i = idx; i < old_active; i++) {
  		ret = mxl862xx_evlan_deactivate_entry(priv,
@@ -942,7 +941,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		if (ret)
  			return ret;
  	}
-@@ -1393,13 +1767,16 @@ static int mxl862xx_port_vlan_filtering(
+@@ -1348,13 +1722,16 @@ static int mxl862xx_port_vlan_filtering(
  
  	/* Reprogram Extended VLAN rules if filtering mode changed */
  	if (changed) {
@@ -964,7 +963,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  		ret = mxl862xx_evlan_program_ingress(priv, port);
  		if (ret)
-@@ -1536,18 +1913,19 @@ static int mxl862xx_setup_cpu_bridge(str
+@@ -1491,18 +1868,19 @@ static int mxl862xx_setup_cpu_bridge(str
  
  	/* include all assigned user ports in the CPU portmap */
  	bitmap_zero(p->portmap, MXL862XX_MAX_BRIDGE_PORTS);
@@ -990,7 +989,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_bridge_join(struct dsa_switch *ds, int port,
  				     const struct dsa_bridge bridge,
  				     bool *tx_fwd_offload,
-@@ -1580,7 +1958,6 @@ static int mxl862xx_port_bridge_join(str
+@@ -1535,7 +1913,6 @@ static int mxl862xx_port_bridge_join(str
  static void mxl862xx_port_bridge_leave(struct dsa_switch *ds, int port,
  				       const struct dsa_bridge bridge)
  {
@@ -998,7 +997,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	struct mxl862xx_priv *priv = ds->priv;
  	struct mxl862xx_port *p = &priv->ports[port];
  	int err;
-@@ -1595,34 +1972,587 @@ static void mxl862xx_port_bridge_leave(s
+@@ -1550,34 +1927,587 @@ static void mxl862xx_port_bridge_leave(s
  	 * single-port bridge
  	 */
  	bitmap_zero(p->portmap, MXL862XX_MAX_BRIDGE_PORTS);
@@ -1010,14 +1009,14 @@ Signed-off-by: Daniel Golle <[email protected]>
 -	/* Detach EVLAN and VF blocks from the bridge port BEFORE freeing
 -	 * them. The firmware tracks a usage count per block and rejects
 -	 * FREE while the count is non-zero.
+-	 *
+-	 * For EVLAN: setting in_use=false makes set_bridge_port send
+-	 * enable=false, which decrements the firmware refcount.
 +	/* Reset VLAN state for standalone mode. Ingress EVLAN is not
 +	 * needed outside a VLAN-aware bridge. Egress EVLAN is
 +	 * reprogrammed below -- in tag_8021q mode it gets the
 +	 * management VID strip catchalls, in SpTag mode it is cleared.
  	 *
--	 * For EVLAN: setting in_use=false makes set_bridge_port send
--	 * enable=false, which decrements the firmware refcount.
--	 *
 -	 * For VF: set_bridge_port sees dp->bridge == NULL (DSA already
 -	 * cleared it) and sends vlan_filter_enable=0, which decrements
 -	 * the firmware VF refcount.
@@ -1597,7 +1596,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_setup(struct dsa_switch *ds, int port)
  {
  	struct mxl862xx_priv *priv = ds->priv;
-@@ -1642,55 +2572,30 @@ static int mxl862xx_port_setup(struct ds
+@@ -1597,55 +2527,30 @@ static int mxl862xx_port_setup(struct ds
  	    dsa_port_is_dsa(dp))
  		return 0;
  
@@ -1660,7 +1659,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return 0;
  }
  
-@@ -1712,7 +2617,7 @@ static void mxl862xx_port_teardown(struc
+@@ -1667,7 +2572,7 @@ static void mxl862xx_port_teardown(struc
  	priv->ports[port].setup_done = false;
  }
  
@@ -1669,7 +1668,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  {
  	struct mxl862xx_priv *priv = ds->priv;
  
-@@ -1730,23 +2635,244 @@ static int mxl862xx_get_fid(struct dsa_s
+@@ -1685,23 +2590,244 @@ static int mxl862xx_get_fid(struct dsa_s
  	}
  }
  
@@ -1702,7 +1701,8 @@ Signed-off-by: Daniel Golle <[email protected]>
 +	if (dsa_is_cpu_port(ds, port) && priv->tag_proto == DSA_TAG_PROTO_MXL862_8021Q &&
 +	    db.type == DSA_DB_PORT) {
 +		bp_cpu = priv->ports[db.dp->index].bridge_port_cpu;
-+
+ 
+-	param.port_id = cpu_to_le32(port);
 +		if (bp_cpu)
 +			return bp_cpu;
 +	}
@@ -1719,8 +1719,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +{
 +	struct mxl862xx_mac_table_add param = {};
 +	struct mxl862xx_priv *priv = ds->priv;
- 
--	param.port_id = cpu_to_le32(port);
++
 +	param.port_id = cpu_to_le32(port_id);
  	param.static_entry = true;
  	param.fid = cpu_to_le16(fid);
@@ -1922,7 +1921,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	if (ret)
  		dev_err(ds->dev, "failed to add FDB entry on port %d\n", port);
  
-@@ -1756,18 +2882,25 @@ static int mxl862xx_port_fdb_add(struct
+@@ -1711,18 +2837,25 @@ static int mxl862xx_port_fdb_add(struct
  static int mxl862xx_port_fdb_del(struct dsa_switch *ds, int port,
  				 const unsigned char *addr, u16 vid, const struct dsa_db db)
  {
@@ -1955,7 +1954,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	if (ret)
  		dev_err(ds->dev, "failed to remove FDB entry on port %d\n", port);
  
-@@ -1806,88 +2939,147 @@ static int mxl862xx_port_fdb_dump(struct
+@@ -1761,88 +2894,147 @@ static int mxl862xx_port_fdb_dump(struct
  	return 0;
  }
  
@@ -2097,7 +2096,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 -	int fid = mxl862xx_get_fid(ds, db), ret;
  	struct mxl862xx_priv *priv = ds->priv;
 +	int fid, ret;
-+
+ 
 +	/* tag_8021q host MDB for bridged ports: clear all VBP bits */
 +	if (priv->tag_proto == DSA_TAG_PROTO_MXL862_8021Q && dsa_is_cpu_port(ds, port) &&
 +	    db.type == DSA_DB_BRIDGE) {
@@ -2107,7 +2106,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +		return mxl862xx_mac_del_host_bridge(ds, mdb->addr,
 +						    mdb->vid, &db.bridge);
 +	}
- 
++
 +	fid = mxl862xx_get_fid(ds, db);
  	if (fid < 0)
  		return fid;
@@ -2154,7 +2153,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	return ret;
  }
-@@ -1975,7 +3167,9 @@ static void mxl862xx_host_flood_work_fn(
+@@ -1930,7 +3122,9 @@ static void mxl862xx_host_flood_work_fn(
  	struct mxl862xx_priv *priv = p->priv;
  	struct dsa_switch *ds = priv->ds;
  	int port = p - priv->ports;
@@ -2164,7 +2163,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	rtnl_lock();
  
-@@ -1988,14 +3182,31 @@ static void mxl862xx_host_flood_work_fn(
+@@ -1943,14 +3137,35 @@ static void mxl862xx_host_flood_work_fn(
  	uc = p->host_flood_uc;
  	mc = p->host_flood_mc;
  
@@ -2195,8 +2194,12 @@ Signed-off-by: Daniel Golle <[email protected]>
 +					port, ERR_PTR(ret));
 +		}
 +	} else {
-+		/* SpTag mode: per-FID forwarding, only works for
-+		 * standalone ports (each has its own FID).
++		/* The hardware controls unknown-unicast/multicast forwarding
++		 * per FID (bridge), not per source port. For bridged ports all
++		 * members share one FID, so we cannot selectively suppress
++		 * flooding to the CPU for one source port while allowing it
++		 * for another. Silently ignore the request -- the excess
++		 * flooding towards the CPU is harmless.
 +		 */
 +		if (!dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
 +			mxl862xx_bridge_config_fwd(ds, p->fid, uc, mc, true);
@@ -2204,7 +2207,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  	rtnl_unlock();
  }
-@@ -2330,7 +3541,9 @@ static void mxl862xx_get_stats64(struct
+@@ -2285,7 +3500,9 @@ static void mxl862xx_get_stats64(struct
  
  static const struct dsa_switch_ops mxl862xx_switch_ops = {
  	.get_tag_protocol = mxl862xx_get_tag_protocol,
@@ -2214,7 +2217,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	.port_setup = mxl862xx_port_setup,
  	.port_teardown = mxl862xx_port_teardown,
  	.phylink_get_caps = mxl862xx_phylink_get_caps,
-@@ -2352,6 +3565,8 @@ static const struct dsa_switch_ops mxl86
+@@ -2307,6 +3524,8 @@ static const struct dsa_switch_ops mxl86
  	.port_vlan_filtering = mxl862xx_port_vlan_filtering,
  	.port_vlan_add = mxl862xx_port_vlan_add,
  	.port_vlan_del = mxl862xx_port_vlan_del,
@@ -2223,7 +2226,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	.get_strings = mxl862xx_get_strings,
  	.get_sset_count = mxl862xx_get_sset_count,
  	.get_ethtool_stats = mxl862xx_get_ethtool_stats,
-@@ -2399,6 +3614,8 @@ static int mxl862xx_probe(struct mdio_de
+@@ -2354,6 +3573,8 @@ static int mxl862xx_probe(struct mdio_de
  
  	INIT_DELAYED_WORK(&priv->stats_work, mxl862xx_stats_work_fn);
  
@@ -2231,10 +2234,10 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dev_set_drvdata(dev, ds);
  
- 	return dsa_register_switch(ds);
-@@ -2415,16 +3632,29 @@ static void mxl862xx_remove(struct mdio_
- 
- 	priv = ds->priv;
+ 	err = dsa_register_switch(ds);
+@@ -2382,6 +3603,19 @@ static void mxl862xx_remove(struct mdio_
+ 	set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
+ 	cancel_delayed_work_sync(&priv->stats_work);
  
 +	/* Tear down tag_8021q under RTNL before dsa_unregister_switch().
 +	 * dsa_tag_8021q_unregister() calls vlan_vid_del() which needs
@@ -2251,39 +2254,9 @@ Signed-off-by: Daniel Golle <[email protected]>
 +
  	dsa_unregister_switch(ds);
  
- 	cancel_delayed_work_sync(&priv->stats_work);
- 
  	mxl862xx_host_shutdown(priv);
- 
--	/* Cancel any pending host flood work.  dsa_unregister_switch()
-+	/* Cancel any pending host flood work. dsa_unregister_switch()
- 	 * has already called port_teardown (which sets setup_done=false),
- 	 * but a worker could still be blocked on rtnl_lock(). Since we
--	 * are now outside RTNL, cancel_work_sync() will not deadlock.
-+	 * are now outside RTNL, cancel_work_sync() won't deadlock.
- 	 */
- 	for (i = 0; i < MXL862XX_MAX_PORTS; i++)
- 		cancel_work_sync(&priv->ports[i].host_flood_work);
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
-@@ -8,8 +8,6 @@
- #include <linux/workqueue.h>
- #include <net/dsa.h>
- 
--struct mxl862xx_priv;
--
- #define MXL862XX_MAX_PORTS		17
- #define MXL862XX_DEFAULT_BRIDGE		0
- #define MXL862XX_MAX_BRIDGES		48
-@@ -20,6 +18,8 @@ struct mxl862xx_priv;
- /* Number of __le16 words in a firmware portmap (128-bit bitmap). */
- #define MXL862XX_FW_PORTMAP_WORDS	(MXL862XX_MAX_BRIDGE_PORTS / 16)
- 
-+struct mxl862xx_priv;
-+
- /**
-  * mxl862xx_fw_portmap_from_bitmap - convert a kernel bitmap to a firmware
-  *                                   portmap (__le16[8])
 @@ -210,6 +210,9 @@ struct mxl862xx_port_stats {
   * @vf:                  per-port VLAN Filter block state
   * @ingress_evlan:       ingress extended VLAN block state
@@ -2317,39 +2290,31 @@ Signed-off-by: Daniel Golle <[email protected]>
  	/* Hardware stats accumulation */
  	struct mxl862xx_port_stats stats;
  	spinlock_t stats_lock;
-@@ -302,6 +311,7 @@ union mxl862xx_fw_version {
-  *                      errors
-  * @crc_err:            set atomically before CRC-triggered shutdown, cleared
-  *                      after
+@@ -308,6 +317,7 @@ union mxl862xx_fw_version {
+  *                      before CRC-triggered shutdown and cleared after;
+  *                      %MXL862XX_FLAG_WORK_STOPPED is set before cancelling
+  *                      stats_work to prevent rescheduling during teardown
 + * @tag_proto:          active DSA tag protocol (native or 8021q)
   * @drop_meter:         index of the single shared zero-rate firmware meter
   *                      used to unconditionally drop traffic (used to block
   *                      flooding)
-@@ -310,12 +320,13 @@ union mxl862xx_fw_version {
-  * @serdes_ports:       SerDes interfaces incl. sub-interfaces in case of
-  *                      10G_QXGMII
-  * @ports:              per-port state, indexed by switch port number
-+ * @evlan_ingress_size: per-port ingress Extended VLAN block size
-+ * @evlan_egress_size:  per-port egress Extended VLAN block size
-+ * @cpu_evlan_ingress_size: CPU port ingress EVLAN block size (tag_8021q)
-  * @bridges:            maps DSA bridge number to firmware bridge ID;
-  *                      zero means no firmware bridge allocated for that
-  *                      DSA bridge number. Indexed by dsa_bridge.num
+@@ -322,6 +332,7 @@ union mxl862xx_fw_version {
   *                      (0 .. ds->max_num_bridges).
-- * @evlan_ingress_size: per-port ingress Extended VLAN block size
-- * @evlan_egress_size:  per-port egress Extended VLAN block size
+  * @evlan_ingress_size: per-port ingress Extended VLAN block size
+  * @evlan_egress_size:  per-port egress Extended VLAN block size
++ * @cpu_evlan_ingress_size: CPU port ingress EVLAN block size (tag_8021q)
   * @vf_block_size:      per-port VLAN Filter block size
   * @stats_work:         periodic work item that polls RMON hardware counters
   *                      and accumulates them into 64-bit per-port stats
-@@ -325,6 +336,7 @@ struct mxl862xx_priv {
+@@ -331,6 +342,7 @@ struct mxl862xx_priv {
  	struct mdio_device *mdiodev;
  	struct work_struct crc_err_work;
- 	unsigned long crc_err;
+ 	unsigned long flags;
 +	enum dsa_tag_protocol tag_proto;
  	u16 drop_meter;
  	union mxl862xx_fw_version fw_version;
  	struct mxl862xx_pcs serdes_ports[8];
-@@ -332,6 +344,7 @@ struct mxl862xx_priv {
+@@ -338,6 +350,7 @@ struct mxl862xx_priv {
  	u16 bridges[MXL862XX_MAX_BRIDGES + 1];
  	u16 evlan_ingress_size;
  	u16 evlan_egress_size;
@@ -2359,16 +2324,15 @@ Signed-off-by: Daniel Golle <[email protected]>
  };
 --- a/include/net/dsa.h
 +++ b/include/net/dsa.h
-@@ -56,6 +56,8 @@ struct tc_action;
+@@ -56,6 +56,7 @@ struct tc_action;
  #define DSA_TAG_PROTO_VSC73XX_8021Q_VALUE	28
  #define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE	29
  #define DSA_TAG_PROTO_MXL862_VALUE		30
 +#define DSA_TAG_PROTO_MXL862_8021Q_VALUE	31
-+
  
  enum dsa_tag_protocol {
  	DSA_TAG_PROTO_NONE		= DSA_TAG_PROTO_NONE_VALUE,
-@@ -89,6 +91,7 @@ enum dsa_tag_protocol {
+@@ -89,6 +90,7 @@ enum dsa_tag_protocol {
  	DSA_TAG_PROTO_LAN937X		= DSA_TAG_PROTO_LAN937X_VALUE,
  	DSA_TAG_PROTO_VSC73XX_8021Q	= DSA_TAG_PROTO_VSC73XX_8021Q_VALUE,
  	DSA_TAG_PROTO_MXL862		= DSA_TAG_PROTO_MXL862_VALUE,

+ 16 - 16
target/linux/generic/pending-6.18/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch

@@ -1,7 +1,7 @@
-From 31359e8b7673e656d0591a9eb5014b45911383ae Mon Sep 17 00:00:00 2001
+From 4e1d854199c166f617b93b7542e863e6a8ad2ccb Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 03:44:41 +0000
-Subject: [PATCH 26/35] net: dsa: mxl862xx: add link aggregation support
+Subject: [PATCH 17/26] net: dsa: mxl862xx: add link aggregation support
 
 Implement LAG offloading via the firmware's trunking engine.  A
 dedicated firmware bridge port is allocated per LAG and remains
@@ -234,7 +234,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	return ret;
  }
  
-@@ -1926,6 +2018,408 @@ static int mxl862xx_setup_cpu_bridge(str
+@@ -1881,6 +1973,408 @@ static int mxl862xx_setup_cpu_bridge(str
  	return mxl862xx_set_bridge_port(ds, port);
  }
  
@@ -643,7 +643,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_port_bridge_join(struct dsa_switch *ds, int port,
  				     const struct dsa_bridge bridge,
  				     bool *tx_fwd_offload,
-@@ -1952,7 +2446,18 @@ static int mxl862xx_port_bridge_join(str
+@@ -1907,7 +2401,18 @@ static int mxl862xx_port_bridge_join(str
  		return 0;
  	}
  
@@ -663,7 +663,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  static void mxl862xx_port_bridge_leave(struct dsa_switch *ds, int port,
-@@ -2011,6 +2516,17 @@ static void mxl862xx_port_bridge_leave(s
+@@ -1966,6 +2471,17 @@ static void mxl862xx_port_bridge_leave(s
  			"failed to update CPU VBP for port %d: %pe\n", port,
  			ERR_PTR(err));
  
@@ -681,7 +681,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	if (!dsa_bridge_ports(ds, bridge.dev))
  		mxl862xx_free_bridge(ds, &bridge);
  }
-@@ -2636,18 +3152,17 @@ static int mxl862xx_get_fid(struct dsa_s
+@@ -2591,18 +3107,17 @@ static int mxl862xx_get_fid(struct dsa_s
  }
  
  /**
@@ -707,7 +707,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   */
  static int mxl862xx_fdb_bridge_port(struct dsa_switch *ds, int port,
  				    const struct dsa_db db)
-@@ -2663,7 +3178,7 @@ static int mxl862xx_fdb_bridge_port(stru
+@@ -2618,7 +3133,7 @@ static int mxl862xx_fdb_bridge_port(stru
  			return bp_cpu;
  	}
  
@@ -716,7 +716,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  }
  
  /**
-@@ -2907,11 +3422,43 @@ static int mxl862xx_port_fdb_del(struct
+@@ -2862,11 +3377,43 @@ static int mxl862xx_port_fdb_del(struct
  	return ret;
  }
  
@@ -760,7 +760,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	u32 entry_port_id;
  	int ret;
  
-@@ -2925,7 +3472,7 @@ static int mxl862xx_port_fdb_dump(struct
+@@ -2880,7 +3427,7 @@ static int mxl862xx_port_fdb_dump(struct
  
  		entry_port_id = le32_to_cpu(param.port_id);
  
@@ -769,7 +769,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  			ret = cb(param.mac, FIELD_GET(MXL862XX_TCI_VLAN_ID,
  						      le16_to_cpu(param.tci)),
  				 param.static_entry, data);
-@@ -3562,6 +4109,11 @@ static const struct dsa_switch_ops mxl86
+@@ -3521,6 +4068,11 @@ static const struct dsa_switch_ops mxl86
  	.port_fdb_dump = mxl862xx_port_fdb_dump,
  	.port_mdb_add = mxl862xx_port_mdb_add,
  	.port_mdb_del = mxl862xx_port_mdb_del,
@@ -781,7 +781,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	.port_vlan_filtering = mxl862xx_port_vlan_filtering,
  	.port_vlan_add = mxl862xx_port_vlan_add,
  	.port_vlan_del = mxl862xx_port_vlan_del,
-@@ -3602,6 +4154,7 @@ static int mxl862xx_probe(struct mdio_de
+@@ -3561,6 +4113,7 @@ static int mxl862xx_probe(struct mdio_de
  	ds->num_ports = MXL862XX_MAX_PORTS;
  	ds->fdb_isolation = true;
  	ds->max_num_bridges = MXL862XX_MAX_BRIDGES;
@@ -791,7 +791,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
-@@ -14,6 +14,19 @@
+@@ -16,6 +16,19 @@ struct mxl862xx_priv;
  #define MXL862XX_MAX_BRIDGE_PORTS	128
  #define MXL862XX_TOTAL_EVLAN_ENTRIES	1024
  #define MXL862XX_TOTAL_VF_ENTRIES	1024
@@ -835,9 +835,9 @@ Signed-off-by: Daniel Golle <[email protected]>
  	/* Hardware stats accumulation */
  	struct mxl862xx_port_stats stats;
  	spinlock_t stats_lock;
-@@ -328,6 +351,15 @@ union mxl862xx_fw_version {
-  *                      DSA bridge number. Indexed by dsa_bridge.num
-  *                      (0 .. ds->max_num_bridges).
+@@ -334,6 +357,15 @@ union mxl862xx_fw_version {
+  * @evlan_egress_size:  per-port egress Extended VLAN block size
+  * @cpu_evlan_ingress_size: CPU port ingress EVLAN block size (tag_8021q)
   * @vf_block_size:      per-port VLAN Filter block size
 + * @lag_bridge_ports:   maps DSA LAG ID to firmware bridge port ID;
 + *                      zero means no bridge port allocated for that LAG.
@@ -851,7 +851,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @stats_work:         periodic work item that polls RMON hardware counters
   *                      and accumulates them into 64-bit per-port stats
   */
-@@ -346,6 +378,8 @@ struct mxl862xx_priv {
+@@ -352,6 +384,8 @@ struct mxl862xx_priv {
  	u16 evlan_egress_size;
  	u16 cpu_evlan_ingress_size;
  	u16 vf_block_size;

+ 7 - 7
target/linux/generic/pending-6.18/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch

@@ -1,7 +1,7 @@
-From fbfa1b0649c578e0d43e3a61617b53a9a722efad Mon Sep 17 00:00:00 2001
+From 5528f38c3d709417625eb7f36628be31727a8221 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 12:05:29 +0000
-Subject: [PATCH 27/35] net: dsa: mxl862xx: add support for mirror port
+Subject: [PATCH 18/26] net: dsa: mxl862xx: add support for mirror port
 
 The MxL862xx hardware supports a single monitor port which can be
 configured to mirror any other port's ingress and/or egress traffic.
@@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #define MXL862XX_TFLOW_PCERULEWRITE	(MXL862XX_TFLOW_MAGIC + 0x2)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
-@@ -1129,6 +1129,8 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -1084,6 +1084,8 @@ static int mxl862xx_setup(struct dsa_swi
  				      (n_user_ports + n_cpu_ports);
  	}
  
@@ -59,7 +59,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	ret = mxl862xx_setup_drop_meter(ds);
  	if (ret)
  		return ret;
-@@ -2018,6 +2020,120 @@ static int mxl862xx_setup_cpu_bridge(str
+@@ -1973,6 +1975,120 @@ static int mxl862xx_setup_cpu_bridge(str
  	return mxl862xx_set_bridge_port(ds, port);
  }
  
@@ -180,7 +180,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  /**
   * mxl862xx_lag_master_port - Find the LAG master (lowest-numbered member)
   * @ds: DSA switch
-@@ -4109,6 +4225,8 @@ static const struct dsa_switch_ops mxl86
+@@ -4068,6 +4184,8 @@ static const struct dsa_switch_ops mxl86
  	.port_fdb_dump = mxl862xx_port_fdb_dump,
  	.port_mdb_add = mxl862xx_port_mdb_add,
  	.port_mdb_del = mxl862xx_port_mdb_del,
@@ -210,7 +210,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	/* LAG state */
  	struct dsa_lag *lag;
  	bool lag_tx_enabled;
-@@ -360,6 +365,8 @@ union mxl862xx_fw_version {
+@@ -366,6 +371,8 @@ union mxl862xx_fw_version {
   * @trunk_hash:         current global hash field bitmask (6 bits,
   *                      MXL862XX_TRUNK_HASH_*); union of all active LAGs'
   *                      hash requirements
@@ -219,7 +219,7 @@ Signed-off-by: Daniel Golle <[email protected]>
   * @stats_work:         periodic work item that polls RMON hardware counters
   *                      and accumulates them into 64-bit per-port stats
   */
-@@ -380,6 +387,7 @@ struct mxl862xx_priv {
+@@ -386,6 +393,7 @@ struct mxl862xx_priv {
  	u16 vf_block_size;
  	u16 lag_bridge_ports[MXL862XX_MAX_LAG_IDS + 1];
  	u8 trunk_hash;

+ 3 - 3
target/linux/generic/pending-6.18/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch

@@ -1,7 +1,7 @@
-From 67f82834819b71417b58dc1293c20f71b990264f Mon Sep 17 00:00:00 2001
+From 4059d35a5bbf1901b2e0eb7126369cd713cacfce Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 16:30:08 +0000
-Subject: [PATCH 28/35] net: dsa: wire flash_update devlink callback to drivers
+Subject: [PATCH 19/26] net: dsa: wire flash_update devlink callback to drivers
 
 Add a devlink_flash_update callback to dsa_switch_ops so that DSA
 drivers can support devlink dev flash without open-coding the devlink
@@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 
 --- a/include/net/dsa.h
 +++ b/include/net/dsa.h
-@@ -1172,6 +1172,9 @@ struct dsa_switch_ops {
+@@ -1171,6 +1171,9 @@ struct dsa_switch_ops {
  	int	(*devlink_info_get)(struct dsa_switch *ds,
  				    struct devlink_info_req *req,
  				    struct netlink_ext_ack *extack);

+ 2 - 2
target/linux/generic/pending-6.18/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch

@@ -1,7 +1,7 @@
-From 1a87b829ef3280d646dc480f7b261d9e32896899 Mon Sep 17 00:00:00 2001
+From 0145151dc68aa318d8addb6fe7f12c0967f951da Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 16:30:17 +0000
-Subject: [PATCH 29/35] net: dsa: mxl862xx: add SMDIO clause-22 register access
+Subject: [PATCH 20/26] net: dsa: mxl862xx: add SMDIO clause-22 register access
 
 Add mxl862xx_smdio_read() and mxl862xx_smdio_write() for clause-22
 SMDIO register access. MCUboot rescue mode only exposes clause-22

+ 4 - 4
target/linux/generic/pending-6.18/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch

@@ -1,7 +1,7 @@
-From b7e8f8fd4493b255f0f01fe790a73ad61b5e8ce8 Mon Sep 17 00:00:00 2001
+From bdbca48510e3e96ed9210f20fa4244dd6df5d44a Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 16:30:31 +0000
-Subject: [PATCH 30/35] net: dsa: mxl862xx: add devlink flash_update and
+Subject: [PATCH 21/26] net: dsa: mxl862xx: add devlink flash_update and
  info_get
 
 Implement runtime firmware upgrade via "devlink dev flash" and version
@@ -546,7 +546,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #include "mxl862xx-host.h"
  #include "mxl862xx-phylink.h"
  
-@@ -4245,6 +4246,9 @@ static const struct dsa_switch_ops mxl86
+@@ -4204,6 +4205,9 @@ static const struct dsa_switch_ops mxl86
  	.get_pause_stats = mxl862xx_get_pause_stats,
  	.get_stats64 = mxl862xx_get_stats64,
  	.self_test = mxl862xx_serdes_self_test,
@@ -558,7 +558,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int mxl862xx_probe(struct mdio_device *mdiodev)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
-@@ -388,6 +388,8 @@ struct mxl862xx_priv {
+@@ -394,6 +394,8 @@ struct mxl862xx_priv {
  	u16 lag_bridge_ports[MXL862XX_MAX_LAG_IDS + 1];
  	u8 trunk_hash;
  	int mirror_dest;

+ 4 - 4
target/linux/generic/pending-6.18/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch

@@ -1,7 +1,7 @@
-From 2cb9aeb3a8d7ebac20331e0a533dcfbd73fa4237 Mon Sep 17 00:00:00 2001
+From 8deb5be9638f7eb3009ed3eb619eedadee1df523 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 23:42:18 +0000
-Subject: [PATCH 31/35] net: dsa: mxl862xx: implement port MTU configuration
+Subject: [PATCH 22/26] net: dsa: mxl862xx: implement port MTU configuration
 
 The firmware exposes a global max_packet_len register via
 MXL862XX_COMMON_CFGSET. Since this is switch-wide rather than
@@ -25,7 +25,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  #include <linux/module.h>
  #include <linux/of_device.h>
  #include <linux/of_mdio.h>
-@@ -3768,6 +3769,53 @@ static int mxl862xx_set_ageing_time(stru
+@@ -3723,6 +3724,53 @@ static int mxl862xx_set_ageing_time(stru
  	return ret;
  }
  
@@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static void mxl862xx_port_stp_state_set(struct dsa_switch *ds, int port,
  					u8 state)
  {
-@@ -4215,6 +4263,8 @@ static const struct dsa_switch_ops mxl86
+@@ -4174,6 +4222,8 @@ static const struct dsa_switch_ops mxl86
  	.port_disable = mxl862xx_port_disable,
  	.port_fast_age = mxl862xx_port_fast_age,
  	.set_ageing_time = mxl862xx_set_ageing_time,

+ 18 - 19
target/linux/generic/pending-6.18/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch

@@ -1,7 +1,7 @@
-From d55ca68eb0d20a66c32d531b0a454871b486c1b1 Mon Sep 17 00:00:00 2001
+From 13a4c918cd9ded7207f38033511ab13f7aff9bd2 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 01:47:19 +0000
-Subject: [PATCH 32/35] net: dsa: mxl862xx: support BR_HAIRPIN_MODE bridge flag
+Subject: [PATCH 23/26] net: dsa: mxl862xx: support BR_HAIRPIN_MODE bridge flag
 
 Implement hairpin mode by including the port's own bridge port ID in
 its forwarding portmap. When hairpin is enabled, bridged frames whose
@@ -18,9 +18,9 @@ bridge member rebuild since only the calling port is affected.
 
 Signed-off-by: Daniel Golle <[email protected]>
 ---
- drivers/net/dsa/mxl862xx/mxl862xx.c | 30 ++++++++++++++++++++++++++++-
+ drivers/net/dsa/mxl862xx/mxl862xx.c | 29 +++++++++++++++++++++++++++--
  drivers/net/dsa/mxl862xx/mxl862xx.h |  6 ++++++
- 2 files changed, 35 insertions(+), 1 deletion(-)
+ 2 files changed, 33 insertions(+), 2 deletions(-)
 
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
@@ -40,7 +40,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  		err = mxl862xx_set_bridge_port(ds, port);
  		if (err)
  			ret = err;
-@@ -3939,7 +3948,7 @@ static int mxl862xx_port_pre_bridge_flag
+@@ -3898,7 +3907,7 @@ static int mxl862xx_port_pre_bridge_flag
  					  struct netlink_ext_ack *extack)
  {
  	if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD |
@@ -49,20 +49,19 @@ Signed-off-by: Daniel Golle <[email protected]>
  		return -EINVAL;
  
  	return 0;
-@@ -3954,6 +3963,7 @@ static int mxl862xx_port_bridge_flags(st
+@@ -3912,6 +3921,7 @@ static int mxl862xx_port_bridge_flags(st
+ 	unsigned long old_block = priv->ports[port].flood_block;
  	unsigned long block = old_block;
- 	bool need_update = false;
  	int ret;
 +	u16 bp;
  
  	if (flags.mask & BR_FLOOD) {
  		if (flags.val & BR_FLOOD)
-@@ -3988,6 +3998,24 @@ static int mxl862xx_port_bridge_flags(st
- 		ret = mxl862xx_set_bridge_port(ds, port);
- 		if (ret)
- 			return ret;
-+	}
-+
+@@ -3940,7 +3950,22 @@ static int mxl862xx_port_bridge_flags(st
+ 	if (flags.mask & BR_LEARNING)
+ 		priv->ports[port].learning = !!(flags.val & BR_LEARNING);
+ 
+-	if ((block != old_block) || (flags.mask & BR_LEARNING)) {
 +	if (flags.mask & BR_HAIRPIN_MODE) {
 +		bp = mxl862xx_lag_bridge_port(priv, port);
 +		priv->ports[port].hairpin = !!(flags.val & BR_HAIRPIN_MODE);
@@ -75,13 +74,13 @@ Signed-off-by: Daniel Golle <[email protected]>
 +			__set_bit(bp, priv->ports[port].portmap);
 +		else
 +			__clear_bit(bp, priv->ports[port].portmap);
++	}
 +
-+		ret = mxl862xx_set_bridge_port(ds, port);
-+		if (ret)
-+			return ret;
- 	}
- 
- 	return 0;
++	if ((block != old_block) ||
++	    (flags.mask & (BR_LEARNING | BR_HAIRPIN_MODE))) {
+ 		priv->ports[port].flood_block = block;
+ 		ret = mxl862xx_set_bridge_port(ds, port);
+ 		if (ret)
 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h
 +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
 @@ -241,6 +241,10 @@ struct mxl862xx_port_stats {

+ 6 - 6
target/linux/generic/pending-6.18/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch

@@ -1,7 +1,7 @@
-From 74b6654ba74eb142340de4c51b97c0221cfcae37 Mon Sep 17 00:00:00 2001
+From d49d1f8bee29269def7593f980d0e08bfb5c3ef8 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Wed, 25 Mar 2026 01:51:33 +0000
-Subject: [PATCH 33/35] net: dsa: mxl862xx: support BR_ISOLATED bridge flag
+Subject: [PATCH 24/26] net: dsa: mxl862xx: support BR_ISOLATED bridge flag
 
 Implement port isolation by excluding isolated ports from each other's
 forwarding portmaps in sync_bridge_members. Non-isolated ports can
@@ -34,7 +34,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  			if (member != port) {
  				bp = mxl862xx_lag_bridge_port(priv,
  							     member);
-@@ -3948,7 +3956,7 @@ static int mxl862xx_port_pre_bridge_flag
+@@ -3907,7 +3915,7 @@ static int mxl862xx_port_pre_bridge_flag
  					  struct netlink_ext_ack *extack)
  {
  	if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD |
@@ -43,15 +43,15 @@ Signed-off-by: Daniel Golle <[email protected]>
  		return -EINVAL;
  
  	return 0;
-@@ -3962,6 +3970,7 @@ static int mxl862xx_port_bridge_flags(st
+@@ -3920,6 +3928,7 @@ static int mxl862xx_port_bridge_flags(st
+ 	struct mxl862xx_priv *priv = ds->priv;
  	unsigned long old_block = priv->ports[port].flood_block;
  	unsigned long block = old_block;
- 	bool need_update = false;
 +	struct dsa_port *dp;
  	int ret;
  	u16 bp;
  
-@@ -4018,6 +4027,21 @@ static int mxl862xx_port_bridge_flags(st
+@@ -3972,6 +3981,21 @@ static int mxl862xx_port_bridge_flags(st
  			return ret;
  	}
  

+ 3 - 3
target/linux/generic/pending-6.18/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch

@@ -1,7 +1,7 @@
-From 0902a6790750714445c75a66d60f1bc4897126ce Mon Sep 17 00:00:00 2001
+From c2fb7f0df63ac994850f766e7f2eb50c6c5ef2cf Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:17:49 +0000
-Subject: [PATCH 34/35] DO NOT SUBMIT: net: dsa: mxl862xx: re-introduce PCE
+Subject: [PATCH 25/26] DO NOT SUBMIT: net: dsa: mxl862xx: re-introduce PCE
  workaround for old firmware
 
 Re-introduce the mxl862xx_disable_fw_global_rules() function that
@@ -64,7 +64,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  
  /* Per-CTP offset used for the link-local trap rule. Each port's CTP
   * flow-table block is pre-allocated by the firmware during init (44
-@@ -1154,9 +1191,11 @@ static int mxl862xx_setup(struct dsa_swi
+@@ -1109,9 +1146,11 @@ static int mxl862xx_setup(struct dsa_swi
  	if (ret)
  		return ret;
  

+ 2 - 2
target/linux/generic/pending-6.18/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch

@@ -1,7 +1,7 @@
-From 0ac876d5b952218ab79ea0a0815cf6fd1290b1d0 Mon Sep 17 00:00:00 2001
+From f0548f842b9ff31f19452a2fc72a16f937d86008 Mon Sep 17 00:00:00 2001
 From: Daniel Golle <[email protected]>
 Date: Tue, 24 Mar 2026 18:19:56 +0000
-Subject: [PATCH 35/35] DO NOT SUBMIT: net: dsa: mxl862xx: legacy SFP API
+Subject: [PATCH 26/26] DO NOT SUBMIT: net: dsa: mxl862xx: legacy SFP API
  fallback for old firmware
 
 Re-introduce the SYS_MISC_SFP_SET-based PCS implementation as a