[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