* [PATCH net-next v4 0/3] ethtool: expose PHY receive totals
@ 2026-11-13 17:12 James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 1/3] ethtool: add PHY receive frame and byte totals James Hilliard
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: James Hilliard @ 2026-11-13 17:12 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Jonathan Corbet, Shuah Khan, Randy Dunlap
Cc: Oleksij Rempel, netdev, linux-kernel, linux-doc, James Hilliard,
stable+noautosel
Some PHYs count received frames and bytes including errored traffic. Add
explicit receive-total counters to the generic PHY statistics interface
alongside its counters for successfully received traffic.
Use the new counters to expose ACx00 receive statistics through the phydev
group. Accumulate sampled deltas in 64-bit software totals, retain those
totals across reset and power transitions, and return cached snapshots to
ethtool. Establish new baselines after reset, resume or sampling gaps that
could hide a complete counter cycle.
Convert DP83TG720's existing RX packet statistic to the receive-total
counter, matching its documented inclusion of packets with errors.
Assisted-by: Codex:gpt-6-astra
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Changes in v4:
- Invalidate the ACx00 baseline before accessing counters in soft_reset,
since phylib may already have reset the hardware before the callback.
- Start a new collection interval on resume and after gaps of at least
320 seconds, including system sleep, preserving collected totals without
interpreting unobserved traffic modulo the hardware counter width.
- Clarify that the byte modulus and frame-byte boundaries were measured
on both AC200 and AC300.
- Specify matching frame-byte boundaries for both PHY byte counters and
explain that phydev corrects the documented name of the existing group.
- Mark the DP83TG720 conversion as unsuitable for automatic stable
selection without the new receive-total API.
- Rebase onto current net-next.
- Link to v3: https://patch.msgid.link/20261109-submit-acx00-phy-stats-v1-v3-0-fbc6327c5be4@gmail.com
Changes in v3:
- Add generic PHY receive-total packet and byte counters in a preparatory
patch, retaining the existing successful-traffic counters and their IDs.
- Report ACx00 packet and byte totals through the new fields, leaving
successful-only counters unset.
- Convert DP83TG720's inclusive RX packet count to the new total field.
- Bound coherent-counter sampling to three attempts and skip unstable
snapshots without making phylib take the link down.
- Reject out-of-range byte samples before updating the hardware baseline
or accumulated totals, retaining MDIO and page-restoration errors.
- Rebase onto current net-next.
- Link to v2: https://patch.msgid.link/20261102-submit-acx00-phy-stats-v1-v2-1-3c8a664407c1@gmail.com
Changes in v2:
- Rebase onto current net-next and repost after the merge window.
- No functional changes.
- Link to v1: https://patch.msgid.link/20261025-submit-acx00-phy-stats-v1-v1-1-d3d461e46db0@gmail.com
To: Andrew Lunn <andrew@lunn.ch>
To: Jakub Kicinski <kuba@kernel.org>
To: "David S. Miller" <davem@davemloft.net>
To: Eric Dumazet <edumazet@kernel.org>
To: Paolo Abeni <pabeni@redhat.com>
To: Simon Horman <horms@kernel.org>
To: Jonathan Corbet <corbet@lwn.net>
To: Shuah Khan <skhan@linuxfoundation.org>
To: Randy Dunlap <rdunlap@infradead.org>
To: Heiner Kallweit <hkallweit1@gmail.com>
To: Russell King <linux@armlinux.org.uk>
To: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: netdev@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
James Hilliard (3):
ethtool: add PHY receive frame and byte totals
net: phy: acx00: report receive statistics
net: phy: dp83tg720: report inclusive RX packet totals
Documentation/networking/ethtool-netlink.rst | 16 ++-
drivers/net/phy/dp83tg720.c | 2 +-
drivers/net/phy/xpowers/acx00.c | 184 ++++++++++++++++++++++++++-
include/linux/ethtool.h | 10 +-
include/uapi/linux/ethtool_netlink.h | 2 +
net/ethtool/stats.c | 8 +-
6 files changed, 215 insertions(+), 7 deletions(-)
---
base-commit: 573af801552999954caa8347e4490b04cf4763f0
change-id: 20261024-submit-acx00-phy-stats-v1-d838f77444e8
Best regards,
--
James Hilliard <james.hilliard1@gmail.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net-next v4 1/3] ethtool: add PHY receive frame and byte totals
2026-11-13 17:12 [PATCH net-next v4 0/3] ethtool: expose PHY receive totals James Hilliard
@ 2026-11-13 17:12 ` James Hilliard
2026-11-13 20:55 ` Andrew Lunn
2026-11-13 17:12 ` [PATCH net-next v4 2/3] net: phy: acx00: report receive statistics James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 3/3] net: phy: dp83tg720: report inclusive RX packet totals James Hilliard
2 siblings, 1 reply; 6+ messages in thread
From: James Hilliard @ 2026-11-13 17:12 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Jonathan Corbet, Shuah Khan, Randy Dunlap
Cc: Oleksij Rempel, netdev, linux-kernel, linux-doc, James Hilliard
The generic PHY receive packet and byte counters describe successfully
received traffic. Some PHYs instead count all received frames and bytes,
including frames with errors. A frame error count cannot recover the
number of successfully received bytes because damaged frames have
different lengths.
Add optional receive-total counters to ethtool_phy_stats and the phydev
statistics group. Count frame bytes including the Ethernet header, padding
and FCS, and excluding the preamble and start frame delimiter. These
counters describe reception at the PHY, before MAC or host filtering.
Clarify the same byte boundaries for the successful-only receive counter.
Append the new attributes so existing statistic IDs and their meanings
remain unchanged. Publish the names through the existing statistics string
set, and retain the unset-counter convention so drivers can report either
set of counters independently. Correct the documented group name to
phydev, matching the existing name exported by the kernel.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Documentation/networking/ethtool-netlink.rst | 16 +++++++++++++++-
include/linux/ethtool.h | 10 +++++++++-
include/uapi/linux/ethtool_netlink.h | 2 ++
net/ethtool/stats.c | 8 +++++++-
4 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
index eba226c79ec3..40dd454d4ad3 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -1665,7 +1665,7 @@ the ``ETHTOOL_A_STATS_GROUPS`` bitset. Currently defined values are:
ETHTOOL_STATS_ETH_PHY eth-phy Basic IEEE 802.3 PHY statistics (30.3.2.1.*)
ETHTOOL_STATS_ETH_CTRL eth-ctrl Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*)
ETHTOOL_STATS_RMON rmon RMON (RFC 2819) statistics
- ETHTOOL_STATS_PHY phy Additional PHY statistics, not defined by IEEE
+ ETHTOOL_STATS_PHY phydev Additional PHY statistics, not defined by IEEE
====================== ======== ===============================================
Each group should have a corresponding ``ETHTOOL_A_STATS_GRP`` in the reply.
@@ -1683,6 +1683,20 @@ by ``ETHTOOL_A_STATS_GRP_SS_ID``. Complex statistics (such as RMON histogram
entries) are also listed inside ``ETHTOOL_A_STATS_GRP`` and do not have
a string defined in the string set.
+The ``phydev`` group provides separate counters for successfully received
+traffic and total received traffic. ``ETHTOOL_A_STATS_PHY_RX_PKTS``
+(``RxFrames``) and ``ETHTOOL_A_STATS_PHY_RX_BYTES`` (``RxOctets``) count
+successfully received frames and bytes. ``ETHTOOL_A_STATS_PHY_RX_PKTS_TOTAL``
+(``RxFramesTotal``) and ``ETHTOOL_A_STATS_PHY_RX_BYTES_TOTAL`` (``RxOctetsTotal``)
+include frames with errors. Both byte counters include the Ethernet header,
+padding and FCS, but exclude the preamble and start frame delimiter. These
+totals describe reception at the PHY, independently of subsequent filtering
+or drops at the MAC or host.
+
+Each counter is optional. Drivers leave unsupported counters at
+``ETHTOOL_STAT_NOT_SET``, and the kernel omits them from the reply. A PHY can
+report total received traffic even when it cannot separate successful traffic.
+
RMON "histogram" counters count number of packets within given size range.
Because RFC does not specify the ranges beyond the standard 1518 MTU devices
differ in definition of buckets. For this reason the definition of packet ranges
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index c3a41fbd5426..f3e0fac8fdfd 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -481,11 +481,17 @@ struct ethtool_eth_phy_stats {
/**
* struct ethtool_phy_stats - PHY-level statistics counters
* @rx_packets: Total successfully received frames
- * @rx_bytes: Total successfully received bytes
+ * @rx_bytes: Total successfully received frame bytes. Includes the Ethernet
+ * header, padding and FCS, but excludes the preamble and start frame
+ * delimiter.
* @rx_errors: Total received frames with errors (e.g., CRC errors)
* @tx_packets: Total successfully transmitted frames
* @tx_bytes: Total successfully transmitted bytes
* @tx_errors: Total transmitted frames with errors
+ * @rx_packets_total: Total received frames, including frames with errors
+ * @rx_bytes_total: Total received frame bytes, including frames with errors.
+ * Includes the Ethernet header, padding and FCS, but excludes the preamble
+ * and start frame delimiter.
*
* This structure provides a standardized interface for reporting
* PHY-level statistics counters. It is designed to expose statistics
@@ -499,6 +505,8 @@ struct ethtool_phy_stats {
u64 tx_packets;
u64 tx_bytes;
u64 tx_errors;
+ u64 rx_packets_total;
+ u64 rx_bytes_total;
};
/* Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*), not otherwise exposed
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index fa5d645140a4..db26cff28f12 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -202,6 +202,8 @@ enum {
ETHTOOL_A_STATS_PHY_TX_PKTS,
ETHTOOL_A_STATS_PHY_TX_BYTES,
ETHTOOL_A_STATS_PHY_TX_ERRORS,
+ ETHTOOL_A_STATS_PHY_RX_PKTS_TOTAL,
+ ETHTOOL_A_STATS_PHY_RX_BYTES_TOTAL,
/* add new constants above here */
__ETHTOOL_A_STATS_PHY_CNT,
diff --git a/net/ethtool/stats.c b/net/ethtool/stats.c
index 9b0d8cb07675..b4c4bdd8fc4b 100644
--- a/net/ethtool/stats.c
+++ b/net/ethtool/stats.c
@@ -88,6 +88,8 @@ const char stats_phy_names[__ETHTOOL_A_STATS_PHY_CNT][ETH_GSTRING_LEN] = {
[ETHTOOL_A_STATS_PHY_TX_PKTS] = "TxFrames",
[ETHTOOL_A_STATS_PHY_TX_BYTES] = "TxOctets",
[ETHTOOL_A_STATS_PHY_TX_ERRORS] = "TxErrors",
+ [ETHTOOL_A_STATS_PHY_RX_PKTS_TOTAL] = "RxFramesTotal",
+ [ETHTOOL_A_STATS_PHY_RX_BYTES_TOTAL] = "RxOctetsTotal",
};
const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_SRC + 1] = {
@@ -295,7 +297,11 @@ static int stats_put_phydev_stats(struct sk_buff *skb,
stat_put(skb, ETHTOOL_A_STATS_PHY_TX_BYTES,
data->phydev_stats.tx_bytes) ||
stat_put(skb, ETHTOOL_A_STATS_PHY_TX_ERRORS,
- data->phydev_stats.tx_errors))
+ data->phydev_stats.tx_errors) ||
+ stat_put(skb, ETHTOOL_A_STATS_PHY_RX_PKTS_TOTAL,
+ data->phydev_stats.rx_packets_total) ||
+ stat_put(skb, ETHTOOL_A_STATS_PHY_RX_BYTES_TOTAL,
+ data->phydev_stats.rx_bytes_total))
return -EMSGSIZE;
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next v4 2/3] net: phy: acx00: report receive statistics
2026-11-13 17:12 [PATCH net-next v4 0/3] ethtool: expose PHY receive totals James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 1/3] ethtool: add PHY receive frame and byte totals James Hilliard
@ 2026-11-13 17:12 ` James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 3/3] net: phy: dp83tg720: report inclusive RX packet totals James Hilliard
2 siblings, 0 replies; 6+ messages in thread
From: James Hilliard @ 2026-11-13 17:12 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Jonathan Corbet, Shuah Khan, Randy Dunlap
Cc: Oleksij Rempel, netdev, linux-kernel, linux-doc, James Hilliard
Expose receive frame and byte totals through the generic PHY statistics
interface as rx_packets_total and rx_bytes_total, alongside CRC errors in
rx_errors. The packet and byte counters include errored frames as well as
successfully received traffic, so leave the successful-only fields unset.
Collect the free-running 32-bit counters through phylib's update_stats
callback and accumulate wrap-adjusted deltas in 64-bit totals. Hardware
measurements on AC200 and AC300 established a receive-byte modulus of
4,000,000,000. The byte counts include Ethernet headers, padding and FCS,
but exclude preamble and SFD. The packet and CRC-error counters wrap at
2^32. Reject byte samples at or above the byte modulus before updating
either the baseline or the totals.
Read the high half on either side of the low half to detect a carry.
Limit each counter to three attempts so persistent inconsistency cannot
retain the PHY, package-state and MDIO locks indefinitely. Skip an
unstable snapshot and retry on the next poll: reporting a synthetic
error through update_stats would make phylib take the link down.
Keep incomplete samples distinct from MDIO errors so page-restoration
failures still propagate.
Serialize collection and reporting with the package-state mutex so reads
cannot race reset or power-off, and the totals are safe on 32-bit systems.
Commit a snapshot only after all counter reads, validation and page
restoration succeed. The reporting callback returns cached totals without
accessing MDIO.
Take a best-effort final snapshot before suspend, but invalidate the
baseline at entry to soft_reset: phylib may already have reset the PHY
through BMCR or its reset signal. Sampling against the previous baseline
then would count the cleared registers as a wrap. Invalidate it before
power-off too, including failed power-off attempts.
Start a new collection interval on resume, including when WoL kept the
PHY powered while polling stopped. Also discard deltas spanning at least
320 seconds, the minimum time for a full byte-counter cycle at 100 Mb/s.
Measure that interval with boottime, including system sleep and register
read duration, since the MDIO sleep path can bypass the PHY PM callbacks.
Retain previously accumulated totals, but do not account for traffic in
these unobserved intervals: complete counter cycles cannot be recovered
from the endpoint values. An unusable initial snapshot is retried by the
periodic collector without preventing initialization.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/net/phy/xpowers/acx00.c | 184 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 181 insertions(+), 3 deletions(-)
diff --git a/drivers/net/phy/xpowers/acx00.c b/drivers/net/phy/xpowers/acx00.c
index cee6c7ff0278..fb53bac12195 100644
--- a/drivers/net/phy/xpowers/acx00.c
+++ b/drivers/net/phy/xpowers/acx00.c
@@ -8,12 +8,14 @@
#include <linux/bitfield.h>
#include <linux/device.h>
+#include <linux/ethtool.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/slab.h>
+#include <linux/timekeeping.h>
#include "../phylib.h"
#include "acx00.h"
@@ -31,6 +33,7 @@
#define ACX00_PAGE_2 2
#define ACX00_PAGE_6 6
#define ACX00_PAGE_8 8
+#define ACX00_PAGE_9 9
#define ACX00_PAGE0_GLOBAL_CONFIG_REG 0x13
#define ACX00_PAGE0_XMII_RX_CLOCK_INVERT BIT(12)
@@ -76,6 +79,32 @@
(ACX00_PAGE8_AUTO_CAL_TX_LEVEL_ADJUST_BYPASS | \
ACX00_PAGE8_AUTO_CAL_LOW_CAL_OPAQUE_BITS)
+#define ACX00_PAGE9_RX_BYTES_HIGH_REG 0x19
+#define ACX00_PAGE9_RX_PACKETS_HIGH_REG 0x1b
+#define ACX00_PAGE9_RX_CRC_ERRORS_HIGH_REG 0x1d
+
+/*
+ * AC200 and AC300 hardware testing confirmed that the receive byte counter
+ * wraps at 4,000,000,000 rather than 2^32.
+ */
+#define ACX00_RX_BYTES_WRAP 4000000000ULL
+/* At 100 Mb/s, a full byte-counter cycle takes at least 320 seconds. */
+#define ACX00_STATS_MAX_INTERVAL_MS (ACX00_RX_BYTES_WRAP * 8 / (SPEED_100 * 1000))
+#define ACX00_COUNTER_READ_ATTEMPTS 3
+
+enum acx00_ephy_stat {
+ ACX00_STAT_RX_BYTES,
+ ACX00_STAT_RX_PACKETS,
+ ACX00_STAT_RX_CRC_ERRORS,
+ ACX00_NUM_STATS,
+};
+
+static const u8 acx00_ephy_stat_regs[ACX00_NUM_STATS] = {
+ [ACX00_STAT_RX_BYTES] = ACX00_PAGE9_RX_BYTES_HIGH_REG,
+ [ACX00_STAT_RX_PACKETS] = ACX00_PAGE9_RX_PACKETS_HIGH_REG,
+ [ACX00_STAT_RX_CRC_ERRORS] = ACX00_PAGE9_RX_CRC_ERRORS_HIGH_REG,
+};
+
/*
* Another integration of this exact-ID PHY documents its digital vendor
* register map, which also matches the observed ACx00 reset values. The ACx00
@@ -86,11 +115,16 @@
struct acx00_ephy_priv {
struct phy_device *phydev;
struct acx00_ephy_control *control;
- /* Serializes package state and multi-register power sequences. */
+ /* Serializes package state, power sequences and statistics. */
struct mutex state_lock;
bool is_ac300;
bool use_low_calibration_tuning;
bool xmii_rx_clock_inverted;
+ bool stats_active;
+ bool stats_valid;
+ ktime_t stats_start;
+ u32 stats_last[ACX00_NUM_STATS];
+ u64 stats[ACX00_NUM_STATS];
};
static int acx00_ephy_read_page(struct phy_device *phydev)
@@ -110,6 +144,124 @@ static int acx00_ephy_write_page(struct phy_device *phydev, int page)
FIELD_PREP(ACX00_PAGE_SELECT_MASK, page));
}
+/* Return 0 on success, 1 for an unstable sample, or a negative MDIO error. */
+static int acx00_ephy_read_counter(struct phy_device *phydev, u8 reg, u32 *count)
+{
+ int high, low, check;
+ int i;
+
+ /* The free-running counter can carry while its two halves are read. */
+ for (i = 0; i < ACX00_COUNTER_READ_ATTEMPTS; i++) {
+ high = __phy_read(phydev, reg);
+ if (high < 0)
+ return high;
+ low = __phy_read(phydev, reg + 1);
+ if (low < 0)
+ return low;
+ check = __phy_read(phydev, reg);
+ if (check < 0)
+ return check;
+ if (high != check)
+ continue;
+
+ *count = (u32)high << 16 | low;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int __acx00_ephy_update_stats(struct phy_device *phydev)
+{
+ struct acx00_ephy_priv *priv = phydev->priv;
+ u32 counts[ACX00_NUM_STATS];
+ ktime_t start;
+ int oldpage;
+ int ret;
+ int i;
+
+ lockdep_assert_held(&priv->state_lock);
+
+ if (!priv->stats_active)
+ return 0;
+
+ start = ktime_get_boottime();
+ oldpage = phy_select_page(phydev, ACX00_PAGE_9);
+ if (oldpage < 0)
+ return phy_restore_page(phydev, oldpage, oldpage);
+
+ for (i = 0; i < ACX00_NUM_STATS; i++) {
+ ret = acx00_ephy_read_counter(phydev, acx00_ephy_stat_regs[i],
+ &counts[i]);
+ if (ret)
+ break;
+ }
+ ret = phy_restore_page(phydev, oldpage, ret);
+ if (ret < 0)
+ return ret;
+
+ /* Skip unusable samples without turning a statistics miss into a link error. */
+ if (ret || counts[ACX00_STAT_RX_BYTES] >= ACX00_RX_BYTES_WRAP)
+ return 0;
+
+ /* Include sleep and read time; complete unseen cycles cannot be recovered. */
+ if (priv->stats_valid &&
+ ktime_ms_delta(ktime_get_boottime(), priv->stats_start) >=
+ (s64)ACX00_STATS_MAX_INTERVAL_MS)
+ priv->stats_valid = false;
+
+ for (i = 0; i < ACX00_NUM_STATS; i++) {
+ u64 count = counts[i];
+
+ if (priv->stats_valid) {
+ if (count < priv->stats_last[i])
+ count += i == ACX00_STAT_RX_BYTES ?
+ ACX00_RX_BYTES_WRAP : BIT_ULL(32);
+ priv->stats[i] += count - priv->stats_last[i];
+ }
+ priv->stats_last[i] = counts[i];
+ }
+ priv->stats_valid = true;
+ priv->stats_start = start;
+
+ return 0;
+}
+
+static int acx00_ephy_update_stats(struct phy_device *phydev)
+{
+ struct acx00_ephy_priv *priv = phydev->priv;
+ int ret;
+
+ mutex_lock(&priv->state_lock);
+ ret = __acx00_ephy_update_stats(phydev);
+ mutex_unlock(&priv->state_lock);
+
+ return ret;
+}
+
+static void acx00_ephy_get_phy_stats(struct phy_device *phydev,
+ struct ethtool_eth_phy_stats *eth_stats,
+ struct ethtool_phy_stats *stats)
+{
+ struct acx00_ephy_priv *priv = phydev->priv;
+
+ mutex_lock(&priv->state_lock);
+ stats->rx_packets_total = priv->stats[ACX00_STAT_RX_PACKETS];
+ stats->rx_bytes_total = priv->stats[ACX00_STAT_RX_BYTES];
+ stats->rx_errors = priv->stats[ACX00_STAT_RX_CRC_ERRORS];
+ mutex_unlock(&priv->state_lock);
+}
+
+static void acx00_ephy_snapshot_stats(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Statistics collection must not prevent reset or power management. */
+ ret = __acx00_ephy_update_stats(phydev);
+ if (ret)
+ phydev_dbg(phydev, "failed to snapshot statistics: %pe\n", ERR_PTR(ret));
+}
+
static int acx00_ephy_control_power_on(struct acx00_ephy_priv *priv)
{
lockdep_assert_held(&priv->state_lock);
@@ -122,6 +274,10 @@ static int acx00_ephy_control_power_off(struct acx00_ephy_priv *priv)
{
lockdep_assert_held(&priv->state_lock);
+ /* Even a failed power-off can have reset the hardware counter. */
+ priv->stats_active = false;
+ priv->stats_valid = false;
+
return priv->control->power_off(priv->control);
}
@@ -350,6 +506,10 @@ static int acx00_ephy_soft_reset(struct phy_device *phydev)
mutex_lock(&priv->state_lock);
+ /* phylib may already have reset the counters before calling us. */
+ priv->stats_active = false;
+ priv->stats_valid = false;
+
ret = acx00_ephy_set_interface(phydev);
if (ret)
goto out_power_off;
@@ -475,10 +635,21 @@ static int __acx00_ephy_config_init(struct phy_device *phydev)
/* Restore the standard EEE policy retained by phylib across resets. */
ret = genphy_c45_an_config_eee_aneg(phydev);
- if (ret <= 0)
+ if (ret < 0)
return ret;
+ if (ret > 0) {
+ ret = genphy_restart_aneg(phydev);
+ if (ret)
+ return ret;
+ }
- return genphy_restart_aneg(phydev);
+ if (!priv->stats_active) {
+ /* Establish a new baseline after reset, retaining the software total. */
+ priv->stats_active = true;
+ acx00_ephy_snapshot_stats(phydev);
+ }
+
+ return 0;
}
static int acx00_ephy_config_init(struct phy_device *phydev)
@@ -534,6 +705,9 @@ static int acx00_ephy_resume(struct phy_device *phydev)
int ret;
mutex_lock(&priv->state_lock);
+ /* WoL can keep the PHY counting while phylib polling is stopped. */
+ priv->stats_active = false;
+ priv->stats_valid = false;
ret = __acx00_ephy_power_on_and_resume(phydev);
mutex_unlock(&priv->state_lock);
@@ -550,6 +724,8 @@ static int acx00_ephy_suspend(struct phy_device *phydev)
mutex_lock(&phydev->lock);
mutex_lock(&priv->state_lock);
+ acx00_ephy_snapshot_stats(phydev);
+
ret = genphy_suspend(phydev);
if (ret)
goto out_unlock;
@@ -616,6 +792,8 @@ static struct phy_driver acx00_ephy_driver[] = {
.soft_reset = acx00_ephy_soft_reset,
.config_init = acx00_ephy_config_init,
.disable_autonomous_eee = acx00_ephy_disable_autonomous_eee,
+ .get_phy_stats = acx00_ephy_get_phy_stats,
+ .update_stats = acx00_ephy_update_stats,
.suspend = acx00_ephy_suspend,
.resume = acx00_ephy_resume,
},
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next v4 3/3] net: phy: dp83tg720: report inclusive RX packet totals
2026-11-13 17:12 [PATCH net-next v4 0/3] ethtool: expose PHY receive totals James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 1/3] ethtool: add PHY receive frame and byte totals James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 2/3] net: phy: acx00: report receive statistics James Hilliard
@ 2026-11-13 17:12 ` James Hilliard
2026-11-13 21:39 ` Oleksij Rempel
2 siblings, 1 reply; 6+ messages in thread
From: James Hilliard @ 2026-11-13 17:12 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Jonathan Corbet, Shuah Khan, Randy Dunlap
Cc: Oleksij Rempel, netdev, linux-kernel, linux-doc, James Hilliard,
stable+noautosel
The DP83TG720S-Q1 datasheet describes PKT_STAT_4 and PKT_STAT_5
(0x063c and 0x063d) as the total received packet count, including packets
with errors. The driver currently reports this count through rx_packets,
which is defined as successfully received packets.
Report the accumulated count through rx_packets_total instead. This
exposes it as RxFramesTotal rather than RxFrames in the ethtool phydev
statistics group, matching the hardware counter's semantics.
Fixes: 677d895af1cc ("net: phy: dp83tg720: add statistics support")
Link: https://www.ti.com/lit/ds/symlink/dp83tg720s-q1.pdf
Cc: <stable+noautosel@kernel.org> # Requires the new PHY receive-total statistics API
Cc: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/net/phy/dp83tg720.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/dp83tg720.c b/drivers/net/phy/dp83tg720.c
index 807ff5525ecd..6c0c8c6007e6 100644
--- a/drivers/net/phy/dp83tg720.c
+++ b/drivers/net/phy/dp83tg720.c
@@ -309,7 +309,7 @@ static void dp83tg720_get_phy_stats(struct phy_device *phydev,
stats->tx_packets = priv->stats.tx_pkt_cnt;
stats->tx_errors = priv->stats.tx_err_pkt_cnt;
- stats->rx_packets = priv->stats.rx_pkt_cnt;
+ stats->rx_packets_total = priv->stats.rx_pkt_cnt;
stats->rx_errors = priv->stats.rx_err_pkt_cnt;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net-next v4 1/3] ethtool: add PHY receive frame and byte totals
2026-11-13 17:12 ` [PATCH net-next v4 1/3] ethtool: add PHY receive frame and byte totals James Hilliard
@ 2026-11-13 20:55 ` Andrew Lunn
0 siblings, 0 replies; 6+ messages in thread
From: Andrew Lunn @ 2026-11-13 20:55 UTC (permalink / raw)
To: James Hilliard
Cc: Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Oleksij Rempel, netdev, linux-kernel,
linux-doc
> Correct the documented group name to
> phydev, matching the existing name exported by the kernel.
> +++ b/Documentation/networking/ethtool-netlink.rst
> @@ -1665,7 +1665,7 @@ the ``ETHTOOL_A_STATS_GROUPS`` bitset. Currently defined values are:
> ETHTOOL_STATS_ETH_PHY eth-phy Basic IEEE 802.3 PHY statistics (30.3.2.1.*)
> ETHTOOL_STATS_ETH_CTRL eth-ctrl Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*)
> ETHTOOL_STATS_RMON rmon RMON (RFC 2819) statistics
> - ETHTOOL_STATS_PHY phy Additional PHY statistics, not defined by IEEE
> + ETHTOOL_STATS_PHY phydev Additional PHY statistics, not defined by IEEE
> ====================== ======== ===============================================
>
> Each group should have a corresponding ``ETHTOOL_A_STATS_GRP`` in the reply.
This should be a patch of its own. That would of forced you to write a
useful commit message, and i would not of needed to ask why it
changed.
You want lots of small patches, with good commit messages, which are
obviously correct.
I suggest you spend some time reviewing other developers patches. See
it from the other side.
Andrew
---
pw-bot: cr
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next v4 3/3] net: phy: dp83tg720: report inclusive RX packet totals
2026-11-13 17:12 ` [PATCH net-next v4 3/3] net: phy: dp83tg720: report inclusive RX packet totals James Hilliard
@ 2026-11-13 21:39 ` Oleksij Rempel
0 siblings, 0 replies; 6+ messages in thread
From: Oleksij Rempel @ 2026-11-13 21:39 UTC (permalink / raw)
To: James Hilliard
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Jonathan Corbet, Shuah Khan, Randy Dunlap, netdev, linux-kernel,
linux-doc, stable+noautosel
On Fri, Nov 13, 2026 at 10:12:07AM -0700, James Hilliard wrote:
> The DP83TG720S-Q1 datasheet describes PKT_STAT_4 and PKT_STAT_5
> (0x063c and 0x063d) as the total received packet count, including packets
> with errors. The driver currently reports this count through rx_packets,
> which is defined as successfully received packets.
>
> Report the accumulated count through rx_packets_total instead. This
> exposes it as RxFramesTotal rather than RxFrames in the ethtool phydev
> statistics group, matching the hardware counter's semantics.
>
> Fixes: 677d895af1cc ("net: phy: dp83tg720: add statistics support")
> Link: https://www.ti.com/lit/ds/symlink/dp83tg720s-q1.pdf
> Cc: <stable+noautosel@kernel.org> # Requires the new PHY receive-total statistics API
> Cc: Oleksij Rempel <o.rempel@pengutronix.de>
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
I do not think this patch should go in. Please drop it from the series.
Patches 1 and 2 do not depend on it; dp83tg720 can keep reporting
rx_packets as it does today.
The datasheet (SNLS604G) does not say that this count includes frames
with errors. Tables 7-80 and 7-81 describe the fields only as the lower
and upper 16 bits of the Rx packet counter. Section 6.3.1.3 and Table 6-2
list a total packet count and a count of packets with errors. They do
not say whether the total includes those packets. The word "total" alone
does not settle it.
Before the reported value changes, I need either a test or other TI
documentation that shows whether the counter includes frames with
CRC errors.
Even if it turns out that the counter includes frames with CRC errors, I
would rather subtract the CRC error count (RxErrors) in the driver and
keep rx_packets with its documented meaning than change the interface
for existing users.
Oleksij
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-11-13 21:39 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13 17:12 [PATCH net-next v4 0/3] ethtool: expose PHY receive totals James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 1/3] ethtool: add PHY receive frame and byte totals James Hilliard
2026-11-13 20:55 ` Andrew Lunn
2026-11-13 17:12 ` [PATCH net-next v4 2/3] net: phy: acx00: report receive statistics James Hilliard
2026-11-13 17:12 ` [PATCH net-next v4 3/3] net: phy: dp83tg720: report inclusive RX packet totals James Hilliard
2026-11-13 21:39 ` Oleksij Rempel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox