Skip to content

Mxl862xx fw 1.0.85 - #212

Merged
frank-w merged 3 commits into
frank-w:7.1-mainfrom
meehien:mxl862xx-fw-1.0.85
Aug 9, 2026
Merged

Mxl862xx fw 1.0.85#212
frank-w merged 3 commits into
frank-w:7.1-mainfrom
meehien:mxl862xx-fw-1.0.85

Conversation

@meehien

Copy link
Copy Markdown

On 1.0.85 as shipped by BananaPi (mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca)
the driver currently fails probe outright and the board comes up with no user ports.

The firmware side was characterised by auditing the 1.0.85 image's GSW API
dispatch table (234 entries, 0x11cab8-0x11d5b0) against every command the
driver sends, and by disassembling the handlers where the semantics were not
obvious from the payload size alone. Every command matches its declared
payload except the XPCS PCS group, which 1.0.84 reshaped.

The series

  1. derive firmware capabilities from the version
    No functional change. Replaces three open-coded MXL862XX_FW_VER_MIN()
    call sites — all comparing against 1.0.80 but gating three unrelated
    behaviours — with a capability mask derived once in
    mxl862xx_init_fw_caps(). Every version literal in the driver now lives in
    that one function. The two patches below build on it.

  2. use the logical-index PCE rule API where available
    1.0.85 pre-allocates a smaller per-CTP flow-table block than 1.0.70 did, so
    the higher protocol-trap offsets fall outside it and are refused with
    -1022. That failure propagates out of mxl862xx_refresh_cpu_targets(),
    aborts dsa_switch_setup(), and costs the board every user port. 1.0.83
    added TFLOW_PCERULELOGICWRITE (0x020a), same 466-byte struct, but the
    index is logical within the region and the firmware grows the block on
    demand. Gated on the new capability; the legacy call is kept below 1.0.83.

  3. use the v2 XPCS API on firmware >= 1.0.84
    PCS_CONFIG grew 6 → 10 bytes and PCS_GET_STATE 8 → 12, with packed
    little-endian mode words replacing the byte fields; PCS_ENABLE (0x1a03)
    and AN_DISABLE (0x1a06) were removed; 0x1a07 was repurposed as
    PCS_LINK_UP. Adds v2 structures with compile-time size assertions and a
    second phylink_pcs_ops generation gated on MXL862XX_CAP_XPCS_V2.
    0x1a0a-0x1a0d (serdes statistics and self-test) survived the reshape
    and are untouched. The CPU port stays on the legacy path — see the commit
    message for why PCS_CONFIG must not run there.

Firmware below 1.0.83 keeps the existing paths bit-for-bit.

Not included here

Several other mxl862xx fixes in my tree are deliberately left out of this PR:
the tag_8021q bridge-port fixes, the PCS link-down-on-read-failure fix, the
TX-drop statistics fix, and the per-port conduit TX queue change. They are
independent of the firmware version and overlap Daniel Golle's work in
dangowrt/linux. Happy to send them separately.

