[BPI-R4 PRO] Maxlinear switch firmware update

I dumped 5 times and all the dumps have same sha. Better than nothing.

Anyone as brave enough as @abs1ck to update their firmware?

@hyf, have you tried the new firmware and do you work for the company?


I asked Claude a question or set of questions and it said:

The debug shell is huge. Baked into this image is a full Zephyr shell with gphy_cfg, xpcs_cli, sfp_cli, msec_cli, mgmt_intf, flash_mxl, chiptest, plus raw primitives: devmem (physical memory r/w), raw MDIO/MMD/SERDES/XPCS register read-write, cable diagnostics (ABIST/CDIAG), loopback and BERT test modes. If that console is reachable (UART header, or the UART_0 backend it references), it’s a very deep hook into the chip.


We really need the old firmware just in case something happens with the new update. That said, apparently there are dual firmware slots so this shouldn’t be an issue - one has to figure out how to switch to the old one in the event that the new one does not work or has issues.

1 Like

MxL 1.0.85: three incompatibilities with the mainline DSA driver

I flashed the new mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca on a BPI-R4 Pro 8X and want to warn people running the mainline/DSA driver rather than BPI’s downstream one. @abs1ck’s report above is on the downstream driver (mxl862xx_dsa-0:00).

Setup: Arch Linux, @frank-w 7.1-main (tip f301d684b889), MxL86252C. The flash itself worked perfectly via the in-kernel devlink dev flash: firmware 1.0.85 (build 85), internal GPHYs 0.77 → 0.105 (0x0069).

Then three separate things broke.

1. XPCS API returns ENOTSUP → switch unreachable

mxl862xx_setup_pcs() selects the firmware XPCS ops at >= 1.0.80. On 1.0.85 those commands do not exist:

mxl862xx mdio-bus:10: configuring for fixed/10gbase-r link mode
mxl862xx mdio-bus:10: CMD 1a03 returned error -134
mxl862xx mdio-bus:10: CMD 1a01 returned error -22
mxl862xx mdio-bus:10: pcs_config failed: -EIO

1a03 is XPCS_PCS_ENABLE; -134 is ENOTSUP in the Zephyr errno space. 1a01/1a02 (PCS_CONFIG/GET_STATE) then fail with -EINVAL, and GET_STATE is polled once per second forever. No SerDes port links, including port 9 — the 10GBASE-R CPU port — so the switch is unreachable from the SoC even though the internal GPHYs link normally.

@dangowrt’s tree already handles this: the gate is at >= 1.0.84, and the XPCS API was renumbered (PCS_ENABLE is gone; +0x7 is now PCS_LINK_UP). frank’s snapshot predates that.

2. PCE rule writes rejected with -1022

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

0202 is TFLOW_PCERULEWRITE. Probe aborts, so zero user ports are registered. Port 0 accepts CTP indices 1–4; port 1 accepts 1–3 and is refused 4 — looks like a reduced or shared per-CTP block rather than a per-port-type limit. Region-0 PCE writes still succeed, so struct mxl862xx_pce_rule is unchanged.

Again already fixed upstream of frank: @dangowrt added PCERULELOGICWRITE gated at >= 1.0.83, where the firmware grows the per-CTP block on demand instead of indexing a fixed one.

3. tag_8021q stops forwarding

With dsa-tag-protocol = "mxl862xx-8021q" on 1.0.85, probe completes, every port links, bridge ports reach forwarding — and nothing passes. Conduit capture shows the tags are correct in both directions (per-port VIDs 3074/3075/3085, stripped properly). Disabling bridge VLAN filtering changes nothing.

Switching the same running kernel to the native tag restores forwarding on the SerDes port immediately:

echo mxl862xx > /sys/class/net/<conduit>/dsa/tagging

Still unsolved: GPHY ingress is dead!

The four internal 2.5G copper ports receive nothing, in either tag mode. Switch-side RMON (ethtool -S) on a port with a 1G client and carrier up for minutes:

tx_packets: 8439      rx_packets: 0        rx_bytes: 0
TxAcmDroppedPkts: 0   RxFilteredPkts: 0    RxExtendedVlanDiscardPkts: 0
MtuExceedDiscardPkts: 0                    RxBadBytes: 0

