1
1
openwrt/target/linux/generic/pending-6.12/760-17-DO-NOT-SUBMIT-net-dsa-mxl862xx-re-introduce-PCE-work.patch
Daniel Golle 5b69e6a4a6 generic: 6.12: update MxL862xx DSA switch driver
Update driver to be ready for the upcoming firmware release.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-05-27 19:01:52 +01:00

135 lines
5.4 KiB
Diff

From 8120b9b88ec47ee41b8350e3e4341839f5fdc28e Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Tue, 24 Mar 2026 18:17:49 +0000
Subject: [PATCH 17/19] DO NOT SUBMIT: net: dsa: mxl862xx: re-introduce PCE
workaround for old firmware
Re-introduce the legacy PCE rule paths needed for firmware versions
older than 1.0.83.
Firmware >= 1.0.83 exposes the new GSW_TFLOW_PCERULELOGICWRITE API
which selects the per-CTP block via @region/@logicalportid and grows
the hardware block on demand. Older firmware lacks that command and
exposes only the legacy GSW_TFLOW_PCERULEWRITE call, where the rule
index is a direct offset into a fixed-size pre-allocated CTP block.
Add MXL862XX_TFLOW_PCERULEWRITE back to mxl862xx-cmd.h and make
mxl862xx_pce_rule_write() pick the right command at runtime based on
the cached firmware version.
In addition, firmware older than 1.0.80 still installs global PCE
rules at boot that redirect link-local frames (BPDUs, LLDP, LACP) to
port 0 (the on-chip microcontroller) instead of the DSA CPU port.
With port 0 disabled under DSA these rules silently drop matching
traffic. Re-introduce mxl862xx_disable_fw_global_rules() to clear
them out during setup. The upstream submission replaced that call
with a dev_warn() since firmware >= 1.0.80 no longer installs the
problematic rules.
This commit is for downstream use only and must not be submitted
upstream.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/dsa/mxl862xx/mxl862xx-cmd.h | 1 +
drivers/net/dsa/mxl862xx/mxl862xx.c | 61 +++++++++++++++++++++----
2 files changed, 53 insertions(+), 9 deletions(-)
--- a/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h
+++ b/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h
@@ -32,6 +32,7 @@
#define MXL862XX_COMMON_MONITORPORTCFGSET (MXL862XX_COMMON_MAGIC + 0xe)
#define MXL862XX_COMMON_REGISTERMOD (MXL862XX_COMMON_MAGIC + 0x11)
+#define MXL862XX_TFLOW_PCERULEWRITE (MXL862XX_TFLOW_MAGIC + 0x2)
#define MXL862XX_TFLOW_PCERULEALLOC (MXL862XX_TFLOW_MAGIC + 0x4)
#define MXL862XX_TFLOW_PCERULEFREE (MXL862XX_TFLOW_MAGIC + 0x5)
#define MXL862XX_TFLOW_PCERULELOGICWRITE \
--- a/drivers/net/dsa/mxl862xx/mxl862xx.c
+++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
@@ -449,6 +449,43 @@ static int mxl862xx_setup_drop_meter(str
return MXL862XX_API_WRITE(priv, MXL862XX_COMMON_REGISTERMOD, reg);
}
+/* Disable firmware global PCE rules that trap various protocols to the
+ * on-die microcontroller (port 0) via PORTMAP_CPU. Under DSA, these
+ * frames must either reach the host CPU via per-port rules (link-local)
+ * or through the normal bridge forwarding path (ARP broadcast), so the
+ * global firmware rules are not needed. With the microcontroller port
+ * disabled they would silently drop matching traffic.
+ *
+ * Global rules have lower indices than CTP rules, hence higher priority
+ * in the PCE pipeline -- they must be explicitly disabled or they will
+ * shadow the per-CTP traps.
+ *
+ * Indices from gsw_flow_index.h:
+ * 1 -- BPDU (STP/RSTP, dst 01:80:c2:00:00:00)
+ * 3 -- LLDP (EtherType 0x88cc)
+ * 4 -- OAM/LACP (EtherType 0x8809)
+ * 6 -- System MAC (dst 02:e0:92:00:00:01, vendor management MAC)
+ * 7 -- ARP Request (broadcast + EtherType 0x0806 + TPA 192.0.2.1)
+ */
+static int mxl862xx_disable_fw_global_rules(struct dsa_switch *ds)
+{
+ static const u16 indices[] = { 1, 3, 4, 6, 7 };
+ struct mxl862xx_pce_rule rule;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(indices); i++) {
+ memset(&rule, 0, sizeof(rule));
+ rule.pattern.index = cpu_to_le16(indices[i]);
+ /* pattern.enable == 0 -> rule is disabled */
+
+ ret = MXL862XX_API_WRITE(ds->priv,
+ MXL862XX_TFLOW_PCERULEWRITE, rule);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
/* Per-CTP logical indices for protocol trap rules.
*
@@ -463,16 +500,20 @@ static int mxl862xx_setup_drop_meter(str
#define MXL862XX_MLDV1_CTP_INDEX 3
#define MXL862XX_MLDV2_CTP_INDEX 4
-/* Install (or overwrite) a PCE rule via the firmware's logical-index
- * API. The firmware translates the logical index in @rule->pattern.index
- * to a physical position within the block selected by @rule->region and
- * @rule->logicalportid, and expands the hardware block size as needed.
+/* Install (or overwrite) a PCE rule. On firmware >= 1.0.83 use the
+ * logical-index API (PCERULELOGICWRITE), which grows the per-CTP block
+ * on demand. On older firmware that API does not exist, so fall back
+ * to the legacy PCERULEWRITE call which uses the rule index as a
+ * direct offset into a fixed-size pre-allocated CTP block.
*/
static int mxl862xx_pce_rule_write(struct mxl862xx_priv *priv,
struct mxl862xx_pce_rule *rule)
{
- return MXL862XX_API_WRITE(priv, MXL862XX_TFLOW_PCERULELOGICWRITE,
- *rule);
+ u16 cmd = MXL862XX_FW_VER_MIN(priv, 1, 0, 83) ?
+ MXL862XX_TFLOW_PCERULELOGICWRITE :
+ MXL862XX_TFLOW_PCERULEWRITE;
+
+ return MXL862XX_API_WRITE(priv, cmd, *rule);
}
/**
@@ -1130,9 +1171,11 @@ static int mxl862xx_setup(struct dsa_swi
if (ret)
return ret;
- if (!MXL862XX_FW_VER_MIN(priv, 1, 0, 80))
- dev_warn(ds->dev, "firmware < 1.0.80 installs global PCE rules "
- "that interfere with DSA operation, please update\n");
+ if (!MXL862XX_FW_VER_MIN(priv, 1, 0, 80)) {
+ ret = mxl862xx_disable_fw_global_rules(ds);
+ if (ret)
+ return ret;
+ }
/* Pre-allocate firmware resources for all ports. The DSA core
* calls change_tag_protocol() between setup() and port_setup(),