The driver adapts to several switch firmware behaviours, and each call
site tests the firmware version directly with MXL862XX_FW_VER_MIN().
There are three such sites and all three compare against 1.0.80, but
they gate three unrelated things: whether the XPCS command family can
drive the SerDes, whether the equalisation and PRBS commands behind the
SerDes statistics exist, and whether the firmware installs its own
global PCE rules that the driver has to disable.
Tying independent behaviours to one open-coded version literal does not
survive contact with new firmware. The features move independently:
1.0.83 adds the logical-index PCE rule API, and 1.0.85 drops
XPCS_PCS_ENABLE and reshapes the XPCS payloads while leaving every
other command's ABI untouched. Each such change currently means either
another literal spread across unrelated call sites, or a workaround
bolted onto one of them.
Introduce a capability mask instead. Derive it once from the cached
version in mxl862xx_wait_ready() and give call sites mxl862xx_fw_has(),
so a firmware that gains or moves a feature only needs the derivation
in mxl862xx_init_fw_caps() updated. Name each capability for the
firmware behaviour it describes rather than for the version that
introduced it, which also removes the negated test at the global-rule
site.
No functional change: the derivation reproduces all three original
version comparisons exactly, for every firmware version.
Signed-off-by: Mihai Ordean <research@mihaiordean.com>
The per-port protocol trap rules (link-local, IGMP, MLDv1/v2) are
written with TFLOW_PCERULEWRITE, where the rule index is a direct
offset into a flow-table block the firmware pre-allocated for that CTP
at init. A write past the end of that block is refused.
Firmware 1.0.85 pre-allocates a smaller block than 1.0.70 did, so the
higher trap offsets now fall outside it:
mxl862xx mdio-bus:10: switch ready after 2150ms, firmware 1.0.85 (build 85)
mxl862xx mdio-bus:10: CMD 0202 returned error -1022
mxl862xx mdio-bus:10: Unable to use tag protocol "mxl862xx-8021q": -EIO
mxl862xx mdio-bus:10: probe with driver mxl862xx failed with error -5
The refusals follow the block size rather than the port type -- port 0
accepts offsets 1-4 while port 1 accepts only 1-3 -- which is what a
shrunken shared block looks like, not a per-port-type restriction.
The failure propagates out of mxl862xx_refresh_cpu_targets(), aborting
dsa_switch_setup() and leaving the board with no user ports at all; on
a BPI-R4 Pro that is the whole LAN side including the 10G SFP+ port.
Firmware 1.0.83 added TFLOW_PCERULELOGICWRITE, which takes the same
466-byte struct mxl862xx_pce_rule but treats the index as logical
within the region selected by region/logicalportid, and grows the
underlying block on demand. That removes the dependency on a
pre-allocated block size the driver never had a way to query.
Add MXL862XX_CAP_PCE_LOGIC_IDX, derived at 1.0.83, and route the four
trap rule writes through a helper that selects the command from it,
keeping the legacy call on firmware below that.
The helper logs a rejection instead of propagating it. These rules
only add link-local trapping and multicast snooping, and the switch
forwards without them, so a firmware that refuses them should not cost
the board every user port -- that state is recoverable only over
serial. Every rejection is logged rather than only the first, because
the affected set is not uniform across ports and offsets.
Reproduced on BPI-R4 Pro 8X, MxL86252C, firmware 1.0.85 (build 85),
internal GPHYs 0.105. The same board on firmware 1.0.70 (build 70)
installs all rules on all ports without error.
Signed-off-by: Mihai Ordean <research@mihaiordean.com>
Firmware 1.0.84 reshaped the XPCS PCS command family. Auditing the
1.0.85 dispatch table (234 entries) against the driver shows every
command the driver sends matches the firmware's declared payload
except the XPCS PCS group: PCS_CONFIG grew from 6 to 10 bytes and
PCS_GET_STATE from 8 to 12 with packed little-endian mode words
replacing the byte fields, PCS_ENABLE (0x1a03) and AN_DISABLE (0x1a06)
were removed outright, and 0x1a07 was repurposed. Disassembling the
1.0.85 0x1a07 handler settles its semantics: it takes a packed mode
word (port_id in bits 1:0, interface mode in 7:2, duplex in bit 8, USX
lane mode and sub-port above) plus a speed in Mbit/s, and acts for
SGMII, USXGMII and QSGMII while short-circuiting when inband AN is
enabled. That is a per-link-up PCS_LINK_UP notification, not a
FORCE_SPEED override: the previous 6-byte layout (u8 port_id, u8
duplex, __le16 speed) would smear the duplex byte across the lane-mode
and sub-port fields.
Add the v2 structures with layouts matching the firmware's declared
sizes (compile-time asserted), a MXL862XX_CAP_XPCS_V2 capability
derived at >= 1.0.84, and a v2 phylink_pcs_ops generation gated on it:
config and get_state use the packed words, an_restart follows the same
mode-word shape, link_up sends PCS_LINK_UP, and there is no
pre_config, because the v2 firmware performs the (idempotent) bringup
inside PCS_CONFIG and no longer implements PCS_ENABLE. PCS_DISABLE is
unchanged, so the existing pcs_disable is reused. This tree drives
each XPCS instance as a single lane with sub-port 0. The serdes
statistics and self-test commands (0x1a0a-0x1a0d) are a separate range
that survived the reshape and are untouched.
Keep the CPU port on the legacy path. The firmware guards PCS_LINK_UP,
AN_RESTART and SIGNAL_DETECT behind a per-instance check and refuses
them, with the Zephyr -EIO (-5), for an instance that has been
configured into a fixed-rate mode, which is what these negotiation
commands not applying looks like from the host. Tracing the instance
through bring-up shows it accepted at probe, accepted after the legacy
configuration and still accepted at link up, with the signal detect
status bits and the device status bank unchanged throughout, so it is
PCS_CONFIG that moves it. PCS_CONFIG is not covered by that guard and
reports success, while replacing the configuration the legacy path
installs: the port then reports link at 10G and forwards nothing,
which takes the switch off the network it is managed over. Nothing is
lost by the exclusion, because a fixed link is resolved by phylink
from the fixed-link configuration and its pcs_get_state() is never
called.
Report the configured flow control on the interface modes that carry
no AN code word, as the legacy path does for every mode, so that a
fixed-rate link does not resolve pause off.
The Zephyr -ENOTSUP (-134) that XPCS_PCS_ENABLE draws on the BananaPi
1.0.85 build for the BPI-R4 Pro is the v2 firmware refusing a removed
v1 command, not the API being absent, so the capability stays granted
and only the ops generation changes. Firmwares 1.0.80 through 1.0.83
keep the existing v1 ops; earlier firmware keeps the legacy register
path. All version comparisons remain confined to
mxl862xx_init_fw_caps().
The 1.0.84 threshold is taken from the reshape's introduction point;
only >= 1.0.85 is directly evidenced on hardware, on a board whose
second XPCS instance drives a combo port routed either to an AS21xxx
PHY or to an SFP cage.
Signed-off-by: Mihai Ordean <research@mihaiordean.com>
@frank-w
frank-w merged commit 73c7cc8 into frank-w:7.1-mainAug 9, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@meehien@frank-w