Reports FEC statistics totals and an 802.3ck FEC histogram. Per-lane counts currently aren't supported. 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-4.6-sonnet Signed-off-by: Eric Joyner --- .../ethernet/pensando/ionic/ionic_ethtool.c | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c index 6069fa460913..41bb27669907 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -425,6 +425,77 @@ static int ionic_get_fecparam(struct net_device *netdev, return 0; } +static const struct ethtool_fec_hist_range ionic_fec_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}, +}; + +#define IONIC_FEC_STAT(dst, src) \ + do { \ + if ((src) != IONIC_STAT_INVALID) \ + (dst) = le64_to_cpu((src)); \ + } while (0) + +static void +ionic_fill_fec_hist(const struct ionic_port_extra_stats *port_extra_stats, + struct ethtool_fec_hist *hist) +{ + __le64 fec_cw_err_bin; + int i; + + if (port_extra_stats->fec_codeword_error_bin[0] == IONIC_STAT_INVALID) + return; + + hist->ranges = ionic_fec_ranges; + /* All bins in ranges must be set */ + for (i = 0; i < ARRAY_SIZE(ionic_fec_ranges) - 1; i++) { + fec_cw_err_bin = port_extra_stats->fec_codeword_error_bin[i]; + + if (fec_cw_err_bin != IONIC_STAT_INVALID) + hist->values[i].sum = le64_to_cpu(fec_cw_err_bin); + else + hist->values[i].sum = 0; + } +} + +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); + + if (!(lif->ionic->ident.dev.capabilities & + cpu_to_le64(IONIC_DEV_CAP_EXTRA_STATS))) + return; + + port_extra_stats = &lif->ionic->idev.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) { @@ -1161,6 +1232,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, -- 2.17.1