Skip to content

Commit

Permalink
Merge branch 'phy-listing-and-topology-tracking'
Browse files Browse the repository at this point in the history
Maxime Chevallier says:

====================
Introduce PHY listing and link_topology tracking

This is V18 of the phy_link_topology series, aiming at improving support
for multiple PHYs being attached to the same MAC.

V18 is a simple rebase of the V17 on top of net-next, gathering the
tested-by and reviewed-by tags from Christophe (thanks !).

This iteration is also one patch shorter than V17 (patch 12/14 in V17 is gone),
as one of the patches used to fix an issue that has now been resolved by
Simon Horman in

743ff02 ethtool: Don't check for NULL info in prepare_data callbacks

As a remainder, here's what the PHY listings would look like :
 - eth0 has a 88x3310 acting as media converter, and an SFP module with
   an embedded 88e1111 PHY
 - eth2 has a 88e1510 PHY

PHY for eth0:
PHY index: 1
Driver name: mv88x3310
PHY device name: f212a600.mdio-mii:00
Downstream SFP bus name: sfp-eth0
Upstream type: MAC

PHY for eth0:
PHY index: 2
Driver name: Marvell 88E1111
PHY device name: i2c:sfp-eth0:16
Upstream type: PHY
Upstream PHY index: 1
Upstream SFP name: sfp-eth0

PHY for eth2:
PHY index: 1
Driver name: Marvell 88E1510
PHY device name: f212a20.mdio-mii:00
Upstream type: MAC

Ethtool patches : https://github.com/minimaxwell/ethtool/tree/mc/topo-v16
(this branch is compatible with this V18 series)

Link to V17: https://lore.kernel.org/netdev/[email protected]/
Link to V16: https://lore.kernel.org/netdev/[email protected]/
Link to V15: https://lore.kernel.org/netdev/[email protected]/
Link to V14: https://lore.kernel.org/netdev/[email protected]/
Link to V13: https://lore.kernel.org/netdev/[email protected]/
Link to v12: https://lore.kernel.org/netdev/[email protected]/
Link to v11: https://lore.kernel.org/netdev/[email protected]/
Link to V10: https://lore.kernel.org/netdev/[email protected]/
Link to V9: https://lore.kernel.org/netdev/[email protected]/
Link to V8: https://lore.kernel.org/netdev/[email protected]/
Link to V7: https://lore.kernel.org/netdev/[email protected]/
Link to V6: https://lore.kernel.org/netdev/[email protected]/
Link to V5: https://lore.kernel.org/netdev/[email protected]/
Link to V4: https://lore.kernel.org/netdev/[email protected]/
Link to V3: https://lore.kernel.org/netdev/[email protected]/
Link to V2: https://lore.kernel.org/netdev/[email protected]/
Link to V1: https://lore.kernel.org/netdev/[email protected]/

More discussions on specific issues that happened in 6.9-rc:

https://lore.kernel.org/netdev/[email protected]/
https://lore.kernel.org/netdev/[email protected]/
https://lore.kernel.org/netdev/[email protected]/
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Aug 23, 2024
2 parents 761d527 + db31e09 commit b34a6e7
Show file tree
Hide file tree
Showing 30 changed files with 1,056 additions and 51 deletions.
58 changes: 58 additions & 0 deletions Documentation/netlink/specs/ethtool.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ definitions:
- ovld-detected
- power-not-available
- short-detected
-
name: phy-upstream-type
enum-name:
type: enum
entries: [ mac, phy ]

attribute-sets:
-
Expand All @@ -54,6 +59,9 @@ attribute-sets:
name: flags
type: u32
enum: header-flags
-
name: phy-index
type: u32

-
name: bitset-bit
Expand Down Expand Up @@ -1089,6 +1097,35 @@ attribute-sets:
-
name: total
type: uint
-
name: phy
attributes:
-
name: header
type: nest
nested-attributes: header
-
name: index
type: u32
-
name: drvname
type: string
-
name: name
type: string
-
name: upstream-type
type: u32
enum: phy-upstream-type
-
name: upstream-index
type: u32
-
name: upstream-sfp-name
type: string
-
name: downstream-sfp-name
type: string

operations:
enum-model: directional
Expand Down Expand Up @@ -1887,3 +1924,24 @@ operations:
- status-msg
- done
- total
-
name: phy-get
doc: Get PHY devices attached to an interface

attribute-set: phy

do: &phy-get-op
request:
attributes:
- header
reply:
attributes:
- header
- index
- drvname
- name
- upstream-type
- upstream-index
- upstream-sfp-name
- downstream-sfp-name
dump: *phy-get-op
51 changes: 51 additions & 0 deletions Documentation/networking/ethtool-netlink.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Structure of this header is
``ETHTOOL_A_HEADER_DEV_INDEX`` u32 device ifindex
``ETHTOOL_A_HEADER_DEV_NAME`` string device name
``ETHTOOL_A_HEADER_FLAGS`` u32 flags common for all requests
``ETHTOOL_A_HEADER_PHY_INDEX`` u32 phy device index
============================== ====== =============================

``ETHTOOL_A_HEADER_DEV_INDEX`` and ``ETHTOOL_A_HEADER_DEV_NAME`` identify the
Expand All @@ -81,6 +82,12 @@ the behaviour is backward compatible, i.e. requests from old clients not aware
of the flag should be interpreted the way the client expects. A client must
not set flags it does not understand.

``ETHTOOL_A_HEADER_PHY_INDEX`` identifies the Ethernet PHY the message relates to.
As there are numerous commands that are related to PHY configuration, and because
there may be more than one PHY on the link, the PHY index can be passed in the
request for the commands that needs it. It is, however, not mandatory, and if it
is not passed for commands that target a PHY, the net_device.phydev pointer
is used.

Bit sets
========
Expand Down Expand Up @@ -2184,6 +2191,49 @@ string.
The ``ETHTOOL_A_MODULE_FW_FLASH_DONE`` and ``ETHTOOL_A_MODULE_FW_FLASH_TOTAL``
attributes encode the completed and total amount of work, respectively.

PHY_GET
=======

Retrieve information about a given Ethernet PHY sitting on the link. The DO
operation returns all available information about dev->phydev. User can also
specify a PHY_INDEX, in which case the DO request returns information about that
specific PHY.

As there can be more than one PHY, the DUMP operation can be used to list the PHYs
present on a given interface, by passing an interface index or name in
the dump request.

For more information, refer to :ref:`phy_link_topology`

Request contents:

==================================== ====== ==========================
``ETHTOOL_A_PHY_HEADER`` nested request header
==================================== ====== ==========================

Kernel response contents:

===================================== ====== ===============================
``ETHTOOL_A_PHY_HEADER`` nested request header
``ETHTOOL_A_PHY_INDEX`` u32 the phy's unique index, that can
be used for phy-specific
requests
``ETHTOOL_A_PHY_DRVNAME`` string the phy driver name
``ETHTOOL_A_PHY_NAME`` string the phy device name
``ETHTOOL_A_PHY_UPSTREAM_TYPE`` u32 the type of device this phy is
connected to
``ETHTOOL_A_PHY_UPSTREAM_INDEX`` u32 the PHY index of the upstream
PHY
``ETHTOOL_A_PHY_UPSTREAM_SFP_NAME`` string if this PHY is connected to
its parent PHY through an SFP
bus, the name of this sfp bus
``ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME`` string if the phy controls an sfp bus,
the name of the sfp bus
===================================== ====== ===============================

When ``ETHTOOL_A_PHY_UPSTREAM_TYPE`` is PHY_UPSTREAM_PHY, the PHY's parent is
another PHY.

Request translation
===================

