From: Eric Joyner <eric.joyner@amd.com>
To: <netdev@vger.kernel.org>
Cc: Brett Creeley <brett.creeley@amd.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
"Eric Dumazet" <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
"Nikhil P . Rao" <nikhil.rao@amd.com>,
Eric Joyner <eric.joyner@amd.com>
Subject: [PATCH net-next] ionic: Add .get_fec_stats ethtool handler
Date: Fri, 31 Jul 2026 14:40:21 -0700 [thread overview]
Message-ID: <20260731214021.15279-1-eric.joyner@amd.com> (raw)
Reports FEC statistics totals and an 802.3ck FEC histogram. Per-lane counts
currently aren't supported, and the only expected histogram format from
firmware is the one with 16 bins from RS(544,514) FEC.
These are physical port counters, so virtual functions are skipped the
same way ionic_get_link_ext_stats() skips them, rather than reporting the
port's counters as if they belonged to the VF.
The reporting of these statistics is gated by DEV_CAP_EXTRA_STATS and
checks for IONIC_STAT_INVALID, since only the newest devices support
reporting all of these stats. Older devices can only report some of the
statistics or not at all, and so the output will properly exclude those
unsupported statistics.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Eric Joyner <eric.joyner@amd.com>
---
v1: This is an updated version of the last patch that was not applied in
the series "ionic: Add .get_fec_stats ethtool handler", see:
https://lore.kernel.org/netdev/20260615182732.7d28e31a@kernel.org/
.../ethernet/pensando/ionic/ionic_ethtool.c | 85 +++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
index c4ab4b5caa0a..0d4bd49cf935 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -441,6 +441,90 @@ static int ionic_get_fecparam(struct net_device *netdev,
return 0;
}
+#define IONIC_FEC_STAT(dst, src) \
+ do { \
+ __le64 __val = (src); \
+ \
+ if (__val != IONIC_STAT_INVALID) \
+ (dst) = le64_to_cpu(__val); \
+ } while (0)
+
+static const struct ethtool_fec_hist_range ionic_fec_hist_ranges[] = {
+ { 0, 0},
+ { 1, 1},
+ { 2, 2},
+ { 3, 3},
+ { 4, 4},
+ { 5, 5},
+ { 6, 6},
+ { 7, 7},
+ { 8, 8},
+ { 9, 9},
+ { 10, 10},
+ { 11, 11},
+ { 12, 12},
+ { 13, 13},
+ { 14, 14},
+ { 15, 15},
+ { 0, 0},
+};
+
+static void
+ionic_fill_fec_hist(const struct ionic_port_extra_stats *port_extra_stats,
+ struct ethtool_fec_hist *hist)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(port_extra_stats->fec_codeword_error_bin); i++) {
+ if (port_extra_stats->fec_codeword_error_bin[i] == IONIC_STAT_INVALID)
+ return;
+
+ hist->values[i].sum =
+ le64_to_cpu(port_extra_stats->fec_codeword_error_bin[i]);
+ }
+
+ hist->ranges = ionic_fec_hist_ranges;
+}
+
+static void ionic_get_fec_stats(struct net_device *netdev,
+ struct ethtool_fec_stats *fec_stats,
+ struct ethtool_fec_hist *hist)
+{
+ struct ionic_port_extra_stats port_extra_stats;
+ struct ionic_lif *lif = netdev_priv(netdev);
+ struct ionic_port_info *port_info;
+
+ if (lif->ionic->pdev->is_virtfn)
+ return;
+
+ if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
+ return;
+
+ if (!(lif->ionic->ident.dev.capabilities &
+ cpu_to_le64(IONIC_DEV_CAP_EXTRA_STATS)))
+ return;
+
+ port_info = lif->ionic->idev.port_info;
+ if (!port_info) {
+ netdev_err_once(netdev, "port_info not initialized\n");
+ return;
+ }
+
+ if (port_info->config.fec_type != IONIC_PORT_FEC_TYPE_RS)
+ return;
+
+ port_extra_stats = port_info->extra_stats;
+
+ IONIC_FEC_STAT(fec_stats->corrected_blocks.total,
+ port_extra_stats.rsfec_correctable_blocks);
+ IONIC_FEC_STAT(fec_stats->uncorrectable_blocks.total,
+ port_extra_stats.rsfec_uncorrectable_blocks);
+ IONIC_FEC_STAT(fec_stats->corrected_bits.total,
+ port_extra_stats.fec_corrected_bits_total);
+
+ ionic_fill_fec_hist(&port_extra_stats, hist);
+}
+
static int ionic_set_fecparam(struct net_device *netdev,
struct ethtool_fecparam *fec)
{
@@ -1177,6 +1261,7 @@ static const struct ethtool_ops ionic_ethtool_ops = {
.get_module_eeprom_by_page = ionic_get_module_eeprom_by_page,
.get_pauseparam = ionic_get_pauseparam,
.set_pauseparam = ionic_set_pauseparam,
+ .get_fec_stats = ionic_get_fec_stats,
.get_fecparam = ionic_get_fecparam,
.set_fecparam = ionic_set_fecparam,
.get_ts_info = ionic_get_ts_info,
base-commit: 2fbade66245059c78daeaccfce13ecf499fffb51
--
2.17.1
reply other threads:[~2026-07-31 21:40 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260731214021.15279-1-eric.joyner@amd.com \
--to=eric.joyner@amd.com \
--cc=andrew+netdev@lunn.ch \
--cc=brett.creeley@amd.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nikhil.rao@amd.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox