aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2024-01-27 21:51:46 +0000
committerAlexander Motin <mav@FreeBSD.org>2024-02-05 20:39:58 +0000
commit7393d37b12249aa26b0336136790cbcb33b690c2 (patch)
tree429f422433b9d78206b2003e41573a4e434f4bc9
parent84d443825255575d1b036958049ffafe8a96c80d (diff)
downloadsrc-7393d37b12249aa26b0336136790cbcb33b690c2.tar.gz
src-7393d37b12249aa26b0336136790cbcb33b690c2.zip
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)
-rw-r--r--sys/dev/ntb/ntb.h2
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw_plx.c26
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