Expand Down Expand Up @@ -2291,4 +2341,5 @@ are netlink only.
n/a ``ETHTOOL_MSG_MM_GET``
n/a ``ETHTOOL_MSG_MM_SET``
n/a ``ETHTOOL_MSG_MODULE_FW_FLASH_ACT``
n/a ``ETHTOOL_MSG_PHY_GET``
=================================== =====================================
1 change: 1 addition & 0 deletions Documentation/networking/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Contents:
operstates
packet_mmap
phonet
phy-link-topology
pktgen
plip
ppp_generic
Expand Down
121 changes: 121 additions & 0 deletions Documentation/networking/phy-link-topology.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
.. SPDX-License-Identifier: GPL-2.0
.. _phy_link_topology:

=================
PHY link topology
=================

Overview
========

The PHY link topology representation in the networking stack aims at representing
the hardware layout for any given Ethernet link.

An Ethernet interface from userspace's point of view is nothing but a
:c:type:`struct net_device <net_device>`, which exposes configuration options
through the legacy ioctls and the ethtool netlink commands. The base assumption
when designing these configuration APIs were that the link looks something like ::

+-----------------------+ +----------+ +--------------+
| Ethernet Controller / | | Ethernet | | Connector / |
| MAC | ------ | PHY | ---- | Port | ---... to LP
+-----------------------+ +----------+ +--------------+
struct net_device struct phy_device

Commands that needs to configure the PHY will go through the net_device.phydev
field to reach the PHY and perform the relevant configuration.

