[PATCH net-next 00/13] net: phy_port: SFP modules representation and phy_port listing

Maxime Chevallier posted 13 patches 1 week, 3 days ago
There is a newer version of this series
Documentation/netlink/specs/ethtool.yaml      |  50 +++
Documentation/networking/ethtool-netlink.rst  |  35 ++
MAINTAINERS                                   |   1 +
drivers/net/phy/phy-caps.h                    |   2 +
drivers/net/phy/phy_caps.c                    |  26 ++
drivers/net/phy/phy_device.c                  | 104 ++++-
drivers/net/phy/phy_link_topology.c           |  80 +++-
drivers/net/phy/phy_port.c                    |   9 +-
drivers/net/phy/phylink.c                     | 121 ++++++
drivers/net/phy/sfp-bus.c                     |  20 +
drivers/net/phy/sfp.c                         |  12 +
drivers/net/phy/sfp.h                         |   2 +
include/linux/phy.h                           |  88 +----
include/linux/phy_link_topology.h             |  34 ++
include/linux/phy_port.h                      |   5 +
include/linux/sfp.h                           |   5 +
.../uapi/linux/ethtool_netlink_generated.h    |  19 +
net/ethtool/Makefile                          |   2 +-
net/ethtool/common.c                          |  44 +++
net/ethtool/netlink.c                         |  11 +
net/ethtool/netlink.h                         |   5 +
net/ethtool/port.c                            | 373 ++++++++++++++++++
22 files changed, 943 insertions(+), 105 deletions(-)
create mode 100644 net/ethtool/port.c
[PATCH net-next 00/13] net: phy_port: SFP modules representation and phy_port listing
Posted by Maxime Chevallier 1 week, 3 days ago
Hello everyone,

This series is another step towards dealing with multi-port interfaces.

It build on the recent addition of phy_port representation to enable
listing the front-facing ports of an interface. For now, we don't control
these ports, we merely list their presence and their capabilities.

As the most common use-case of multi-port interfaces is combo-ports that
provide both RJ45 and SFP connectors on a single MAC, there's a lot of
SFP stuff in this series.

This series is in 2 main parts. The first one aims at representing the
SFP cages and modules using phy_port, as combo-ports with RJ45 + SFP are
by far the most common cases for multi-connector setups.

The second part is the netlink interface to list those ports, now that
most use-cases are covered.

Let's see what we can do with some examples of the new ethtool API :

- Get MII interfaces supported by an empty SFP cage :

# ethtool --show-ports eth3

Port for eth3:
	Port id: 1
	Occupied: no
	Supported MII interfaces : sgmii, 1000base-x, 2500base-x
	Port type: sfp


- Get Combo-ports supported modes, on each port :

# ethtool --show-ports eth0

Port for eth0:
	Port id: 1
	Occupied: no
	Supported link modes:  10baseT/Half 10baseT/Full
	                       100baseT/Half 100baseT/Full
	                       1000baseT/Half 1000baseT/Full
	                       10000baseT/Full
	                       2500baseT/Full
	                       5000baseT/Full
	Port type: mdi

Port for eth0:
	Port id: 2
	Occupied: no
	Supported MII interfaces : 10gbase-r
	Port type: sfp
	

- Get Achievable linkmodes on a SFP module (combo port with a DAC in the
SFP cage)

# ethtool --show-ports eth1

Port for eth1:
	Port id: 1
	Occupied: no
	Supported link modes:  10baseT/Half 10baseT/Full
	                       100baseT/Half 100baseT/Full
	                       1000baseT/Half 1000baseT/Full
	                       10000baseT/Full
	                       2500baseT/Full
	                       5000baseT/Full
	Port type: mdi

Port for eth1:
	Port id: 2
	Occupied: yes
	Supported MII interfaces : 10gbase-r
	Port type: sfp

Port for eth1:
	Port id: 3
	Occupied: no
	Supported link modes:  10000baseCR/Full
	Port type: mdi

Note that here, we have 3 ports :
 - The Copper port
 - The SFP Cage itself, marked as 'occupied'
 - The SFP module

This series builds on top of phy_port and phy_link_topology to allow
tracking the ports of an interface. We maintain a list of supported
linkmodes/interfaces on each port, which allows for fine-grained
reporting of each port's capability.

What this series doesn't do :
 - We don't support selecting which port is active. This is the next step.
 - We only support PHY-driven combo ports. The end-goal of this whole
   journey that started with phy_link_topology is to get support for MII
   muxes, such as the one we have on the Turris Omnia. This will eventually
   be upstreamed as well.

If you want to play around with it, here's [1] the patched ethtool that I've
been using to produce the outputs above.

Thanks !

Maxime

[1] : https://github.com/minimaxwell/ethtool/tree/mc/ethtool_port

