git: 54393bf5361a - main - arm64/smmu: Split out waiting for sync completion
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 21 Sep 2026 15:26:09 UTC
The branch main has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=54393bf5361a653c530170da20323181e515d7a1
commit 54393bf5361a653c530170da20323181e515d7a1
Author: Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2026-09-18 11:28:51 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-09-18 11:28:51 +0000
arm64/smmu: Split out waiting for sync completion
In preparation for adding a non-MSI method split out waiting for sync
completions from smmu_sync.
While here fix the loop to wait for sync timeout to the worst case
Linux uses.
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D59487
---
sys/arm64/iommu/smmu.c | 49 +++++++++++++++++++++++++++----------------------
1 file changed, 27 insertions(+), 22 deletions(-)
diff --git a/sys/arm64/iommu/smmu.c b/sys/arm64/iommu/smmu.c
index 38cdd507a9c2..d5f79c9a2801 100644
--- a/sys/arm64/iommu/smmu.c
+++ b/sys/arm64/iommu/smmu.c
@@ -567,43 +567,48 @@ smmu_poll_until_consumed(struct smmu_softc *sc, struct smmu_queue *q)
}
}
-static int
-smmu_sync(struct smmu_softc *sc)
+static void
+smmu_sync_wait_msi(struct smmu_softc *sc, struct smmu_queue *q)
{
- struct smmu_cmdq_entry cmd;
- struct smmu_queue *q;
+ sbintime_t start;
uint32_t *base;
- int timeout;
int prod;
- q = &sc->cmdq;
prod = q->lc.prod;
- /* Enqueue sync command. */
- cmd.opcode = CMD_SYNC;
- cmd.sync.msiaddr = q->paddr + Q_IDX(q, prod) * CMDQ_ENTRY_DWORDS * 8;
- smmu_cmdq_enqueue_cmd(sc, &cmd);
-
/* Wait for the sync completion. */
base = (void *)((uint64_t)q->vaddr +
Q_IDX(q, prod) * CMDQ_ENTRY_DWORDS * 8);
- /*
- * It takes around 200 loops (6 instructions each)
- * on Neoverse N1 to complete the sync.
- */
- timeout = 10000;
-
+ start = getsbinuptime();
do {
- if (*base == 0) {
+ if (atomic_load_32(base) == 0) {
/* MSI write completed. */
- break;
+ return;
}
- cpu_spinwait();
- } while (timeout--);
+ DELAY(100);
+ } while ((getsbinuptime() - start) < SBT_1S);
- if (timeout < 0)
+ if (atomic_load_32(base) != 0)
device_printf(sc->dev, "Failed to sync\n");
+}
+
+static int
+smmu_sync(struct smmu_softc *sc)
+{
+ struct smmu_cmdq_entry cmd;
+ struct smmu_queue *q;
+ int prod;
+
+ q = &sc->cmdq;
+ prod = q->lc.prod;
+
+ /* Enqueue sync command. */
+ cmd.opcode = CMD_SYNC;
+ cmd.sync.msiaddr = q->paddr + Q_IDX(q, prod) * CMDQ_ENTRY_DWORDS * 8;
+ smmu_cmdq_enqueue_cmd(sc, &cmd);
+
+ smmu_sync_wait_msi(sc, q);
return (0);
}