Reviewed-by: Iago Toral Quiroga <ito...@igalia.com>

El lun, 23-09-2024 a las 10:55 -0300, Maíra Canal escribió:
> We must first flush the MMU cache and then, flush the TLB, not the
> other
> way around. Currently, we can see a race condition between the MMU
> cache
> and the TLB when running multiple rendering processes at the same
> time.
> This is evidenced by MMU errors triggered by the IRQ.
> 
> Fix the MMU flush order by flushing the MMU cache and then the TLB.
> Also, in order to address the race condition, wait for the MMU cache
> flush
> to finish before starting the TLB flush.
> 
> Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for
> Broadcom V3D V3.x+")
> Signed-off-by: Maíra Canal <mca...@igalia.com>
> ---
>  drivers/gpu/drm/v3d/v3d_mmu.c | 29 ++++++++++-------------------
>  1 file changed, 10 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c
> b/drivers/gpu/drm/v3d/v3d_mmu.c
> index 14f3af40d6f6..e36ec3343b06 100644
> --- a/drivers/gpu/drm/v3d/v3d_mmu.c
> +++ b/drivers/gpu/drm/v3d/v3d_mmu.c
> @@ -32,32 +32,23 @@ static int v3d_mmu_flush_all(struct v3d_dev *v3d)
>  {
>       int ret;
>  
> -     /* Make sure that another flush isn't already running when
> we
> -      * start this one.
> -      */
> -     ret = wait_for(!(V3D_READ(V3D_MMU_CTL) &
> -                      V3D_MMU_CTL_TLB_CLEARING), 100);
> -     if (ret)
> -             dev_err(v3d->drm.dev, "TLB clear wait idle pre-wait
> failed\n");
> -
> -     V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL) |
> -               V3D_MMU_CTL_TLB_CLEAR);
> -
> -     V3D_WRITE(V3D_MMUC_CONTROL,
> -               V3D_MMUC_CONTROL_FLUSH |
> +     V3D_WRITE(V3D_MMUC_CONTROL, V3D_MMUC_CONTROL_FLUSH |
>                 V3D_MMUC_CONTROL_ENABLE);
>  
> -     ret = wait_for(!(V3D_READ(V3D_MMU_CTL) &
> -                      V3D_MMU_CTL_TLB_CLEARING), 100);
> +     ret = wait_for(!(V3D_READ(V3D_MMUC_CONTROL) &
> +                      V3D_MMUC_CONTROL_FLUSHING), 100);
>       if (ret) {
> -             dev_err(v3d->drm.dev, "TLB clear wait idle
> failed\n");
> +             dev_err(v3d->drm.dev, "MMUC flush wait idle
> failed\n");
>               return ret;
>       }
>  
> -     ret = wait_for(!(V3D_READ(V3D_MMUC_CONTROL) &
> -                      V3D_MMUC_CONTROL_FLUSHING), 100);
> +     V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL) |
> +               V3D_MMU_CTL_TLB_CLEAR);
> +
> +     ret = wait_for(!(V3D_READ(V3D_MMU_CTL) &
> +                      V3D_MMU_CTL_TLB_CLEARING), 100);
>       if (ret)
> -             dev_err(v3d->drm.dev, "MMUC flush wait idle
> failed\n");
> +             dev_err(v3d->drm.dev, "MMU TLB clear wait idle
> failed\n");
>  
>       return ret;
>  }

Reply via email to