[PATCH v4 11/15] iommu/arm-smmu-v3: Discard partial PRI faults on PRIQ overflow

From: Nicolin Chen

Date: Thu Sep 10 2026 - 19:24:15 EST


On PRIQ overflow, partial requests stored via report_partial_fault() whose
LAST-page entry was lost stay in iopf_param->partial. Drop them by calling
iopf_queue_discard_partial(), matching intel-iommu's handling.

Do it only after the queue is fully drained, since the visible entries all
precede the loss point: a group whose LAST-page entry is still in the queue
gets assembled before the discard, rather than losing its stored partials
to it.

Nothing can arrive in between, as an active overflow inhibits new entries
from being written to the PRI queue until a final CONS write acknowledges
it (IHI0070 8.1).

Suggested-by: Harsha Vardhan V <harsha.v@xxxxxxxxxxxxxxxx>
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index c631c6344685d..0a15556c9a558 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2441,15 +2441,27 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
struct arm_smmu_queue *q = &smmu->priq.q;
struct arm_smmu_ll_queue *llq = &q->llq;
u64 evt[PRIQ_ENT_DWORDS];
+ bool overflow = false;

do {
while (!queue_remove_raw(q, evt))
arm_smmu_handle_ppr(smmu, evt);

- if (queue_sync_prod_in(q) == -EOVERFLOW)
+ if (queue_sync_prod_in(q) == -EOVERFLOW) {
dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n");
+ overflow = true;
+ }
} while (!queue_empty(llq));

+ /*
+ * Discard the partial faults after the drain, so any group with its
+ * LAST-page entry visible in the queue gets assembled beforehand. An
+ * active overflow condition inhibits new entries from being written
+ * to the PRI queue, until it gets acknowledged below.
+ */
+ if (overflow)
+ iopf_queue_discard_partial(smmu->evtq.iopf);
+
/* Sync our overflow flag, as we believe we're up to speed */
queue_sync_cons_ovf(q);
return IRQ_HANDLED;
--
2.43.0