Every discard counter is zero — frames never reach the switch MAC at all. The SerDes port on the same switch shows normal RX plus non-zero RxFilteredPkts/RxBadBytes.

@dangowrt’s mxl-gpy.c carries a link_change_notify hook that force-sets VSPEC1_SGMII_CTRL_ANEN on every link change, with the comment “setting SGMII AN to enabled then back to disabled clears this for some reason” — same symptom, no root cause. I reproduced the register state (VSPEC1_SGMII_CTRL = 0x0008, ANEN clear, at a 1G link) and tried setting ANEN, ANEN+ANRS, and the enable→disable toggle by hand. The writes stick (read back correctly, firmware does not fight them) but RX stays at 0. So on this firmware it is not simply the ANEN bit.

Summary

@frank-w — would a resync of drivers/net/dsa/mxl862xx/ (and the mxl-gpy delta) from @dangowrt’s tree be on the cards? Happy to test and send a PR if useful.

@dangowrt — the GPHY ingress failure above may be a cleaner reproduction of whatever your link_change_notify hack is papering over, if that’s of any use. Full logs, conduit captures and RMON dumps available on request.

@pameruoso — you mentioned dumping your 1.0.70 off the QSPI with flashrom and getting a matching SHA five times. Would you be willing to share it? No public 1.0.70 image exists and BPI has declined to provide one, so it is currently the only known rollback for anyone who hits this. (Also interested in how you’d restore it — the published upgrade image has an MCUboot header and two CRC’d slots, which a raw chip dump won’t match.)

1 Like

My dumps are 8MB size (the size of the qspi).

If anything goes wrong and if bpi or maxlinear does not provide anything I think last resort for me would be to just use the same sop-8 clip with flashrom -w to write entirely the spi again.

I don’t know if my backup is shareable…I guess I am not allowed for NDA paperworks. Should we just wait for Daniel to jump in and clarify if the .85 build should just work?

these are great news … let’s see if it works with 7.2 when is out

Would be great if you can strip changes between 7.2-ec or 7.1-main and daniels wip tree.

Want to try upgrading firmware with wip tree next days. Does it work so far for you?

It’s fine. And also quick update. I think I managed to fix most of the things so, TLDR, I’m in an equivalent (or better) state than 1.0.70 was. These tasks are so much easier with AI now, but harder to verify, I guess. A cost worth paying sometimes I guess. Anyway see below:

XPCS works: the -134/-EINVAL cascade was exactly what it looked like — frank’s tree gates the API at >= 1.0.80 and 1.0.85 has renumbered/reshaped it, same as @dangowrt found. I disassembled the 1.0.85 dispatch table to pin down the new PCS_CONFIG/GET_STATE payload layouts and what +0x7 (now PCS_LINK_UP) actually does. One catch worth flagging for anyone else hitting this: the CPU port’s XPCS instance on my board refuses the firmware’s own negotiation commands once it’s been put into a fixed-rate mode, so driving it through the API — rather than the legacy register path — silently breaks forwarding while the port still reports link. Traced that down to the instance itself, not the payload shape, so the fix keeps the CPU port on the legacy path and only moves the SFP/PHY combo port onto the new API.

tag_8021q works: forwarding was dying on a VBP (virtual bridge port) map ordering bug, unrelated to the XPCS issue. Fixed and confirmed working with per-port VLANs.

GPHY work: mxl862xx_set_cpu_vbp() updates each virtual bridge port with a mask covering only BRIDGE_ID and EGRESS_SUB_METER, leaving bridge_port_map zeroed in the request. The map had been written once, by mxl862xx_setup_virtual_bridge_port(). Firmware 1.0.85 does not preserve a field the caller did not select, and mxl862xx_complete_tag_8021q_setup() calls set_cpu_vbp() for every port immediately after allocation — so the map was cleared before the first frame was ever forwarded.

Can I help with firmware testing? But I have version 4e. How can I take the current firmware dump and how can I find out what version it is? Now I use:

But I need fairly detailed instructions.

