git: 2a139853129e - stable/13 - cxgbe(4): Fix illegal hardware access in cxgbe_refresh_stats.

From: Navdeep Parhar <np_at_FreeBSD.org>
Date: Mon, 28 Feb 2022 06:55:53 UTC
The branch stable/13 has been updated by np:

URL: https://cgit.FreeBSD.org/src/commit/?id=2a139853129e890e8291bb215b97fa41a41ef7ae

commit 2a139853129e890e8291bb215b97fa41a41ef7ae
Author:     Navdeep Parhar <np@FreeBSD.org>
AuthorDate: 2022-02-12 00:58:46 +0000
Commit:     Navdeep Parhar <np@FreeBSD.org>
CommitDate: 2022-02-28 06:51:51 +0000

    cxgbe(4): Fix illegal hardware access in cxgbe_refresh_stats.
    
    cxgbe_refresh_stats takes into account VI_SKIP_STATS but not
    VI_INIT_DONE when deciding whether to read the hardware stats.  But
    before this change VI_SKIP_STATS was set only for VIs with VI_INIT_DONE.
    That meant that cxgbe_refresh_stats always accessed the hardware for
    uninitialized VIs, and this is a problem if the adapter is suspended or
    in the middle of a reset.
    
    Fix this by setting VI_SKIP_STATS on all VIs during suspend.  While
    here, ignore VI_INIT_DONE in vi_refresh_stats too to be consistent with
    cxgbe_refresh_stats.
    
    Sponsored by:   Chelsio Communications
    
    (cherry picked from commit 08c7dc7fd4735b85e9696d0439af6cc98b23b25d)
---
 sys/dev/cxgbe/t4_main.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index e8f82e4aea3b..333373e69aea 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -1928,13 +1928,15 @@ t4_suspend(device_t dev)
 
 		for_each_vi(pi, j, vi) {
 			vi->xact_addr_filt = -1;
+			mtx_lock(&vi->tick_mtx);
+			vi->flags |= VI_SKIP_STATS;
+			mtx_unlock(&vi->tick_mtx);
 			if (!(vi->flags & VI_INIT_DONE))
 				continue;
 
 			ifp = vi->ifp;
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 				mtx_lock(&vi->tick_mtx);
-				vi->flags |= VI_SKIP_STATS;
 				callout_stop(&vi->tick);
 				mtx_unlock(&vi->tick_mtx);
 				callout_drain(&vi->tick);
@@ -2265,6 +2267,9 @@ t4_resume(device_t dev)
 		for_each_port(sc, i) {
 			pi = sc->port[i];
 			for_each_vi(pi, j, vi) {
+				mtx_lock(&vi->tick_mtx);
+				vi->flags &= ~VI_SKIP_STATS;
+				mtx_unlock(&vi->tick_mtx);
 				if (!(vi->flags & VI_INIT_DONE))
 					continue;
 				rc = vi_full_init(vi);
@@ -2301,7 +2306,6 @@ t4_resume(device_t dev)
 					TXQ_UNLOCK(txq);
 				}
 				mtx_lock(&vi->tick_mtx);
-				vi->flags &= ~VI_SKIP_STATS;
 				callout_schedule(&vi->tick, hz);
 				mtx_unlock(&vi->tick_mtx);
 			}
@@ -7081,7 +7085,7 @@ vi_refresh_stats(struct vi_info *vi)
 
 	mtx_assert(&vi->tick_mtx, MA_OWNED);
 
-	if (!(vi->flags & VI_INIT_DONE) || vi->flags & VI_SKIP_STATS)
+	if (vi->flags & VI_SKIP_STATS)
 		return;
 
 	getmicrotime(&tv);