[PATCH v9 07/12] iommu/arm-smmu-v3: Add CMDQ_PROD_STOP_FLAG to gate CMDQ submissions
Pranjal Shrivastava
praan at google.com
Tue Aug 25 11:38:35 PDT 2026
On Tue, Aug 25, 2026 at 01:36:11PM -0300, Jason Gunthorpe wrote:
> > [ ... 52 lines skipped ... ]
> > while (!queue_has_space(&llq, n + sync)) {
> > local_irq_restore(flags);
> > +
> > + /* Avoid waiting for space if the SMMU is suspending */
> > + if (Q_STOP(READ_ONCE(cmdq->q.llq.prod)))
> > + return 0;
> > +
> > if (arm_smmu_cmdq_poll_until_not_full(smmu, cmdq, &llq))
> > dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
> > local_irq_save(flags);
>
> [Severity: Critical]
> Can this loop bypass the Q_STOP check if a suspend happens concurrently?
>
> If a thread enters the while loop because there's no space, and a concurrent
> task sets the CMDQ_PROD_STOP_FLAG while space becomes available:
>
> 1. arm_smmu_cmdq_poll_until_not_full() updates llq.val with the latest global
> state, which now includes the newly set STOP_FLAG in llq.prod.
> 2. The loop condition !queue_has_space(&llq, n + sync) now evaluates to false,
> causing the thread to exit the inner loop.
> 3. This bypasses the Q_STOP(READ_ONCE(cmdq->q.llq.prod)) check inside the
> loop, as well as the Q_STOP(llq.prod) check at the top of the do-while loop.
>
> The thread would then successfully cmpxchg the new producer index with the
> STOP_FLAG set.
>
> Make sense to me, having arm_smmu_cmdq_poll_until_not_full() reload
> the llq and then not loop again from the top skips the Q_STOP
> flag.
>
Right. I guess we should check the condition again after exiting the
loop or add the point of commitment to this space loop somehow. I'll
take care of this.
Thanks,
Praan
More information about the linux-arm-kernel
mailing list