git: 54393bf5361a - main - arm64/smmu: Split out waiting for sync completion

From: Andrew Turner <andrew_at_FreeBSD.org>
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);
 }