This assumption falls apart in more complex topologies that can arise when,
for example, using SFP transceivers (although that's not the only specific case).

Here, we have 2 basic scenarios. Either the MAC is able to output a serialized
interface, that can directly be fed to an SFP cage, such as SGMII, 1000BaseX,
10GBaseR, etc.

The link topology then looks like this (when an SFP module is inserted) ::

+-----+ SGMII +------------+
| MAC | ------- | SFP Module |
+-----+ +------------+

Knowing that some modules embed a PHY, the actual link is more like ::

+-----+ SGMII +--------------+
| MAC | -------- | PHY (on SFP) |
+-----+ +--------------+

In this case, the SFP PHY is handled by phylib, and registered by phylink through
its SFP upstream ops.

Now some Ethernet controllers aren't able to output a serialized interface, so
we can't directly connect them to an SFP cage. However, some PHYs can be used
as media-converters, to translate the non-serialized MAC MII interface to a
serialized MII interface fed to the SFP ::

+-----+ RGMII +-----------------------+ SGMII +--------------+
| MAC | ------- | PHY (media converter) | ------- | PHY (on SFP) |
+-----+ +-----------------------+ +--------------+

This is where the model of having a single net_device.phydev pointer shows its
limitations, as we now have 2 PHYs on the link.

The phy_link topology framework aims at providing a way to keep track of every
PHY on the link, for use by both kernel drivers and subsystems, but also to
report the topology to userspace, allowing to target individual PHYs in configuration
commands.

API
===

The :c:type:`struct phy_link_topology <phy_link_topology>` is a per-netdevice
resource, that gets initialized at netdevice creation. Once it's initialized,
it is then possible to register PHYs to the topology through :

:c:func:`phy_link_topo_add_phy`

Besides registering the PHY to the topology, this call will also assign a unique
index to the PHY, which can then be reported to userspace to refer to this PHY
(akin to the ifindex). This index is a u32, ranging from 1 to U32_MAX. The value
0 is reserved to indicate the PHY doesn't belong to any topology yet.

The PHY can then be removed from the topology through

:c:func:`phy_link_topo_del_phy`

These function are already hooked into the phylib subsystem, so all PHYs that
are linked to a net_device through :c:func:`phy_attach_direct` will automatically
join the netdev's topology.

PHYs that are on a SFP module will also be automatically registered IF the SFP
upstream is phylink (so, no media-converter).

PHY drivers that can be used as SFP upstream need to call :c:func:`phy_sfp_attach_phy`
and :c:func:`phy_sfp_detach_phy`, which can be used as a
.attach_phy / .detach_phy implementation for the
:c:type:`struct sfp_upstream_ops <sfp_upstream_ops>`.

UAPI
====

There exist a set of netlink commands to query the link topology from userspace,
see ``Documentation/networking/ethtool-netlink.rst``.

The whole point of having a topology representation is to assign the phyindex
field in :c:type:`struct phy_device <phy_device>`. This index is reported to
userspace using the ``ETHTOOL_MSG_PHY_GET`` ethtnl command. Performing a DUMP operation
will result in all PHYs from all net_device being listed. The DUMP command
accepts either a ``ETHTOOL_A_HEADER_DEV_INDEX`` or ``ETHTOOL_A_HEADER_DEV_NAME``
to be passed in the request to filter the DUMP to a single net_device.

The retrieved index can then be passed as a request parameter using the
``ETHTOOL_A_HEADER_PHY_INDEX`` field in the following ethnl commands :

* ``ETHTOOL_MSG_STRSET_GET`` to get the stats string set from a given PHY
* ``ETHTOOL_MSG_CABLE_TEST_ACT`` and ``ETHTOOL_MSG_CABLE_TEST_ACT``, to perform
cable testing on a given PHY on the link (most likely the outermost PHY)
* ``ETHTOOL_MSG_PSE_SET`` and ``ETHTOOL_MSG_PSE_GET`` for PHY-controlled PoE and PSE settings
* ``ETHTOOL_MSG_PLCA_GET_CFG``, ``ETHTOOL_MSG_PLCA_SET_CFG`` and ``ETHTOOL_MSG_PLCA_GET_STATUS``
to set the PLCA (Physical Layer Collision Avoidance) parameters

Note that the PHY index can be passed to other requests, which will silently
ignore it if present and irrelevant.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -8341,6 +8341,7 @@ F: include/linux/mii.h
F: include/linux/of_net.h
F: include/linux/phy.h
F: include/linux/phy_fixed.h
F: include/linux/phy_link_topology.h
F: include/linux/phylib_stubs.h
F: include/linux/platform_data/mdio-bcm-unimac.h
F: include/linux/platform_data/mdio-gpio.h
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/phy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Makefile for Linux PHY drivers

libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \
linkmode.o
linkmode.o phy_link_topology.o
mdio-bus-y += mdio_bus.o mdio_device.o

ifdef CONFIG_MDIO_DEVICE
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/phy/marvell-88x2222.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,8 @@ static const struct sfp_upstream_ops sfp_phy_ops = {
.link_down = mv2222_sfp_link_down,
.attach = phy_sfp_attach,
.detach = phy_sfp_detach,
.connect_phy = phy_sfp_connect_phy,
.disconnect_phy = phy_sfp_disconnect_phy,
};

static int mv2222_probe(struct phy_device *phydev)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/phy/marvell.c
Original file line number Diff line number Diff line change
Expand Up @@ -3613,6 +3613,8 @@ static const struct sfp_upstream_ops m88e1510_sfp_ops = {
.module_remove = m88e1510_sfp_remove,
.attach = phy_sfp_attach,
.detach = phy_sfp_detach,
.connect_phy = phy_sfp_connect_phy,
.disconnect_phy = phy_sfp_disconnect_phy,
};

static int m88e1510_probe(struct phy_device *phydev)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/phy/marvell10g.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
static const struct sfp_upstream_ops mv3310_sfp_ops = {
.attach = phy_sfp_attach,
.detach = phy_sfp_detach,
.connect_phy = phy_sfp_connect_phy,
.disconnect_phy = phy_sfp_disconnect_phy,
.module_insert = mv3310_sfp_insert,
};

Expand Down
Loading

0 comments on commit b34a6e7

Please sign in to comment.