Reviewed-by: Iago Toral Quiroga <itoral@xxxxxxxxxx> 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@xxxxxxxxxx> > --- > 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; > }