Maxime Chevallier (13):
  net: phy: phy_port: Correctly recompute the port's linkmodes
  net: phy: phy_link_topology: Add a helper for opportunistic alloc
  net: phy: phy_link_topology: Track ports in phy_link_topology
  net: phylink: Register a phy_port for MAC-driven SFP busses
  net: phy: Create SFP phy_port before registering usptream
  net: sfp: Add a sfp-bus ops when connecting a module without PHY
  net: phy: Represent PHY-less SFP modules with phy_port
  net: phylink: Represent PHY-less SFP modules with phy_port
  net: phy: phy_port: Store information about a MII port's occupancy
  net: phy: phy_link_topology: Add a helper to retrieve ports
  net: phy: store phy_modes in a static array
  netlink: specs: Add ethernet port listing with ethtool
  net: ethtool: Introduce ethtool command to list ports

 Documentation/netlink/specs/ethtool.yaml      |  50 +++
 Documentation/networking/ethtool-netlink.rst  |  35 ++
 MAINTAINERS                                   |   1 +
 drivers/net/phy/phy-caps.h                    |   2 +
 drivers/net/phy/phy_caps.c                    |  26 ++
 drivers/net/phy/phy_device.c                  | 104 ++++-
 drivers/net/phy/phy_link_topology.c           |  80 +++-
 drivers/net/phy/phy_port.c                    |   9 +-
 drivers/net/phy/phylink.c                     | 121 ++++++
 drivers/net/phy/sfp-bus.c                     |  20 +
 drivers/net/phy/sfp.c                         |  12 +
 drivers/net/phy/sfp.h                         |   2 +
 include/linux/phy.h                           |  88 +----
 include/linux/phy_link_topology.h             |  34 ++
 include/linux/phy_port.h                      |   5 +
 include/linux/sfp.h                           |   5 +
 .../uapi/linux/ethtool_netlink_generated.h    |  19 +
 net/ethtool/Makefile                          |   2 +-
 net/ethtool/common.c                          |  44 +++
 net/ethtool/netlink.c                         |  11 +
 net/ethtool/netlink.h                         |   5 +
 net/ethtool/port.c                            | 373 ++++++++++++++++++
 22 files changed, 943 insertions(+), 105 deletions(-)
 create mode 100644 net/ethtool/port.c

-- 
2.49.0
Re: [PATCH net-next 00/13] net: phy_port: SFP modules representation and phy_port listing
Posted by Jakub Kicinski 1 week, 3 days ago
On Tue, 27 Jan 2026 14:41:48 +0100 Maxime Chevallier wrote:
> This series is another step towards dealing with multi-port interfaces.
> 
> It build on the recent addition of phy_port representation to enable
> listing the front-facing ports of an interface. For now, we don't control
> these ports, we merely list their presence and their capabilities.
> 
> As the most common use-case of multi-port interfaces is combo-ports that
> provide both RJ45 and SFP connectors on a single MAC, there's a lot of
> SFP stuff in this series.
> 
> This series is in 2 main parts. The first one aims at representing the
> SFP cages and modules using phy_port, as combo-ports with RJ45 + SFP are
> by far the most common cases for multi-connector setups.
> 
> The second part is the netlink interface to list those ports, now that
> most use-cases are covered.

Some config-related build unhappines here (kunit hits this):

../include/linux/phy_link_topology.h:110:1: error: return type defaults to ‘int’ [-Wimplicit-int]
  110 | phy_link_topo_get_port(struct net_device *dev, u32 port_id)
      | ^~~~~~~~~~~~~~~~~~~~~~
../include/linux/phy_link_topology.h:110:1: warning: no previous prototype for ‘phy_link_topo_get_port’ [-Wmissing-prototypes]
In file included from ../include/uapi/linux/posix_types.h:5,
                 from ../include/uapi/linux/types.h:14,
                 from ../include/linux/types.h:6,
                 from ../include/linux/kasan-checks.h:5,
                 from ../include/asm-generic/rwonce.h:26,
                 from ./arch/x86/include/generated/asm/rwonce.h:1,
                 from ../include/linux/compiler.h:380,
                 from ../include/linux/build_bug.h:5,
                 from ../include/linux/bits.h:30,
                 from ../include/linux/bitops.h:6,
                 from ../include/linux/bitmap.h:8,
                 from ../include/linux/ethtool.h:16,
                 from ../include/uapi/linux/ethtool_netlink.h:12,
                 from ../include/linux/ethtool_netlink.h:6,
                 from ../net/ethtool/common.c:3:
../include/linux/phy_link_topology.h: In function ‘phy_link_topo_get_port’:
../include/linux/stddef.h:8:14: error: returning ‘void *’ from a function with return type ‘int’ makes integer from pointer without a cast [-Wint-conversion]
    8 | #define NULL ((void *)0)
      |              ^
../include/linux/phy_link_topology.h:112:16: note: in expansion of macro ‘NULL’
  112 |         return NULL;
      |                ^~~~
-- 
pw-bot: cr
Re: [PATCH net-next 00/13] net: phy_port: SFP modules representation and phy_port listing
Posted by Maxime Chevallier 1 week, 3 days ago
Hi again,

On 27/01/2026 22:07, Jakub Kicinski wrote:

