.../bindings/net/dsa/maxlinear,mxl862xx.yaml | 154 ++++ MAINTAINERS | 8 + drivers/net/dsa/Kconfig | 2 + drivers/net/dsa/Makefile | 1 + drivers/net/dsa/mxl862xx/Kconfig | 12 + drivers/net/dsa/mxl862xx/Makefile | 3 + drivers/net/dsa/mxl862xx/mxl862xx-api.h | 675 ++++++++++++++++++ drivers/net/dsa/mxl862xx/mxl862xx-cmd.h | 49 ++ drivers/net/dsa/mxl862xx/mxl862xx-host.c | 245 +++++++ drivers/net/dsa/mxl862xx/mxl862xx-host.h | 12 + drivers/net/dsa/mxl862xx/mxl862xx.c | 475 ++++++++++++ drivers/net/dsa/mxl862xx/mxl862xx.h | 19 + include/linux/mdio.h | 13 + include/net/dsa.h | 2 + net/dsa/Kconfig | 7 + net/dsa/Makefile | 1 + net/dsa/tag_mxl862xx.c | 112 +++ 17 files changed, 1790 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/dsa/maxlinear,mxl862xx.yaml create mode 100644 drivers/net/dsa/mxl862xx/Kconfig create mode 100644 drivers/net/dsa/mxl862xx/Makefile create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-api.h create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-cmd.h create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-host.c create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-host.h create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx.c create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx.h create mode 100644 net/dsa/tag_mxl862xx.c
This series adds very basic DSA support for the MaxLinear MxL86252
(5 PHY ports) and MxL86282 (8 PHY ports) switches.
MxL862xx integrates a firmware running on an embedded processor (running
Zephyr RTOS). Host interaction uses a simple netlink-like API transported
over MDIO/MMD.
This series includes only what's needed to pass traffic between user
ports and the CPU port: relayed MDIO to internal PHYs, basic port
enable/disable, and CPU-port special tagging.
Follow up series will bring bridge, VLAN, ... offloading, and support
for using a 802.1Q-based special tag instead of the proprietary 8-byte
tag.
---
basic DSA selftests were run, results:
* no_forwarding.sh: all tests PASS
* bridge_vlan_unaware.sh: all tests PASS
* bridge_vlan_mcast.sh: all tests PASS
* bridge_vlan_aware.sh: all tests PASS
* local_termination.sh: all tests PASS or XFAIL, except for
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address [FAIL]
reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address, allmulti [FAIL]
reception succeeded, but should have failed
As obviously this is mostly testing the Linux software bridge at this point
so I didn't bother to run any of the FDB or MDB related tests.
Changes since v8:
1/4 dt-bindings: net: dsa: add MaxLinear MxL862xx
* no changes
2/4 net: dsa: add tag format for MxL862xx switches
* no changes
3/4 net: mdio: add unlocked mdiodev C45 bus accessors
* no changes
4/4 net: dsa: add basic initial driver for MxL862xx switches
* remove practically unused struct hw_info
* lots of kerneldoc improvements in mxl862xx-api.h
* drop .mac_select_pcs() stub
* better handling for firmware error return value
* apply reverse xmas tree in mxl862xx_api_wrap
* guard headers with #ifdef macro
* include net/dsa.h and linux/mdio.h in mxl862xx.h
* call mxl862xx_port_fast_age() only once in .port_setup
* don't create isolation bridges for unused ports
* replace errornous cast with correct range of values denoting firmware errors
Changes since v7
1/4 dt-bindings: net: dsa: add MaxLinear MxL862xx
* no changes
2/4 net: dsa: add tag format for MxL862xx switches
* no changes
3/4 net: mdio: add unlocked mdiodev C45 bus accessors
* no changes
4/4 net: dsa: add basic initial driver for MxL862xx switches
* use little-endian in bridge_port_config API
* remove duplciate assignment of br_port_cfg.bridge_port_id when setting
up CPU port
Changes since v6
1/4 dt-bindings: net: dsa: add MaxLinear MxL862xx
* no changes
2/4 net: dsa: add tag format for MxL862xx switches
* no changes
3/4 net: mdio: add unlocked mdiodev C45 bus accessors
* no changes
4/4 net: dsa: add basic initial driver for MxL862xx switches
* fix kerneldoc style
Changes since RFC v5
1/4 dt-bindings: net: dsa: add MaxLinear MxL862xx
* no changes
2/4 net: dsa: add tag format for MxL862xx switches
* remove unnecessary check for skb != NULL
* merge consecutively printed warnings into single dev_warn_ratelimited
3/4 net: mdio: add unlocked mdiodev C45 bus accessors
* no changes
4/4 net: dsa: add basic initial driver for MxL862xx switches
* include bridge and bridgeport API needed to isolate ports
* remove warning in .setup as ports are now isolated
* make ready-after-reset check more robust by adding delay
* sort structs in order of struct definitions
* best effort to sort functions without introducing additional prototypes
* always use enums with kerneldoc comments in mxl862xx-api.h
* remove bogus .phy_read and .phy_write DSA ops as the driver anyway registers
a user MDIO bus with Clause-22 and Clause-45 operations
* various small style fixes
Changes since RFC v4
1/4 dt-bindings: net: dsa: add MaxLinear MxL862xx
* no changes
2/4 net: dsa: add tag format for MxL862xx switches
* drop unused precompiler macros
3/4 net: mdio: add unlocked mdiodev C45 bus accessors
* fix indentation
4/4 net: dsa: add basic initial driver for MxL862xx switches
* output warning in .setup regarding unknown pre-configuration
* add comment explaining why CFGGET is used in reset function
Changes since RFC v3
1/4 dt-bindings: net: dsa: add MaxLinear MxL862xx
* remove labels from example
* remove 'bindings for' from commit title
2/4 net: dsa: add tag format for MxL862xx switches
* describe fields and variables with comments
* sub-interface is only 5 bits
* harmonize Kconfig symbol name
* maintain alphabetic order in Kconfig
* fix typo s/beginnig/beginning/
* fix typo s/swtiches/switches/
* arrange local variables in reverse xmas tree order
3/4 net: mdio: add unlocked mdiodev C45 bus accessors
* unchanged
4/4 net: dsa: add basic initial driver for MxL862xx switches
* poll switch readiness after reset
* implement driver shutdown
* added port_fast_aging API call and driver op
* unified port setup in new .port_setup op
* improve comment explaining special handlign for unaligned API read
* various typos and formatting improvements
Changes since RFC v2
1/4, 2/4, 3/4: unchanged
4/4 net: dsa: add basic initial driver for MxL862xx switches
* fix return value being uninitialized on error in mxl862xx_api_wrap()
* add missing description in kerneldoc comment of
struct mxl862xx_ss_sp_tag
Changes since initial RFC
1/4 dt-bindings: net: dsa: add bindings for MaxLinear MxL862xx
* better description in dt-bindings doc
2/4 net: dsa: add tag formats for MxL862xx switches
* make sure all tag fields are initialized
3/4 net: mdio: add unlocked mdiodev C45 bus accessors
* new patch
4/4 net: dsa: add basic initial driver for MxL862xx switches
* make use of struct mdio_device
* add phylink_mac_ops stubs
* drop leftover nonsense from mxl862xx_phylink_get_caps()
* fix endian conversions
* use __le32 instead of enum types in over-the-wire structs
* use existing MDIO_* macros whenever possible
* simplify API constants to be more readable
* use readx_poll_timeout instead of open-coding poll timeout loop
* add mxl862xx_reg_read() and mxl862xx_reg_write() helpers
* demystify error codes returned by the firmware
* add #defines for mxl862xx_ss_sp_tag member values
* move reset to dedicated function, clarify magic number being the
reset command ID
Daniel Golle (4):
dt-bindings: net: dsa: add MaxLinear MxL862xx
net: dsa: add tag format for MxL862xx switches
net: mdio: add unlocked mdiodev C45 bus accessors
net: dsa: add basic initial driver for MxL862xx switches
.../bindings/net/dsa/maxlinear,mxl862xx.yaml | 154 ++++
MAINTAINERS | 8 +
drivers/net/dsa/Kconfig | 2 +
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/mxl862xx/Kconfig | 12 +
drivers/net/dsa/mxl862xx/Makefile | 3 +
drivers/net/dsa/mxl862xx/mxl862xx-api.h | 675 ++++++++++++++++++
drivers/net/dsa/mxl862xx/mxl862xx-cmd.h | 49 ++
drivers/net/dsa/mxl862xx/mxl862xx-host.c | 245 +++++++
drivers/net/dsa/mxl862xx/mxl862xx-host.h | 12 +
drivers/net/dsa/mxl862xx/mxl862xx.c | 475 ++++++++++++
drivers/net/dsa/mxl862xx/mxl862xx.h | 19 +
include/linux/mdio.h | 13 +
include/net/dsa.h | 2 +
net/dsa/Kconfig | 7 +
net/dsa/Makefile | 1 +
net/dsa/tag_mxl862xx.c | 112 +++
17 files changed, 1790 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/dsa/maxlinear,mxl862xx.yaml
create mode 100644 drivers/net/dsa/mxl862xx/Kconfig
create mode 100644 drivers/net/dsa/mxl862xx/Makefile
create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-api.h
create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-cmd.h
create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-host.c
create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx-host.h
create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx.c
create mode 100644 drivers/net/dsa/mxl862xx/mxl862xx.h
create mode 100644 net/dsa/tag_mxl862xx.c
--
2.52.0
On Tue, Jan 27, 2026 at 09:37:40PM +0000, Daniel Golle wrote:
> This series adds very basic DSA support for the MaxLinear MxL86252
> (5 PHY ports) and MxL86282 (8 PHY ports) switches.
>
> MxL862xx integrates a firmware running on an embedded processor (running
> Zephyr RTOS). Host interaction uses a simple netlink-like API transported
> over MDIO/MMD.
>
> This series includes only what's needed to pass traffic between user
> ports and the CPU port: relayed MDIO to internal PHYs, basic port
> enable/disable, and CPU-port special tagging.
> Follow up series will bring bridge, VLAN, ... offloading,
I'm surprised the Kconfig help text says:
These switches have two 10GE SerDes interfaces, one typically
used as CPU port.
yet only PHY_INTERFACE_MODE_INTERNAL is set in phylink supported_interfaces.
You're also not making any mention of future SerDes support. What's up
with that, how do the SerDes ports currently work and how are they
described? (as internal?!)
> and support for using a 802.1Q-based special tag instead of the
> proprietary 8-byte tag.
Why is that?
Another (related) question. You have this comment in tag_mxl862xx.c:
/* switch firmware expects ports to be counted starting from 1 */
from which I don't completely understand how is the firmware involved
(does it process the tags?). Would the expectation also apply to the
802.1Q based tagger?
What's the real story behind port index 0? Does it really not exist, or
is it some attempt to hide an internal port that's not supposed to be used?
If the latter, I guess something like the snippet below (seen in
arch/arm64/boot/dts/freescale/fsl-lx2160a-bluebox3.dts) would simplify
the driver by a bit:
ethernet-switch@0 {
...
ethernet-ports {
...
/* Microcontroller port */
port@0 {
reg = <0>;
status = "disabled";
};
On Wed, Jan 28, 2026 at 12:56:43AM +0200, Vladimir Oltean wrote:
> On Tue, Jan 27, 2026 at 09:37:40PM +0000, Daniel Golle wrote:
> > This series adds very basic DSA support for the MaxLinear MxL86252
> > (5 PHY ports) and MxL86282 (8 PHY ports) switches.
> >
> > MxL862xx integrates a firmware running on an embedded processor (running
> > Zephyr RTOS). Host interaction uses a simple netlink-like API transported
> > over MDIO/MMD.
> >
> > This series includes only what's needed to pass traffic between user
> > ports and the CPU port: relayed MDIO to internal PHYs, basic port
> > enable/disable, and CPU-port special tagging.
> > Follow up series will bring bridge, VLAN, ... offloading,
>
> I'm surprised the Kconfig help text says:
>
> These switches have two 10GE SerDes interfaces, one typically
> used as CPU port.
>
> yet only PHY_INTERFACE_MODE_INTERNAL is set in phylink supported_interfaces.
> You're also not making any mention of future SerDes support. What's up
> with that, how do the SerDes ports currently work and how are they
> described? (as internal?!)
Oh, sure, I'm obviously going to add both SerDes interfaces which support
various interface modes as phylink_pcs instances in a follow-up series.
I was planning to do basic bridge offloading and FDB access first, then
SerDes PCS, then LAG, then VLAN, and then last but not least using the
802.1Q-based special tag (LoC of just that feature is almost as much
as all the rest together in the vendor driver).
>
> > and support for using a 802.1Q-based special tag instead of the
> > proprietary 8-byte tag.
>
> Why is that?
Using an 802.1Q-based special tag is advantageous in some situations,
for example PPE offloading engines typically do support 802.1Q and
802.1ad VLANs, but do not support any special tag apart from those
of the same vendor (eg. MediaTek's PPE supports MediaTek's 4-byte
special tag, but includes "plain" 802.1Q or 802.1ad/Q-in-Q as part of
the tuple identifying a flow). Hence by implementing an 802.1Q-based
tag one can benefit from better performance, less CPU load and less
energy consumption when combining these switches with router SoCs
of other vendors if they implementing "picky" offloading fast-paths.
>
> Another (related) question. You have this comment in tag_mxl862xx.c:
>
> /* switch firmware expects ports to be counted starting from 1 */
>
> from which I don't completely understand how is the firmware involved
> (does it process the tags?). Would the expectation also apply to the
> 802.1Q based tagger?
No. The 802.1Q-based tagger is basically implemented entirely by
setting up additional bridges, virtual bridge ports and special VLAN
forwarding rules. It takes more than just "switching" the tag protocol...
But hence it can be implemented in pretty much any way we want.
>
> What's the real story behind port index 0? Does it really not exist, or
> is it some attempt to hide an internal port that's not supposed to be used?
It's just an oddity of the management firmware which runs on the switch.
Port ID 0 has special meaning, physical ports are counted started from 1.
For example, when adding FDB entries, port_id == 0 means not specifying a
port (eg. for filter rules). However, it *is* weird that BIT(0) of any
portmap isn't ever used in the driver, and it looks like it could be like
you describe below. I will ask.
>
> If the latter, I guess something like the snippet below (seen in
> arch/arm64/boot/dts/freescale/fsl-lx2160a-bluebox3.dts) would simplify
> the driver by a bit:
>
> ethernet-switch@0 {
> ...
> ethernet-ports {
> ...
> /* Microcontroller port */
> port@0 {
> reg = <0>;
> status = "disabled";
> };
This construct could never the less help to make things more easy and
less annoying to deal with. I might just start counting from reg = <1>
in DT and have a dummy/reserved port 0.
Always having add/substract 1 is often confusing because then you have
to remember if a port number or mask stored in some structure or
variable denotes the DSA perspective or the switch firmware perspective.
Unifying the two would definitely be beneficial. I can give that a short
tomorrow.
© 2016 - 2026 Red Hat, Inc.