From: Oleksij Rempel <o.rempel@pengutronix.de>
To: Andrew Lunn <andrew@lunn.ch>, Jakub Kicinski <kuba@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Donald Hunter <donald.hunter@gmail.com>,
Jonathan Corbet <corbet@lwn.net>,
Heiner Kallweit <hkallweit1@gmail.com>,
Russell King <linux@armlinux.org.uk>,
Kory Maincent <kory.maincent@bootlin.com>,
Maxime Chevallier <maxime.chevallier@bootlin.com>,
Nishanth Menon <nm@ti.com>
Cc: Oleksij Rempel <o.rempel@pengutronix.de>,
kernel@pengutronix.de, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, UNGLinuxDriver@microchip.com,
linux-doc@vger.kernel.org, Michal Kubecek <mkubecek@suse.cz>,
Roan van Dijk <roan@protonic.nl>
Subject: [PATCH net-next v3 3/5] ethtool: netlink: add lightweight MSE reporting to LINKSTATE_GET
Date: Tue, 19 Aug 2025 09:12:54 +0200 [thread overview]
Message-ID: <20250819071256.3392659-4-o.rempel@pengutronix.de> (raw)
In-Reply-To: <20250819071256.3392659-1-o.rempel@pengutronix.de>
Extend ETHTOOL_MSG_LINKSTATE_GET to optionally return a simplified
Mean Square Error (MSE) reading alongside existing link status fields.
The new attributes are:
- ETHTOOL_A_LINKSTATE_MSE_VALUE: current average MSE value
- ETHTOOL_A_LINKSTATE_MSE_MAX: scale limit for the reported value
- ETHTOOL_A_LINKSTATE_MSE_CHANNEL: source channel selector
This path reuses the PHY MSE core API, but only retrieves a single
value intended for quick link-health checks:
* If the PHY supports a WORST channel selector, report its current
average MSE.
* Otherwise, if LINK-wide measurements are supported, report those.
* If neither is available, omit the attributes.
Unlike the full MSE_GET interface, LINKSTATE_GET does not expose
per-channel or peak/worst-peak values and incurs minimal overhead.
Drivers that implement get_mse_config() / get_mse_snapshot() will
automatically populate this data.
The intent is to provide tooling with a “fast path” health indicator
without issuing a separate MSE_GET request, though the long-term
overlap with the full interface may need reevaluation.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
changes v3:
- add missing yaml spec
---
Documentation/netlink/specs/ethtool.yaml | 9 ++
Documentation/networking/ethtool-netlink.rst | 9 ++
.../uapi/linux/ethtool_netlink_generated.h | 3 +
net/ethtool/linkstate.c | 84 +++++++++++++++++++
4 files changed, 105 insertions(+)
diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml
index ed4774826b16..ffdabcbe47b9 100644
--- a/Documentation/netlink/specs/ethtool.yaml
+++ b/Documentation/netlink/specs/ethtool.yaml
@@ -708,6 +708,15 @@ attribute-sets:
-
name: ext-down-cnt
type: u32
+ -
+ name: mse-value
+ type: u32
+ -
+ name: mse-max
+ type: u32
+ -
+ name: mse-channel
+ type: u32
-
name: debug
attr-cnt-name: __ethtool-a-debug-cnt
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
index 55efe3673f85..a3c47dfc0605 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -530,6 +530,9 @@ Kernel response contents:
``ETHTOOL_A_LINKSTATE_EXT_STATE`` u8 link extended state
``ETHTOOL_A_LINKSTATE_EXT_SUBSTATE`` u8 link extended substate
``ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT`` u32 count of link down events
+ ``ETHTOOL_A_LINKSTATE_MSE_VALUE`` u32 Current average MSE value
+ ``ETHTOOL_A_LINKSTATE_MSE_MAX`` u32 Max scale for average MSE
+ ``ETHTOOL_A_LINKSTATE_MSE_CHANNEL`` u32 Source of MSE value
==================================== ====== ============================
For most NIC drivers, the value of ``ETHTOOL_A_LINKSTATE_LINK`` returns
@@ -541,6 +544,12 @@ optional values. ethtool core can provide either both
``ETHTOOL_A_LINKSTATE_EXT_STATE`` and ``ETHTOOL_A_LINKSTATE_EXT_SUBSTATE``,
or only ``ETHTOOL_A_LINKSTATE_EXT_STATE``, or none of them.
+``ETHTOOL_A_LINKSTATE_MSE_VALUE`` and ``ETHTOOL_A_LINKSTATE_MSE_MAX`` are
+optional values. The MSE value provided by this interface is a lightweight,
+less detailed version for quick health checks. If only one channel is used, it
+returns the current average MSE value. If multiple channels are supported, it
+returns the current average MSE of the channel with the worst MSE.
+
``LINKSTATE_GET`` allows dump requests (kernel returns reply messages for all
devices supporting the request).
diff --git a/include/uapi/linux/ethtool_netlink_generated.h b/include/uapi/linux/ethtool_netlink_generated.h
index 9c37a96a320b..6ef03a7de4ab 100644
--- a/include/uapi/linux/ethtool_netlink_generated.h
+++ b/include/uapi/linux/ethtool_netlink_generated.h
@@ -322,6 +322,9 @@ enum {
ETHTOOL_A_LINKSTATE_EXT_STATE,
ETHTOOL_A_LINKSTATE_EXT_SUBSTATE,
ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT,
+ ETHTOOL_A_LINKSTATE_MSE_VALUE,
+ ETHTOOL_A_LINKSTATE_MSE_MAX,
+ ETHTOOL_A_LINKSTATE_MSE_CHANNEL,
__ETHTOOL_A_LINKSTATE_CNT,
ETHTOOL_A_LINKSTATE_MAX = (__ETHTOOL_A_LINKSTATE_CNT - 1)
diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c
index 05a5f72c99fa..b27fb0ffc526 100644
--- a/net/ethtool/linkstate.c
+++ b/net/ethtool/linkstate.c
@@ -14,6 +14,9 @@ struct linkstate_reply_data {
int link;
int sqi;
int sqi_max;
+ u32 mse_value;
+ u32 mse_max;
+ u32 mse_channel;
struct ethtool_link_ext_stats link_stats;
bool link_ext_state_provided;
struct ethtool_link_ext_state_info ethtool_link_ext_state_info;
@@ -76,6 +79,65 @@ static bool linkstate_sqi_valid(struct linkstate_reply_data *data)
data->sqi <= data->sqi_max;
}
+static int linkstate_get_mse(struct phy_device *phydev,
+ struct linkstate_reply_data *data)
+{
+ struct phy_mse_snapshot snapshot = {};
+ struct phy_mse_config config = {};
+ int channel, ret;
+
+ if (!phydev)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&phydev->lock);
+
+ if (!phydev->drv || !phydev->drv->get_mse_config ||
+ !phydev->drv->get_mse_snapshot) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
+
+ if (!phydev->link) {
+ ret = -ENETDOWN;
+ goto unlock;
+ }
+
+ ret = phydev->drv->get_mse_config(phydev, &config);
+ if (ret)
+ goto unlock;
+
+ if (config.supported_caps & PHY_MSE_CAP_WORST_CHANNEL) {
+ channel = PHY_MSE_CHANNEL_WORST;
+ } else if (config.supported_caps & PHY_MSE_CAP_LINK) {
+ channel = PHY_MSE_CHANNEL_LINK;
+ } else {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
+
+ ret = phydev->drv->get_mse_snapshot(phydev, channel, &snapshot);
+ if (ret)
+ goto unlock;
+
+ data->mse_value = snapshot.average_mse;
+ data->mse_max = config.max_average_mse;
+ data->mse_channel = channel;
+
+unlock:
+ mutex_unlock(&phydev->lock);
+ return ret;
+}
+
+static bool linkstate_mse_critical_error(int err)
+{
+ return err < 0 && err != -EOPNOTSUPP && err != -ENETDOWN;
+}
+
+static bool linkstate_mse_valid(struct linkstate_reply_data *data)
+{
+ return data->mse_max > 0 && data->mse_value <= data->mse_max;
+}
+
static int linkstate_get_link_ext_state(struct net_device *dev,
struct linkstate_reply_data *data)
{
@@ -125,6 +187,10 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
goto out;
data->sqi_max = ret;
+ ret = linkstate_get_mse(phydev, data);
+ if (linkstate_mse_critical_error(ret))
+ goto out;
+
if (dev->flags & IFF_UP) {
ret = linkstate_get_link_ext_state(dev, data);
if (ret < 0 && ret != -EOPNOTSUPP && ret != -ENODATA)
@@ -164,6 +230,12 @@ static int linkstate_reply_size(const struct ethnl_req_info *req_base,
len += nla_total_size(sizeof(u32)); /* LINKSTATE_SQI_MAX */
}
+ if (linkstate_mse_valid(data)) {
+ len += nla_total_size(sizeof(u32)); /* LINKSTATE_MSE_VALUE */
+ len += nla_total_size(sizeof(u32)); /* LINKSTATE_MSE_MAX */
+ len += nla_total_size(sizeof(u32)); /* LINKSTATE_MSE_CHANNEL */
+ }
+
if (data->link_ext_state_provided)
len += nla_total_size(sizeof(u8)); /* LINKSTATE_EXT_STATE */
@@ -195,6 +267,18 @@ static int linkstate_fill_reply(struct sk_buff *skb,
return -EMSGSIZE;
}
+ if (linkstate_mse_valid(data)) {
+ if (nla_put_u32(skb, ETHTOOL_A_LINKSTATE_MSE_VALUE,
+ data->mse_value))
+ return -EMSGSIZE;
+ if (nla_put_u32(skb, ETHTOOL_A_LINKSTATE_MSE_MAX,
+ data->mse_max))
+ return -EMSGSIZE;
+ if (nla_put_u32(skb, ETHTOOL_A_LINKSTATE_MSE_CHANNEL,
+ data->mse_channel))
+ return -EMSGSIZE;
+ }
+
if (data->link_ext_state_provided) {
if (nla_put_u8(skb, ETHTOOL_A_LINKSTATE_EXT_STATE,
data->ethtool_link_ext_state_info.link_ext_state))
--
2.39.5
next prev parent reply other threads:[~2025-08-19 7:13 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-19 7:12 [PATCH net-next v3 0/5] ethtool: introduce PHY MSE diagnostics UAPI and drivers Oleksij Rempel
2025-08-19 7:12 ` [PATCH net-next v3 1/5] ethtool: introduce core UAPI and driver API for PHY MSE diagnostics Oleksij Rempel
2025-08-19 7:12 ` [PATCH net-next v3 2/5] ethtool: netlink: add ETHTOOL_MSG_MSE_GET and wire up PHY MSE access Oleksij Rempel
2025-08-20 9:41 ` Kory Maincent
2025-08-19 7:12 ` Oleksij Rempel [this message]
2025-08-20 9:52 ` [PATCH net-next v3 3/5] ethtool: netlink: add lightweight MSE reporting to LINKSTATE_GET Kory Maincent
2025-08-19 7:12 ` [PATCH net-next v3 4/5] net: phy: micrel: add MSE interface support for KSZ9477 family Oleksij Rempel
2025-08-19 7:12 ` [PATCH net-next v3 5/5] net: phy: dp83td510: add MSE interface support for 10BASE-T1L Oleksij Rempel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250819071256.3392659-4-o.rempel@pengutronix.de \
--to=o.rempel@pengutronix.de \
--cc=UNGLinuxDriver@microchip.com \
--cc=andrew@lunn.ch \
--cc=corbet@lwn.net \
--cc=davem@davemloft.net \
--cc=donald.hunter@gmail.com \
--cc=edumazet@google.com \
--cc=hkallweit1@gmail.com \
--cc=horms@kernel.org \
--cc=kernel@pengutronix.de \
--cc=kory.maincent@bootlin.com \
--cc=kuba@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=maxime.chevallier@bootlin.com \
--cc=mkubecek@suse.cz \
--cc=netdev@vger.kernel.org \
--cc=nm@ti.com \
--cc=pabeni@redhat.com \
--cc=roan@protonic.nl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).