git: cee4fc7cada8 - main - cxgbe: Use secq(9) to manage the timestamp generations.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Mon, 26 Sep 2022 22:10:42 UTC
The branch main has been updated by jhb:

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

commit cee4fc7cada8244f375a6542f03d1f255c719bf1
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-09-26 21:58:06 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-09-26 21:58:41 +0000

    cxgbe: Use secq(9) to manage the timestamp generations.
    
    This is mostly cosmetic, but it also doesn't leave a gap of time where
    no structures are valid.  Instead, we permit the ISR to continue to
    use the previous structure if the write to update cal_current isn't
    yet visible.
    
    Reviewed by:    gallatin
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D36669
---
 sys/dev/cxgbe/adapter.h |  3 ++-
 sys/dev/cxgbe/t4_main.c | 28 +++++++++++++++++-----------
 sys/dev/cxgbe/t4_sge.c  | 11 ++++++-----
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 9312549cf7ba..c62ada5b9225 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -41,6 +41,7 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/rwlock.h>
+#include <sys/seqc.h>
 #include <sys/sx.h>
 #include <sys/vmem.h>
 #include <vm/uma.h>
@@ -871,7 +872,7 @@ struct clock_sync {
 	uint64_t hw_prev;
 	sbintime_t sbt_cur;
 	sbintime_t sbt_prev;
-	uint32_t gen;
+	seqc_t gen;
 };
 
 struct adapter {
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 9f982ca32097..25d9831c2019 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -1114,35 +1114,41 @@ t4_calibration(void *arg)
 {
 	struct adapter *sc;
 	struct clock_sync *cur, *nex;
+	uint64_t hw;
+	sbintime_t sbt;
 	int next_up;
 
 	sc = (struct adapter *)arg;
 
+	KASSERT((hw_off_limits(sc) == 0), ("hw_off_limits at t4_calibration"));
+	hw = t4_read_reg64(sc, A_SGE_TIMESTAMP_LO);
+	sbt = sbinuptime();
+
 	cur = &sc->cal_info[sc->cal_current];
 	next_up = (sc->cal_current + 1) % CNT_CAL_INFO;
        	nex = &sc->cal_info[next_up];
 	if (__predict_false(sc->cal_count == 0)) {
 		/* First time in, just get the values in */
-		cur->hw_cur = t4_read_reg64(sc, A_SGE_TIMESTAMP_LO);
-		cur->sbt_cur = sbinuptime();
+		cur->hw_cur = hw;
+		cur->sbt_cur = sbt;
 		sc->cal_count++;
 		goto done;
 	}
-	nex->hw_prev = cur->hw_cur;
-	nex->sbt_prev = cur->sbt_cur;
-	KASSERT((hw_off_limits(sc) == 0), ("hw_off_limits at t4_calibration"));
-	nex->hw_cur = t4_read_reg64(sc, A_SGE_TIMESTAMP_LO);
-	nex->sbt_cur = sbinuptime();
-	if ((nex->hw_cur - nex->hw_prev) == 0) {
+
+	if (cur->hw_cur == hw) {
 		/* The clock is not advancing? */
 		sc->cal_count = 0;
 		atomic_store_rel_int(&cur->gen, 0);
 		goto done;
 	}
-	atomic_store_rel_int(&cur->gen, 0);
+
+	seqc_write_begin(&nex->gen);
+	nex->hw_prev = cur->hw_cur;
+	nex->sbt_prev = cur->sbt_cur;
+	nex->hw_cur = hw;
+	nex->sbt_cur = sbt;
+	seqc_write_end(&nex->gen);
 	sc->cal_current = next_up;
-	sc->cal_gen++;
-	atomic_store_rel_int(&nex->gen, sc->cal_gen);
 done:
 	callout_reset_sbt_curcpu(&sc->cal_callout, SBT_1S, 0, t4_calibration,
 	    sc, C_DIRECT_EXEC);
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 161a753cc4ee..954e8f58e3e9 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -1530,16 +1530,17 @@ t4_tstmp_to_ns(struct adapter *sc, uint64_t lf)
 	uint64_t hw_clk_div;
 	sbintime_t sbt_cur_to_prev, sbt;
 	uint64_t hw_tstmp = lf & 0xfffffffffffffffULL;	/* 60b, not 64b. */
-	uint32_t gen;
+	seqc_t gen;
 
-	do {
+	for (;;) {
 		cur = &sc->cal_info[sc->cal_current];
-		gen = atomic_load_acq_int(&cur->gen);
+		gen = seqc_read(&cur->gen);
 		if (gen == 0)
 			return (0);
 		dcur = *cur;
-		atomic_thread_fence_acq();
-	} while (gen != dcur.gen);
+		if (seqc_consistent(&cur->gen, gen))
+			break;
+	}
 
 	/*
 	 * Our goal here is to have a result that is: