Re: [PATCH] iommu/arm-smmu-v3: Acknowledge pri/event queue overflow if any
From: Tomas Krcka
Date: Thu Apr 06 2023 - 04:14:10 EST
Am Mi., 29. März 2023 um 14:34 Uhr schrieb <tomas.krcka@xxxxxxxxx>:
>
> From: Tomas Krcka <krckatom@xxxxxxxxx>
>
> 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@xxxxxxxxx>
> ---
> 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 ...