git: 50e01b6351b1 - main - arm64/smmu: Only MSI poll when cache-coherent
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 21 Sep 2026 15:26:11 UTC
The branch main has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=50e01b6351b1a4955814cce021852c65a5b5bb9f
commit 50e01b6351b1a4955814cce021852c65a5b5bb9f
Author: Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2026-09-18 11:29:19 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-09-18 11:29:19 +0000
arm64/smmu: Only MSI poll when cache-coherent
Only use the MSI polling method when we support MSIs and the SMMU is
cache-coherent.
The SMMU writes to a memory location. If it is not cache-coherent then
the CPU may read the existing value in its cache and miss the signal
the sync operation has completed.
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D59489
---
sys/arm64/iommu/smmu.c | 12 ++++++++----
sys/arm64/iommu/smmu_fdt.c | 2 ++
sys/arm64/iommu/smmuvar.h | 4 ++++
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/sys/arm64/iommu/smmu.c b/sys/arm64/iommu/smmu.c
index 930c97a8aeb3..2b95d2f5fb3c 100644
--- a/sys/arm64/iommu/smmu.c
+++ b/sys/arm64/iommu/smmu.c
@@ -623,20 +623,23 @@ smmu_sync(struct smmu_softc *sc)
struct smmu_cmdq_entry cmd;
struct smmu_queue *q;
int prod;
+ bool msipoll;
q = &sc->cmdq;
prod = q->lc.prod;
+ msipoll = ((sc->options & SMMU_OPT_MSIPOLL) != 0);
+
/* Enqueue sync command. */
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = CMD_SYNC;
- if ((sc->features & SMMU_FEATURE_MSI) != 0) {
+ if (msipoll) {
cmd.sync.msiaddr = q->paddr +
Q_IDX(q, prod) * CMDQ_ENTRY_DWORDS * 8;
}
smmu_cmdq_enqueue_cmd(sc, &cmd);
- if ((sc->features & SMMU_FEATURE_MSI) != 0)
+ if (msipoll)
smmu_sync_wait_msi(sc, q);
else
smmu_sync_wait_poll(sc, q);
@@ -1356,8 +1359,6 @@ smmu_check_features(struct smmu_softc *sc)
uint32_t reg;
uint32_t val;
- sc->features = 0;
-
reg = bus_read_4(sc->res[0], SMMU_IDR0);
if (reg & IDR0_ST_LVL_2) {
@@ -1404,6 +1405,9 @@ smmu_check_features(struct smmu_softc *sc)
if (bootverbose)
device_printf(sc->dev, "MSI feature present.\n");
sc->features |= SMMU_FEATURE_MSI;
+ /* Support polling if we support MSI & are cache-coherent */
+ if ((sc->features & SMMU_FEATURE_COHERENCY) != 0)
+ sc->options |= SMMU_OPT_MSIPOLL;
}
if (reg & IDR0_HYP) {
diff --git a/sys/arm64/iommu/smmu_fdt.c b/sys/arm64/iommu/smmu_fdt.c
index 31105054ddb2..0bd512a47d6f 100644
--- a/sys/arm64/iommu/smmu_fdt.c
+++ b/sys/arm64/iommu/smmu_fdt.c
@@ -87,6 +87,8 @@ smmu_fdt_attach(device_t dev)
sc->dev = dev;
node = ofw_bus_get_node(dev);
+ if (OF_hasprop(node, "dma-coherent"))
+ sc->features |= SMMU_FEATURE_COHERENCY;
rid = 0;
sc->res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
diff --git a/sys/arm64/iommu/smmuvar.h b/sys/arm64/iommu/smmuvar.h
index 60fad8f87531..e517e3e88ac1 100644
--- a/sys/arm64/iommu/smmuvar.h
+++ b/sys/arm64/iommu/smmuvar.h
@@ -160,6 +160,10 @@ struct smmu_softc {
#define SMMU_FEATURE_VAX (1 << 13)
#define SMMU_FEATURE_COHERENCY (1 << 14)
#define SMMU_FEATURE_RANGE_INV (1 << 15)
+
+ uint32_t options;
+#define SMMU_OPT_MSIPOLL (1 << 0)
+
struct smmu_queue cmdq;
struct smmu_queue evtq;
struct smmu_queue priq;