git: 0689a5ea451b - main - arm64/smmu: Support polling for sync completion
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 21 Sep 2026 15:26:10 UTC
The branch main has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=0689a5ea451bdef62f7e81ffb3e5f580c5c99b2b
commit 0689a5ea451bdef62f7e81ffb3e5f580c5c99b2b
Author: Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2026-09-18 11:29:02 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-09-18 11:29:02 +0000
arm64/smmu: Support polling for sync completion
When the hardware doesn't support MSIs we need to poll to wait for
sync operations to complete. Add support for this to support booting
on this hardware.
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D59488
---
sys/arm64/iommu/smmu.c | 39 +++++++++++++++++++++++++++++++++++----
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/sys/arm64/iommu/smmu.c b/sys/arm64/iommu/smmu.c
index d5f79c9a2801..930c97a8aeb3 100644
--- a/sys/arm64/iommu/smmu.c
+++ b/sys/arm64/iommu/smmu.c
@@ -245,7 +245,7 @@ smmu_q_empty(struct smmu_queue *q)
return (0);
}
-static int __unused
+static int
smmu_q_consumed(struct smmu_queue *q, uint32_t prod)
{
@@ -254,7 +254,7 @@ smmu_q_consumed(struct smmu_queue *q, uint32_t prod)
return (1);
if ((Q_WRP(q, q->lc.cons) != Q_WRP(q, prod)) &&
- (Q_IDX(q, q->lc.cons) <= Q_IDX(q, prod)))
+ (Q_IDX(q, q->lc.cons) < Q_IDX(q, prod)))
return (1);
return (0);
@@ -567,6 +567,30 @@ smmu_poll_until_consumed(struct smmu_softc *sc, struct smmu_queue *q)
}
}
+static void
+smmu_sync_wait_poll(struct smmu_softc *sc, struct smmu_queue *q)
+{
+ sbintime_t start;
+ int prod;
+
+ prod = q->lc.prod;
+
+ start = getsbinuptime();
+ do {
+ if (smmu_q_consumed(q, prod))
+ return;
+ if ((sc->features & SMMU_FEATURE_SEV) != 0)
+ wfe();
+ else
+ DELAY(100);
+
+ q->lc.cons = bus_read_4(sc->res[0], q->cons_off);
+ } while ((getsbinuptime() - start) < SBT_1S);
+
+ if (!smmu_q_consumed(q, prod))
+ device_printf(sc->dev, "Failed to sync\n");
+}
+
static void
smmu_sync_wait_msi(struct smmu_softc *sc, struct smmu_queue *q)
{
@@ -604,11 +628,18 @@ smmu_sync(struct smmu_softc *sc)
prod = q->lc.prod;
/* Enqueue sync command. */
+ memset(&cmd, 0, sizeof(cmd));
cmd.opcode = CMD_SYNC;
- cmd.sync.msiaddr = q->paddr + Q_IDX(q, prod) * CMDQ_ENTRY_DWORDS * 8;
+ if ((sc->features & SMMU_FEATURE_MSI) != 0) {
+ 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);
+ if ((sc->features & SMMU_FEATURE_MSI) != 0)
+ smmu_sync_wait_msi(sc, q);
+ else
+ smmu_sync_wait_poll(sc, q);
return (0);
}