git: 7393d37b1224 - stable/13 - ntb_hw_plx: Workaround read-only scratchpad registers

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Mon, 05 Feb 2024 20:41:20 UTC
The branch stable/13 has been updated by mav:

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

commit 7393d37b12249aa26b0336136790cbcb33b690c2
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2024-01-27 21:51:46 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2024-02-05 20:39:58 +0000

    ntb_hw_plx: Workaround read-only scratchpad registers
    
    On several systems we've noticed that when NTB link goes down, the
    Physical Layer User Test Pattern registers we use as additional
    scratchpad registers (that is explicitly allowed by the chip specs)
    become read-only for about 100us.  I see no explanation for this in
    the chip specs, neither why it was not seen before, may be a race.
    Since we do need these registers, workaround it by repeating writes
    until we succeed or 1ms timeout expire.
    
    MFC after:      1 week
    
    (cherry picked from commit 3883c6fbf232452098ba6ea802ef1426d83d2d68)
---
 sys/dev/ntb/ntb.h               |  2 +-
 sys/dev/ntb/ntb_hw/ntb_hw_plx.c | 26 +++++++++++++++++++++-----
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/sys/dev/ntb/ntb.h b/sys/dev/ntb/ntb.h
index 61dc2cac5faf..f5f85815103e 100644
--- a/sys/dev/ntb/ntb.h
+++ b/sys/dev/ntb/ntb.h
@@ -281,7 +281,7 @@ int ntb_mw_set_wc(device_t ntb, unsigned mw_idx, vm_memattr_t mode);
 uint8_t ntb_spad_count(device_t ntb);
 
 /*
- * ntb_get_max_spads() - zero local scratch registers
+ * ntb_spad_clear() - zero local scratch registers
  * @ntb: pointer to ntb_softc instance
  *
  * This functions overwrites all local scratchpad registers with zeroes.
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c
index 535a6f489e40..0e48903ad7b9 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c
+++ b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c
@@ -880,17 +880,33 @@ static int
 ntb_plx_spad_write(device_t dev, unsigned int idx, uint32_t val)
 {
 	struct ntb_plx_softc *sc = device_get_softc(dev);
-	u_int off;
+	u_int off, t;
 
 	if (idx >= sc->spad_count1 + sc->spad_count2)
 		return (EINVAL);
 
-	if (idx < sc->spad_count1)
+	if (idx < sc->spad_count1) {
 		off = sc->spad_off1 + idx * 4;
-	else
+		bus_write_4(sc->conf_res, off, val);
+		return (0);
+	} else {
 		off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
-	bus_write_4(sc->conf_res, off, val);
-	return (0);
+		/*
+		 * For some reason when link goes down Test Pattern registers
+		 * we use as additional scratchpad become read-only for about
+		 * 100us.  I see no explanation in specs, so just wait a bit.
+		 */
+		for (t = 0; t <= 1000; t++) {
+			bus_write_4(sc->conf_res, off, val);
+			if (bus_read_4(sc->conf_res, off) == val)
+				return (0);
+			DELAY(1);
+		}
+		device_printf(dev,
+		    "Can't write Physical Layer User Test Pattern (0x%x)\n",
+		    off);
+		return (EIO);
+	}
 }
 
 static void