git: 3883c6fbf232 - main - ntb_hw_plx: Workaround read-only scratchpad registers
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 27 Jan 2024 22:29:06 UTC
The branch main has been updated by mav:
URL: https://cgit.FreeBSD.org/src/commit/?id=3883c6fbf232452098ba6ea802ef1426d83d2d68
commit 3883c6fbf232452098ba6ea802ef1426d83d2d68
Author: Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2024-01-27 21:51:46 +0000
Commit: Alexander Motin <mav@FreeBSD.org>
CommitDate: 2024-01-27 22:29:01 +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
---
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 f9119fa0aedc..e2af625fff94 100644
--- a/sys/dev/ntb/ntb.h
+++ b/sys/dev/ntb/ntb.h
@@ -279,7 +279,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 57e3265ee5b1..906660116067 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c
+++ b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c
@@ -879,17 +879,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