diff options
| author | Erni Sri Satya Vennela <ernis@linux.microsoft.com> | 2025-11-14 03:43:19 -0800 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2025-11-17 19:52:30 -0800 |
| commit | be4f1d67ec56f23f37714ac73c01094e63c7ff28 (patch) | |
| tree | 09cb5279acdbd40378d0cc6b24181be65caae7cb /drivers/net/ethernet/microsoft/mana/mana_en.c | |
| parent | e275d9091c01b3b46f3ec534ce4ac77cffc9e3ae (diff) | |
net: mana: Add standard counter rx_missed_errors
Report standard counter stats->rx_missed_errors
using hc_rx_discards_no_wqe from the hardware.
Add a global workqueue to periodically run
mana_query_gf_stats every 2 seconds to get the latest
info in eth_stats and define a driver capability flag
to notify hardware of the periodic queries.
To avoid repeated failures and log flooding, the workqueue
is not rescheduled if mana_query_gf_stats fails on HWC timeout
error and the stats are reset to 0. Other errors are transient
which will not need a VF reset for recovery.
Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Link: https://patch.msgid.link/1763120599-6331-3-git-send-email-ernis@linux.microsoft.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/ethernet/microsoft/mana/mana_en.c')
| -rw-r--r-- | drivers/net/ethernet/microsoft/mana/mana_en.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index d8ce4402c696..13f47be7aca6 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -534,6 +534,11 @@ static void mana_get_stats64(struct net_device *ndev, netdev_stats_to_stats64(st, &ndev->stats); + if (apc->ac->hwc_timeout_occurred) + netdev_warn_once(ndev, "HWC timeout occurred\n"); + + st->rx_missed_errors = apc->ac->hc_stats.hc_rx_discards_no_wqe; + for (q = 0; q < num_queues; q++) { rx_stats = &apc->rxqs[q]->stats; @@ -2809,7 +2814,7 @@ int mana_config_rss(struct mana_port_context *apc, enum TRI_STATE rx, return 0; } -void mana_query_gf_stats(struct mana_context *ac) +int mana_query_gf_stats(struct mana_context *ac) { struct gdma_context *gc = ac->gdma_dev->gdma_context; struct mana_query_gf_stat_resp resp = {}; @@ -2852,14 +2857,14 @@ void mana_query_gf_stats(struct mana_context *ac) sizeof(resp)); if (err) { dev_err(dev, "Failed to query GF stats: %d\n", err); - return; + return err; } err = mana_verify_resp_hdr(&resp.hdr, MANA_QUERY_GF_STAT, sizeof(resp)); if (err || resp.hdr.status) { dev_err(dev, "Failed to query GF stats: %d, 0x%x\n", err, resp.hdr.status); - return; + return err; } ac->hc_stats.hc_rx_discards_no_wqe = resp.rx_discards_nowqe; @@ -2894,6 +2899,8 @@ void mana_query_gf_stats(struct mana_context *ac) ac->hc_stats.hc_tx_mcast_pkts = resp.hc_tx_mcast_pkts; ac->hc_stats.hc_tx_mcast_bytes = resp.hc_tx_mcast_bytes; ac->hc_stats.hc_tx_err_gdma = resp.tx_err_gdma; + + return 0; } void mana_query_phy_stats(struct mana_port_context *apc) @@ -3428,6 +3435,24 @@ int mana_rdma_service_event(struct gdma_context *gc, enum gdma_service_type even return 0; } +#define MANA_GF_STATS_PERIOD (2 * HZ) + +static void mana_gf_stats_work_handler(struct work_struct *work) +{ + struct mana_context *ac = + container_of(to_delayed_work(work), struct mana_context, gf_stats_work); + int err; + + err = mana_query_gf_stats(ac); + if (err == -ETIMEDOUT) { + /* HWC timeout detected - reset stats and stop rescheduling */ + ac->hwc_timeout_occurred = true; + memset(&ac->hc_stats, 0, sizeof(ac->hc_stats)); + return; + } + schedule_delayed_work(&ac->gf_stats_work, MANA_GF_STATS_PERIOD); +} + int mana_probe(struct gdma_dev *gd, bool resuming) { struct gdma_context *gc = gd->gdma_context; @@ -3520,6 +3545,10 @@ int mana_probe(struct gdma_dev *gd, bool resuming) } err = add_adev(gd, "eth"); + + INIT_DELAYED_WORK(&ac->gf_stats_work, mana_gf_stats_work_handler); + schedule_delayed_work(&ac->gf_stats_work, MANA_GF_STATS_PERIOD); + out: if (err) { mana_remove(gd, false); @@ -3544,6 +3573,7 @@ void mana_remove(struct gdma_dev *gd, bool suspending) int i; disable_work_sync(&ac->link_change_work); + cancel_delayed_work_sync(&ac->gf_stats_work); /* adev currently doesn't support suspending, always remove it */ if (gd->adev) |