[PATCH v9 11/12] iommu/arm-smmu-v3: Invoke pm_runtime before hw access
Daniel Mentz
danielmentz at google.com
Sun Aug 30 14:11:10 PDT 2026
On Tue, Jul 28, 2026 at 2:10 PM Pranjal Shrivastava <praan at google.com> wrote:
> @@ -2386,6 +2407,34 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
> static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
> DEFAULT_RATELIMIT_BURST);
>
> + /*
> + * Use a non-sleeping get to avoid a circular dependency deadlock
> + * with arm_smmu_runtime_suspend().
> + *
> + * When using a combined_irq, the suspend thread waits for pending
> + * threaded handlers to complete. If the IRQ thread blocks waiting
> + * for the PM core, it creates a deadlock:
> + *
> + * [Suspend Thread] | [IRQ Thread]
> + * pm_runtime_suspend() |
> + * state = RPM_SUSPENDING; |
> + * | IRQ fires
> + * | arm_smmu_rpm_get()
> + * | sleeps (waiting for suspend)
> + * arm_smmu_runtime_suspend() |
> + * ... |
> + * synchronize_irq() |
> + * sleeps (waiting for IRQ) |
> + *
> + * <==== DEADLOCK ====>
> + *
> + * A non-sleeping get allows the thread to instantly drop the event
> + * if the device is suspending, safely bypassing the synchronize_irq()
> + * deadlock.
> + */
> + if (!arm_smmu_rpm_get_if_active(smmu))
> + return IRQ_NONE;
> +
> do {
> while (!queue_remove_raw(q, evt)) {
> arm_smmu_decode_event(smmu, evt, &event);
Sashiko has the following concern:
> Does returning IRQ_NONE here during transient PM states cause an interrupt
> storm or data loss?
> If the device is in a transient state (like RPM_SUSPENDING), this lockless
> check returns false and the thread aborts without acknowledging the hardware
> interrupt. For a level-triggered interrupt, this could cause an infinite
> interrupt storm since the line is unmasked on thread exit.
> Additionally, can aborting early here cause pending events to be permanently
> erased on resume?
> Because the thread aborts without updating the software llq.prod index via
> queue_sync_prod_in(), the stale pointer will be written back to the hardware
> EVTQ_PROD register during arm_smmu_device_reset() on resume.
I tend to agree with the concern about the stale producer index.
Should we call queue_sync_prod_in(&smmu->evtq.q) in
arm_smmu_runtime_suspend() after disabling the event queue? Also, how
about printing a warning and returning IRQ_HANDLED if
arm_smmu_rpm_get_if_active(smmu) returns false here?
More information about the linux-arm-kernel
mailing list