[PATCH v6 01/11] drm/v3d: Address race-condition in MMU flush
Iago Toral
itoral at igalia.com
Tue Sep 24 05:27:27 UTC 2024
Reviewed-by: Iago Toral Quiroga <itoral at 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 <mcanal at 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;
> }
More information about the dri-devel
mailing list