[PATCH] iommu/arm-smmu-v3: Acknowledge pri/event queue overflow if any

Tomas Krcka tomas.krcka at gmail.com
Thu Apr 6 01:13:23 PDT 2023


Am Mi., 29. März 2023 um 14:34 Uhr schrieb <tomas.krcka at gmail.com>:
>
> From: Tomas Krcka <krckatom at amazon.de>
>
> When an overflow occurs in the PRI queue, the SMMU toggles the overflow
> flag in the PROD register. To exit the overflow condition, the PRI thread
> is supposed to acknowledge it by toggling this flag in the CONS register.
> Unacknowledged overflow causes the queue to stop adding anything new.
>
> Currently, the priq thread always writes the CONS register back to the
> SMMU after clearing the queue.
>
> The writeback is not necessary if the OVFLG in the PROD register has not
> been changed, no overflow has occured.
>
> This commit checks the difference of the overflow flag between CONS and
> PROD register. If it's different, toggles the OVACKFLG flag in the CONS
> register and write it to the SMMU.
>
> The situation is similar for the event queue.
> The acknowledge register is also toggled after clearing the event
> queue but never propagated to the hardware. This would only be done the
> next time when executing evtq thread.
>
> Unacknowledged event queue overflow doesn't affect the event
> queue, because the SMMU still adds elements to that queue when the
> overflow condition is active.
> But it feel nicer to keep SMMU in sync when possible, so use the same
> way here as well.
>
> Signed-off-by: Tomas Krcka <krckatom at amazon.de>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 19 ++++++++++++++-----
>  1 file changed, 14 insertions(+), 5 deletions(-)
>
> 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 f2425b0f0cd6..7614739ea2c1 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -152,6 +152,18 @@ static void queue_inc_cons(struct arm_smmu_ll_queue *q)
>         q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
>  }
>
> +static void queue_sync_cons_ovf(struct arm_smmu_queue *q)
> +{
> +       struct arm_smmu_ll_queue *llq = &q->llq;
> +
> +       if (likely(Q_OVF(llq->prod) == Q_OVF(llq->cons)))
> +               return;
> +
> +       llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
> +                     Q_IDX(llq, llq->cons);
> +       queue_sync_cons_out(q);
> +}
> +
>  static int queue_sync_prod_in(struct arm_smmu_queue *q)
>  {
>         u32 prod;
> @@ -1577,8 +1589,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
>         } while (!queue_empty(llq));
>
>         /* Sync our overflow flag, as we believe we're up to speed */
> -       llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
> -                   Q_IDX(llq, llq->cons);
> +       queue_sync_cons_ovf(q);
>         return IRQ_HANDLED;
>  }
>
> @@ -1636,9 +1647,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
>         } while (!queue_empty(llq));
>
>         /* Sync our overflow flag, as we believe we're up to speed */
> -       llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
> -                     Q_IDX(llq, llq->cons);
> -       queue_sync_cons_out(q);
> +       queue_sync_cons_ovf(q);
>         return IRQ_HANDLED;
>  }
>
> --
> 2.39.2
>

ping for this patch ...



More information about the linux-arm-kernel mailing list