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
This commit is contained in:
Andrew Turner committed 2026-09-18 12:29:19 +01:00
1 parent 0689a5ea45
commit 50e01b6351
3 files changed
+14 -4

No files matched your search

+8 -4
View File
@@ -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) {
+2
View File
@@ -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,
+4
View File
@@ -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;