> Some config-related build unhappines here (kunit hits this):
> 
> ../include/linux/phy_link_topology.h:110:1: error: return type defaults to ‘int’ [-Wimplicit-int]
>   110 | phy_link_topo_get_port(struct net_device *dev, u32 port_id)
>       | ^~~~~~~~~~~~~~~~~~~~~~
> ../include/linux/phy_link_topology.h:110:1: warning: no previous prototype for ‘phy_link_topo_get_port’ [-Wmissing-prototypes]
> In file included from ../include/uapi/linux/posix_types.h:5,
>                  from ../include/uapi/linux/types.h:14,
>                  from ../include/linux/types.h:6,
>                  from ../include/linux/kasan-checks.h:5,
>                  from ../include/asm-generic/rwonce.h:26,
>                  from ./arch/x86/include/generated/asm/rwonce.h:1,
>                  from ../include/linux/compiler.h:380,
>                  from ../include/linux/build_bug.h:5,
>                  from ../include/linux/bits.h:30,
>                  from ../include/linux/bitops.h:6,
>                  from ../include/linux/bitmap.h:8,
>                  from ../include/linux/ethtool.h:16,
>                  from ../include/uapi/linux/ethtool_netlink.h:12,
>                  from ../include/linux/ethtool_netlink.h:6,
>                  from ../net/ethtool/common.c:3:
> ../include/linux/phy_link_topology.h: In function ‘phy_link_topo_get_port’:
> ../include/linux/stddef.h:8:14: error: returning ‘void *’ from a function with return type ‘int’ makes integer from pointer without a cast [-Wint-conversion]
>     8 | #define NULL ((void *)0)
>       |              ^
> ../include/linux/phy_link_topology.h:112:16: note: in expansion of macro ‘NULL’
>   112 |         return NULL;
>       |                ^~~~

The kernel test bot also found it, and AI found stuff to fix I'll
address that + AI review then :)

Maxime
Re: [PATCH net-next 00/13] net: phy_port: SFP modules representation and phy_port listing
Posted by Maxime Chevallier 1 week, 3 days ago
Hi,

On 27/01/2026 22:07, Jakub Kicinski wrote:
> On Tue, 27 Jan 2026 14:41:48 +0100 Maxime Chevallier wrote:
>> This series is another step towards dealing with multi-port interfaces.
>>
>> It build on the recent addition of phy_port representation to enable
>> listing the front-facing ports of an interface. For now, we don't control
>> these ports, we merely list their presence and their capabilities.
>>
>> As the most common use-case of multi-port interfaces is combo-ports that
>> provide both RJ45 and SFP connectors on a single MAC, there's a lot of
>> SFP stuff in this series.
>>
>> This series is in 2 main parts. The first one aims at representing the
>> SFP cages and modules using phy_port, as combo-ports with RJ45 + SFP are
>> by far the most common cases for multi-connector setups.
>>
>> The second part is the netlink interface to list those ports, now that
>> most use-cases are covered.
> 
> Some config-related build unhappines here (kunit hits this):
> 
> ../include/linux/phy_link_topology.h:110:1: error: return type defaults to ‘int’ [-Wimplicit-int]
>   110 | phy_link_topo_get_port(struct net_device *dev, u32 port_id)
>       | ^~~~~~~~~~~~~~~~~~~~~~
> ../include/linux/phy_link_topology.h:110:1: warning: no previous prototype for ‘phy_link_topo_get_port’ [-Wmissing-prototypes]
> In file included from ../include/uapi/linux/posix_types.h:5,
>                  from ../include/uapi/linux/types.h:14,
>                  from ../include/linux/types.h:6,
>                  from ../include/linux/kasan-checks.h:5,
>                  from ../include/asm-generic/rwonce.h:26,
>                  from ./arch/x86/include/generated/asm/rwonce.h:1,
>                  from ../include/linux/compiler.h:380,
>                  from ../include/linux/build_bug.h:5,
>                  from ../include/linux/bits.h:30,
>                  from ../include/linux/bitops.h:6,
>                  from ../include/linux/bitmap.h:8,
>                  from ../include/linux/ethtool.h:16,
>                  from ../include/uapi/linux/ethtool_netlink.h:12,
>                  from ../include/linux/ethtool_netlink.h:6,
>                  from ../net/ethtool/common.c:3:
> ../include/linux/phy_link_topology.h: In function ‘phy_link_topo_get_port’:
> ../include/linux/stddef.h:8:14: error: returning ‘void *’ from a function with return type ‘int’ makes integer from pointer without a cast [-Wint-conversion]
>     8 | #define NULL ((void *)0)
>       |              ^
> ../include/linux/phy_link_topology.h:112:16: note: in expansion of macro ‘NULL’
>   112 |         return NULL;
>       |                ^~~~

Ah yes indeed, silly mistake from me but wasn't caught by running
./ingest_mdir.py locally, I'll increase my local coverage with a
defconfig that triggers this.

I was so focused making sure the various combinations of phylib et.al.
being built as modules or builtin that I didn't test with PHYLIB=n :/

Thanks for reporting, I'll address that :)

Maxime