From 5ee6ddb461e848d0475996ff8f26e8104d04a098 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 31 Mar 2026 03:13:41 +0100 Subject: [PATCH] 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 --- ...x-cancel-pending-work-on-probe-error.patch | 37 ++++ ...ove-dsa_bridge_ports-helper-to-dsa.h.patch | 4 +- ...sa-add-bridge-member-iteration-macro.patch | 4 +- ...2xx-set-dsa_default_offload_fwd_mark.patch | 4 +- ...mxl862xx-implement-bridge-offloading.patch | 71 ++++---- ...xl862xx-implement-VLAN-functionality.patch | 123 ++----------- ...862xx-add-ethtool-statistics-support.patch | 8 +- ...-dsa-mxl862xx-implement-.get_stats64.patch | 122 ++++++++++--- ...-store-firmware-version-for-feature-.patch | 22 +-- ...-move-phylink-stubs-to-mxl862xx-phyl.patch | 8 +- ...x-move-API-macros-to-mxl862xx-host.h.patch | 4 +- ...xl862xx-add-support-for-SerDes-ports.patch | 14 +- ...l862xx-add-SerDes-ethtool-statistics.patch | 10 +- ...-add-SerDes-self-test-via-PRBS-and-B.patch | 6 +- ...-trap-link-local-frames-to-the-CPU-p.patch | 6 +- ...-warn-about-old-firmware-default-PCE.patch | 6 +- ...1Q-VLAN-based-tag-driver-for-MxL862x.patch | 168 +++++++----------- ...xl862xx-add-link-aggregation-support.patch | 32 ++-- ...mxl862xx-add-support-for-mirror-port.patch | 14 +- ...sh_update-devlink-callback-to-driver.patch | 6 +- ...-add-SMDIO-clause-22-register-access.patch | 4 +- ...-add-devlink-flash_update-and-info_g.patch | 8 +- ...2xx-implement-port-MTU-configuration.patch | 8 +- ...-support-BR_HAIRPIN_MODE-bridge-flag.patch | 37 ++-- ...62xx-support-BR_ISOLATED-bridge-flag.patch | 12 +- ...t-dsa-mxl862xx-re-introduce-PCE-work.patch | 6 +- ...t-dsa-mxl862xx-legacy-SFP-API-fallba.patch | 4 +- ...x-cancel-pending-work-on-probe-error.patch | 37 ++++ ...ove-dsa_bridge_ports-helper-to-dsa.h.patch | 6 +- ...sa-add-bridge-member-iteration-macro.patch | 4 +- ...2xx-set-dsa_default_offload_fwd_mark.patch | 4 +- ...mxl862xx-implement-bridge-offloading.patch | 71 ++++---- ...xl862xx-implement-VLAN-functionality.patch | 123 ++----------- ...862xx-add-ethtool-statistics-support.patch | 8 +- ...-dsa-mxl862xx-implement-.get_stats64.patch | 122 ++++++++++--- ...-store-firmware-version-for-feature-.patch | 22 +-- ...-move-phylink-stubs-to-mxl862xx-phyl.patch | 8 +- ...x-move-API-macros-to-mxl862xx-host.h.patch | 4 +- ...xl862xx-add-support-for-SerDes-ports.patch | 14 +- ...l862xx-add-SerDes-ethtool-statistics.patch | 10 +- ...-add-SerDes-self-test-via-PRBS-and-B.patch | 6 +- ...-trap-link-local-frames-to-the-CPU-p.patch | 6 +- ...-warn-about-old-firmware-default-PCE.patch | 6 +- ...1Q-VLAN-based-tag-driver-for-MxL862x.patch | 168 +++++++----------- ...xl862xx-add-link-aggregation-support.patch | 32 ++-- ...mxl862xx-add-support-for-mirror-port.patch | 14 +- ...sh_update-devlink-callback-to-driver.patch | 6 +- ...-add-SMDIO-clause-22-register-access.patch | 4 +- ...-add-devlink-flash_update-and-info_g.patch | 8 +- ...2xx-implement-port-MTU-configuration.patch | 8 +- ...-support-BR_HAIRPIN_MODE-bridge-flag.patch | 37 ++-- ...62xx-support-BR_ISOLATED-bridge-flag.patch | 12 +- ...t-dsa-mxl862xx-re-introduce-PCE-work.patch | 6 +- ...t-dsa-mxl862xx-legacy-SFP-API-fallba.patch | 4 +- 54 files changed, 735 insertions(+), 763 deletions(-) create mode 100644 target/linux/generic/pending-6.12/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch create mode 100644 target/linux/generic/pending-6.18/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch diff --git a/target/linux/generic/pending-6.12/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch b/target/linux/generic/pending-6.12/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch new file mode 100644 index 0000000000..d215cbbb8d --- /dev/null +++ b/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 +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 +--- + 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) diff --git a/target/linux/generic/pending-6.12/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch b/target/linux/generic/pending-6.12/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch index 843ca14b64..c203174a8a 100644 --- a/target/linux/generic/pending-6.12/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch +++ b/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 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. diff --git a/target/linux/generic/pending-6.12/760-02-net-dsa-add-bridge-member-iteration-macro.patch b/target/linux/generic/pending-6.12/760-02-net-dsa-add-bridge-member-iteration-macro.patch index af90028b98..67dc948461 100644 --- a/target/linux/generic/pending-6.12/760-02-net-dsa-add-bridge-member-iteration-macro.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.12/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch b/target/linux/generic/pending-6.12/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch index 7c824994aa..e47f4e44c8 100644 --- a/target/linux/generic/pending-6.12/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.12/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch b/target/linux/generic/pending-6.12/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch index 9d1c1c958b..a545e70677 100644 --- a/target/linux/generic/pending-6.12/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch +++ b/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 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 --- 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 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 + 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 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 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 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 } 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 + 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 +/* 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 + 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 + 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 + 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 }; 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 + 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 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 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); diff --git a/target/linux/generic/pending-6.12/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch b/target/linux/generic/pending-6.12/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch index 109808792c..c9e1769d98 100644 --- a/target/linux/generic/pending-6.12/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch +++ b/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 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 --- - 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 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 + 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 + 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 + 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 + 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 + 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 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 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 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 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 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 }; 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 /* 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 * 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 diff --git a/target/linux/generic/pending-6.12/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch b/target/linux/generic/pending-6.12/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch index a1517ccde0..9788fb4021 100644 --- a/target/linux/generic/pending-6.12/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch +++ b/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 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 #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 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, diff --git a/target/linux/generic/pending-6.12/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch b/target/linux/generic/pending-6.12/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch index 9d4d93bc2d..55b81a7023 100644 --- a/target/linux/generic/pending-6.12/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch +++ b/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 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 --- - 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 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 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 + 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 + 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 }; 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 + 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 */ 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 + 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 */ 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; diff --git a/target/linux/generic/pending-6.12/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch b/target/linux/generic/pending-6.12/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch index d62b466029..03aeb8c9b7 100644 --- a/target/linux/generic/pending-6.12/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch +++ b/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 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 #include #include #include -@@ -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 +#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 * @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]; diff --git a/target/linux/generic/pending-6.12/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch b/target/linux/generic/pending-6.12/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch index 833ec0642e..2ce4d1fb0e 100644 --- a/target/linux/generic/pending-6.12/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch +++ b/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 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 #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 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, }; diff --git a/target/linux/generic/pending-6.12/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch b/target/linux/generic/pending-6.12/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch index 01013eec3e..7ac42cb3a6 100644 --- a/target/linux/generic/pending-6.12/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.12/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch b/target/linux/generic/pending-6.12/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch index 790f50c87d..6fe50aeb90 100644 --- a/target/linux/generic/pending-6.12/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch +++ b/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 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 #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 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 * 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 * @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]; diff --git a/target/linux/generic/pending-6.12/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch b/target/linux/generic/pending-6.12/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch index 5f1e1bb3e5..749a1ee2a6 100644 --- a/target/linux/generic/pending-6.12/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch +++ b/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 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 #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 } 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 } 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); } diff --git a/target/linux/generic/pending-6.12/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch b/target/linux/generic/pending-6.12/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch index 1da11ae9c0..baba8311c6 100644 --- a/target/linux/generic/pending-6.12/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch +++ b/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 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 #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, diff --git a/target/linux/generic/pending-6.12/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch b/target/linux/generic/pending-6.12/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch index 385e44f480..56d3612310 100644 --- a/target/linux/generic/pending-6.12/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch +++ b/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 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 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; diff --git a/target/linux/generic/pending-6.12/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch b/target/linux/generic/pending-6.12/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch index 38dc45c594..d590f54f47 100644 --- a/target/linux/generic/pending-6.12/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch +++ b/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 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 --- 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; diff --git a/target/linux/generic/pending-6.12/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch b/target/linux/generic/pending-6.12/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch index 8663883077..9b7a719db0 100644 --- a/target/linux/generic/pending-6.12/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch +++ b/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 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 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 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 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 - /* 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 + * 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 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 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 * 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 } 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 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 * 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 * * 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 { 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 } 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 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 * 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 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 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 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 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 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 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 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 - /* 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 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 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 { 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 + 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 +{ + 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 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 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 - 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 + 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 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 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 + 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 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 .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 .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 + 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 + 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 - #include - --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 /* 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 }; --- 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, diff --git a/target/linux/generic/pending-6.12/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch b/target/linux/generic/pending-6.12/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch index d373f6511f..0e4074254b 100644 --- a/target/linux/generic/pending-6.12/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch +++ b/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 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 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 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 } 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 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 */ 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 } /** -@@ -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 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 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 .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 --- 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 /* 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 * @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; diff --git a/target/linux/generic/pending-6.12/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch b/target/linux/generic/pending-6.12/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch index faf69c0c0e..cdcbaee869 100644 --- a/target/linux/generic/pending-6.12/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch +++ b/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 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 #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 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 /** * 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 /* 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 * @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; diff --git a/target/linux/generic/pending-6.12/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch b/target/linux/generic/pending-6.12/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch index bd0e9ef628..2adad2d11c 100644 --- a/target/linux/generic/pending-6.12/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch +++ b/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 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 --- 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); diff --git a/target/linux/generic/pending-6.12/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch b/target/linux/generic/pending-6.12/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch index 17668b9734..2986143175 100644 --- a/target/linux/generic/pending-6.12/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.12/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch b/target/linux/generic/pending-6.12/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch index 28b91f8021..d731ec1b08 100644 --- a/target/linux/generic/pending-6.12/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch +++ b/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 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 #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 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; diff --git a/target/linux/generic/pending-6.12/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch b/target/linux/generic/pending-6.12/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch index 1869a9f17c..1a22bba1f1 100644 --- a/target/linux/generic/pending-6.12/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch +++ b/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 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 #include #include #include -@@ -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 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, diff --git a/target/linux/generic/pending-6.12/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch b/target/linux/generic/pending-6.12/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch index bf4d2f0ca7..dfbf953754 100644 --- a/target/linux/generic/pending-6.12/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch +++ b/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 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 --- - 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 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 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 + __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 { diff --git a/target/linux/generic/pending-6.12/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch b/target/linux/generic/pending-6.12/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch index a524d157e5..c67d95d5c5 100644 --- a/target/linux/generic/pending-6.12/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch +++ b/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 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 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 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; } diff --git a/target/linux/generic/pending-6.12/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch b/target/linux/generic/pending-6.12/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch index 98cfb44d48..6e5d25069d 100644 --- a/target/linux/generic/pending-6.12/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch +++ b/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 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 /* 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; diff --git a/target/linux/generic/pending-6.12/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch b/target/linux/generic/pending-6.12/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch index 41cd927ac4..cba47630f4 100644 --- a/target/linux/generic/pending-6.12/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.18/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch b/target/linux/generic/pending-6.18/760-00-net-dsa-mxl862xx-cancel-pending-work-on-probe-error.patch new file mode 100644 index 0000000000..d215cbbb8d --- /dev/null +++ b/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 +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 +--- + 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) diff --git a/target/linux/generic/pending-6.18/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch b/target/linux/generic/pending-6.18/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch index 843ca14b64..51d3644d58 100644 --- a/target/linux/generic/pending-6.18/760-01-net-dsa-move-dsa_bridge_ports-helper-to-dsa.h.patch +++ b/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 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 --- 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 diff --git a/target/linux/generic/pending-6.18/760-02-net-dsa-add-bridge-member-iteration-macro.patch b/target/linux/generic/pending-6.18/760-02-net-dsa-add-bridge-member-iteration-macro.patch index af90028b98..67dc948461 100644 --- a/target/linux/generic/pending-6.18/760-02-net-dsa-add-bridge-member-iteration-macro.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.18/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch b/target/linux/generic/pending-6.18/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch index 7c824994aa..e47f4e44c8 100644 --- a/target/linux/generic/pending-6.18/760-03-dsa-tag_mxl862xx-set-dsa_default_offload_fwd_mark.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.18/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch b/target/linux/generic/pending-6.18/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch index 9d1c1c958b..a545e70677 100644 --- a/target/linux/generic/pending-6.18/760-04-net-dsa-mxl862xx-implement-bridge-offloading.patch +++ b/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 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 --- 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 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 + 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 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 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 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 } 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 + 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 +/* 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 + 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 + 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 + 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 }; 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 + 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 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 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); diff --git a/target/linux/generic/pending-6.18/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch b/target/linux/generic/pending-6.18/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch index 109808792c..c9e1769d98 100644 --- a/target/linux/generic/pending-6.18/760-05-net-dsa-mxl862xx-implement-VLAN-functionality.patch +++ b/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 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 --- - 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 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 + 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 + 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 + 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 + 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 + 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 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 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 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 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 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 }; 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 /* 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 * 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 diff --git a/target/linux/generic/pending-6.18/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch b/target/linux/generic/pending-6.18/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch index a1517ccde0..9788fb4021 100644 --- a/target/linux/generic/pending-6.18/760-06-net-dsa-mxl862xx-add-ethtool-statistics-support.patch +++ b/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 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 #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 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, diff --git a/target/linux/generic/pending-6.18/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch b/target/linux/generic/pending-6.18/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch index 9d4d93bc2d..55b81a7023 100644 --- a/target/linux/generic/pending-6.18/760-07-net-dsa-mxl862xx-implement-.get_stats64.patch +++ b/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 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 --- - 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 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 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 + 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 + 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 }; 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 + 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 */ 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 + 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 */ 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; diff --git a/target/linux/generic/pending-6.18/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch b/target/linux/generic/pending-6.18/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch index d62b466029..03aeb8c9b7 100644 --- a/target/linux/generic/pending-6.18/760-08-net-dsa-mxl862xx-store-firmware-version-for-feature-.patch +++ b/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 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 #include #include #include -@@ -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 +#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 * @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]; diff --git a/target/linux/generic/pending-6.18/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch b/target/linux/generic/pending-6.18/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch index 833ec0642e..2ce4d1fb0e 100644 --- a/target/linux/generic/pending-6.18/760-09-net-dsa-mxl862xx-move-phylink-stubs-to-mxl862xx-phyl.patch +++ b/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 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 #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 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, }; diff --git a/target/linux/generic/pending-6.18/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch b/target/linux/generic/pending-6.18/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch index 01013eec3e..7ac42cb3a6 100644 --- a/target/linux/generic/pending-6.18/760-10-net-dsa-mxl862xx-move-API-macros-to-mxl862xx-host.h.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.18/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch b/target/linux/generic/pending-6.18/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch index 5680ac1747..ebd51cee4e 100644 --- a/target/linux/generic/pending-6.18/760-11-net-dsa-mxl862xx-add-support-for-SerDes-ports.patch +++ b/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 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 #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 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 * 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 * @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]; diff --git a/target/linux/generic/pending-6.18/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch b/target/linux/generic/pending-6.18/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch index 26c0452fb8..b5738eebc7 100644 --- a/target/linux/generic/pending-6.18/760-12-net-dsa-mxl862xx-add-SerDes-ethtool-statistics.patch +++ b/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 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 #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 } 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 } 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); } diff --git a/target/linux/generic/pending-6.18/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch b/target/linux/generic/pending-6.18/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch index 1fb76182d3..5760db143e 100644 --- a/target/linux/generic/pending-6.18/760-13-net-dsa-mxl862xx-add-SerDes-self-test-via-PRBS-and-B.patch +++ b/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 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 #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, diff --git a/target/linux/generic/pending-6.18/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch b/target/linux/generic/pending-6.18/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch index 385e44f480..56d3612310 100644 --- a/target/linux/generic/pending-6.18/760-14-net-dsa-mxl862xx-trap-link-local-frames-to-the-CPU-p.patch +++ b/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 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 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; diff --git a/target/linux/generic/pending-6.18/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch b/target/linux/generic/pending-6.18/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch index 38dc45c594..d590f54f47 100644 --- a/target/linux/generic/pending-6.18/760-15-net-dsa-mxl862xx-warn-about-old-firmware-default-PCE.patch +++ b/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 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 --- 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; diff --git a/target/linux/generic/pending-6.18/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch b/target/linux/generic/pending-6.18/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch index 8663883077..9b7a719db0 100644 --- a/target/linux/generic/pending-6.18/760-16-net-dsa-add-802.1Q-VLAN-based-tag-driver-for-MxL862x.patch +++ b/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 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 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 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 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 - /* 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 + * 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 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 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 * 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 } 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 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 * 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 * * 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 { 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 } 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 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 * 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 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 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 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 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 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 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 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 - /* 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 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 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 { 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 + 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 +{ + 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 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 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 - 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 + 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 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 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 + 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 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 .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 .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 + 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 + 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 - #include - --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 /* 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 }; --- 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, diff --git a/target/linux/generic/pending-6.18/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch b/target/linux/generic/pending-6.18/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch index d373f6511f..0e4074254b 100644 --- a/target/linux/generic/pending-6.18/760-17-net-dsa-mxl862xx-add-link-aggregation-support.patch +++ b/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 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 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 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 } 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 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 */ 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 } /** -@@ -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 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 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 .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 --- 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 /* 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 * @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; diff --git a/target/linux/generic/pending-6.18/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch b/target/linux/generic/pending-6.18/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch index faf69c0c0e..cdcbaee869 100644 --- a/target/linux/generic/pending-6.18/760-18-net-dsa-mxl862xx-add-support-for-mirror-port.patch +++ b/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 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 #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 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 /** * 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 /* 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 * @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; diff --git a/target/linux/generic/pending-6.18/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch b/target/linux/generic/pending-6.18/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch index 98144a4c0d..2ab03a5d26 100644 --- a/target/linux/generic/pending-6.18/760-19-net-dsa-wire-flash_update-devlink-callback-to-driver.patch +++ b/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 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 --- 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); diff --git a/target/linux/generic/pending-6.18/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch b/target/linux/generic/pending-6.18/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch index 17668b9734..2986143175 100644 --- a/target/linux/generic/pending-6.18/760-20-net-dsa-mxl862xx-add-SMDIO-clause-22-register-access.patch +++ b/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 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 diff --git a/target/linux/generic/pending-6.18/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch b/target/linux/generic/pending-6.18/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch index 28b91f8021..d731ec1b08 100644 --- a/target/linux/generic/pending-6.18/760-21-net-dsa-mxl862xx-add-devlink-flash_update-and-info_g.patch +++ b/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 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 #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 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; diff --git a/target/linux/generic/pending-6.18/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch b/target/linux/generic/pending-6.18/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch index 1869a9f17c..1a22bba1f1 100644 --- a/target/linux/generic/pending-6.18/760-22-net-dsa-mxl862xx-implement-port-MTU-configuration.patch +++ b/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 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 #include #include #include -@@ -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 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, diff --git a/target/linux/generic/pending-6.18/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch b/target/linux/generic/pending-6.18/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch index bf4d2f0ca7..dfbf953754 100644 --- a/target/linux/generic/pending-6.18/760-23-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch +++ b/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 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 --- - 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 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 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 + __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 { diff --git a/target/linux/generic/pending-6.18/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch b/target/linux/generic/pending-6.18/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch index a524d157e5..c67d95d5c5 100644 --- a/target/linux/generic/pending-6.18/760-24-net-dsa-mxl862xx-support-BR_ISOLATED-bridge-flag.patch +++ b/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 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 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 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; } diff --git a/target/linux/generic/pending-6.18/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch b/target/linux/generic/pending-6.18/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch index 98cfb44d48..6e5d25069d 100644 --- a/target/linux/generic/pending-6.18/760-25-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch +++ b/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 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 /* 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; diff --git a/target/linux/generic/pending-6.18/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch b/target/linux/generic/pending-6.18/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch index 8a96401456..ddf7da101b 100644 --- a/target/linux/generic/pending-6.18/760-26-DO-NOT-SUBMIT-net-dsa-mxl862xx-legacy-SFP-API-fallba.patch +++ b/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 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