From: Aleksander Jan Bajkowski <olek2@wp.pl>
To: andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: Aleksander Jan Bajkowski <olek2@wp.pl>
Subject: [PATCH] net: phy: intel-xway: add PHY-level statistics via ethtool
Date: Sat, 9 May 2026 22:59:27 +0200 [thread overview]
Message-ID: <20260509205933.3965832-1-olek2@wp.pl> (raw)
Report PCS receive error counts for all supported PEF 7061, 7071, 7072 and
xRX200 PHYs.
Accumulate the vendor-specific PHY_ERRCNT read-clear counter
(SEL=RXERR) in .update_stats() and expose it as both IEEE 802.3
SymbolErrorDuringCarrier and generic rx_errors via
.get_phy_stats().
Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
---
drivers/net/phy/intel-xway.c | 79 ++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c
index 12ff4c1f285d..afbcec711744 100644
--- a/drivers/net/phy/intel-xway.c
+++ b/drivers/net/phy/intel-xway.c
@@ -10,11 +10,16 @@
#include <linux/of.h>
#include <linux/bitfield.h>
+#define XWAY_MDIO_ERRCNT 0x15 /* error counter */
#define XWAY_MDIO_MIICTRL 0x17 /* mii control */
#define XWAY_MDIO_IMASK 0x19 /* interrupt mask */
#define XWAY_MDIO_ISTAT 0x1A /* interrupt status */
#define XWAY_MDIO_LED 0x1B /* led control */
+#define XWAY_MDIO_ERRCNT_SEL GENMASK(11, 8)
+#define XWAY_MDIO_ERRCNT_COUNT GENMASK(7, 0)
+#define XWAY_MDIO_ERRCNT_SEL_RXERR 0
+
#define XWAY_MDIO_MIICTRL_RXSKEW_MASK GENMASK(14, 12)
#define XWAY_MDIO_MIICTRL_TXSKEW_MASK GENMASK(10, 8)
@@ -169,6 +174,10 @@
#define PHY_ID_PHY11G_VR9_1_2 0xD565A409
#define PHY_ID_PHY22F_VR9_1_2 0xD565A419
+struct xway_gphy_priv {
+ u64 rx_errors;
+};
+
static const int xway_internal_delay[] = {0, 500, 1000, 1500, 2000, 2500,
3000, 3500};
@@ -299,6 +308,21 @@ static int xway_gphy_config_init(struct phy_device *phydev)
if (err)
return err;
+ /* Count MDI RX errors (SymbolErrorDuringCarrier) */
+ return phy_write(phydev, XWAY_MDIO_ERRCNT,
+ FIELD_PREP(XWAY_MDIO_ERRCNT_SEL, XWAY_MDIO_ERRCNT_SEL_RXERR));
+}
+
+static int xway_gphy_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct xway_gphy_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ phydev->priv = priv;
+
return 0;
}
@@ -532,6 +556,31 @@ static int xway_gphy_led_polarity_set(struct phy_device *phydev, int index,
return -EINVAL;
}
+static int xway_gphy_update_stats(struct phy_device *phydev)
+{
+ struct xway_gphy_priv *priv = phydev->priv;
+ int ret;
+
+ /* XWAY_MDIO_ERRCNT: 8-bit read-clear counter, SEL set to RXERR */
+ ret = phy_read(phydev, XWAY_MDIO_ERRCNT);
+ if (ret < 0)
+ return ret;
+
+ priv->rx_errors += FIELD_GET(XWAY_MDIO_ERRCNT_COUNT, ret);
+
+ return 0;
+}
+
+static void xway_gphy_get_phy_stats(struct phy_device *phydev,
+ struct ethtool_eth_phy_stats *eth_stats,
+ struct ethtool_phy_stats *stats)
+{
+ struct xway_gphy_priv *priv = phydev->priv;
+
+ eth_stats->SymbolErrorDuringCarrier = priv->rx_errors;
+ stats->rx_errors = priv->rx_errors;
+}
+
static struct phy_driver xway_gphy[] = {
{
.phy_id = PHY_ID_PHY11G_1_3,
@@ -539,6 +588,7 @@ static struct phy_driver xway_gphy[] = {
.name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.3",
/* PHY_GBIT_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.config_aneg = xway_gphy14_config_aneg,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
@@ -549,12 +599,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY22F_1_3,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (PEF 7061) v1.3",
/* PHY_BASIC_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.config_aneg = xway_gphy14_config_aneg,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
@@ -565,12 +618,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY11G_1_4,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.4",
/* PHY_GBIT_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.config_aneg = xway_gphy14_config_aneg,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
@@ -581,12 +637,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY22F_1_4,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (PEF 7061) v1.4",
/* PHY_BASIC_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.config_aneg = xway_gphy14_config_aneg,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
@@ -597,12 +656,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY11G_1_5,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6",
/* PHY_GBIT_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
@@ -612,12 +674,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY22F_1_5,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (PEF 7061) v1.5 / v1.6",
/* PHY_BASIC_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
@@ -627,12 +692,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY11G_VR9_1_1,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (xRX v1.1 integrated)",
/* PHY_GBIT_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
@@ -642,12 +710,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY22F_VR9_1_1,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (xRX v1.1 integrated)",
/* PHY_BASIC_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
@@ -657,12 +728,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY11G_VR9_1_2,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (xRX v1.2 integrated)",
/* PHY_GBIT_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
@@ -672,12 +746,15 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
}, {
.phy_id = PHY_ID_PHY22F_VR9_1_2,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (xRX v1.2 integrated)",
/* PHY_BASIC_FEATURES */
.config_init = xway_gphy_config_init,
+ .probe = xway_gphy_probe,
.handle_interrupt = xway_gphy_handle_interrupt,
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
@@ -687,6 +764,8 @@ static struct phy_driver xway_gphy[] = {
.led_hw_control_get = xway_gphy_led_hw_control_get,
.led_hw_control_set = xway_gphy_led_hw_control_set,
.led_polarity_set = xway_gphy_led_polarity_set,
+ .update_stats = xway_gphy_update_stats,
+ .get_phy_stats = xway_gphy_get_phy_stats,
},
};
module_phy_driver(xway_gphy);
--
2.53.0
next reply other threads:[~2026-05-09 21:06 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-09 20:59 Aleksander Jan Bajkowski [this message]
2026-05-13 3:45 ` [PATCH] net: phy: intel-xway: add PHY-level statistics via ethtool patchwork-bot+netdevbpf
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=20260509205933.3965832-1-olek2@wp.pl \
--to=olek2@wp.pl \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=hkallweit1@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.