root@bpi-r4:~# devlink dev
platform/15020000.switch
mdio_bus/mdio-bus:10
root@bpi-r4:~# devlink dev info mdio_bus/mdio-bus:10
mdio_bus/mdio-bus:10:
  driver mxl862xx
  versions:
      fixed:
        asic.id 8628
        asic.rev 0
      running:
        fw 1.0.70
      stored:
        fw 1.0.70

currently applying daniels latest patches to my 7.2-rc tree as his tree has strange erros with my debian rootfs and my initrd has no devlink command

root@bpi-r4:~# ls
dmesg_7.2-rc1-r4pro8x.log  mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca.bin  regs  rootfs_arm64.cpio.zst
root@bpi-r4:~# devlink dev flash mdio_bus/mdio-bus:10 file mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca.bin                                              
[  202.154602] mxl862xx mdio-bus:10: Direct firmware load for mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca.bin failed with error -2
[  202.166882] mxl862xx mdio-bus:10: Falling back to sysfs fallback for: mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca.bin
Error: failed to locate the requested firmware file.
root@bpi-r4:~# cat /sys/class/thermal/thermal_zone0/temp
40742
root@bpi-r4:~# cp mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca.bin /lib/firmware/                                                                        
root@bpi-r4:~# devlink dev flash mdio_bus/mdio-bus:10 file mxl862xxc_1030_1085_1085_0069_signed_xfi_upgrade_fca.bin
[  346.177994] mxl862xx mdio-bus:10: flash: running firmware 1.0.70
[  346.185852] lanbr0: port 3(lan1) entered disabled state
[  346.192836] lanbr0: port 1(lan2) entered disabled state
[  346.199830] lanbr0: port 2(lan3) entered disabled state
[  346.205476] mtk_soc_eth 15100000.ethernet eth2: Link is Down
Waiting for bootloader
Erasing flash           
Flashing 100% ( 0m 22s )[  398.682014] mxl862xx mdio-bus:10: switch ready after 2080ms, firmware 1.0.85 (build 85)

after that i got many traces and had to power off the board

after a boot i get this:

root@bpi-r4:~# dmesg | grep -i mxl
[    5.431737] mxl862xx mdio-bus:10: switch ready after 2140ms, firmware 1.0.85 (build 85)
[    5.464303] mxl862xx mdio-bus:10: CMD 1801 returned error -19
[    5.481280] MaxLinear Ethernet MxL86252 mdio-bus:10-mii:01: Firmware Version: 0.105 (0x0069 test version)
[    5.519008] MaxLinear Ethernet MxL86252 mdio-bus:10-mii:02: Firmware Version: 0.105 (0x0069 test version)
[    5.546630] MaxLinear Ethernet MxL86252 mdio-bus:10-mii:03: Firmware Version: 0.105 (0x0069 test version)
[    5.911723] mxl862xx mdio-bus:10: configuring for fixed/10gbase-r link mode
[    5.918995] mxl862xx mdio-bus:10: Link is Up - 10Gbps/Full - flow control off
[    5.945748] mxl862xx mdio-bus:10 lan1 (uninitialized): failed to connect to PHY: -ENODEV
[    5.953839] mxl862xx mdio-bus:10 lan1 (uninitialized): error -19 setting up PHY for tree 0, switch 0, port 1

daniel told me that phys are now also 1-based…these are still 0-based in my dts

yes. i have some patches for that. it’s exactly what i experienced.

yes. it’s exactly what i got after the update. I have some patches for it, but they are very rough. i’ll see if i can sort them out and do a PR tomorrow, against the 7.1-main, if you want them.

mhm, error does not happen with reg+1 of the phys, but now second port is lan1 and gives a linkup…first port is dead

his tree has also 0-based phy-regs

so i reverted this change for now

Did I understand correctly that testing is currently taking place on Debian? I need wait fix for openwrt?

I use debian for development as i find it much more easier as i can simply replace kernel without reflashing or rebuilding userspace and no struggle with quilt and patchfiles,others may test in openwrt.

1 Like

Ok. I will wait update openwrt repo and i can test it. Now i not upgrade the firmware and i want save the old firmware. And i use bpi r4 pro 4e version the board. Big thx for the work! UpD: Now i see it:

It help for next support bpi r4 pro i hope.