On Tue, Dec 02, 2025 at 02:35:37PM +0100, Boris Brezillon wrote:
> When we re-assign a slot to a different VM, we need to make sure the
> old VM caches are flushed before doing the switch. Specialize
> panthor_mmu_as_disable() so we can skip the slot programmation while
> still getting the cache flushing, and call this helper from
> panthor_vm_active() when an idle slot is recycled.
>
> Fixes: 6e2d3b3e8589 ("drm/panthor: Add support for atomic page table updates")
> Signed-off-by: Boris Brezillon <[email protected]>
Reviewed-by: Liviu Dudau <[email protected]>
Best regards,
Liviu
> ---
> drivers/gpu/drm/panthor/panthor_mmu.c | 26 ++++++++++++++++++++------
> 1 file changed, 20 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c
> b/drivers/gpu/drm/panthor/panthor_mmu.c
> index 8ba5259e3d28..3644af1a8e56 100644
> --- a/drivers/gpu/drm/panthor/panthor_mmu.c
> +++ b/drivers/gpu/drm/panthor/panthor_mmu.c
> @@ -585,7 +585,8 @@ static int panthor_mmu_as_enable(struct panthor_device
> *ptdev, u32 as_nr,
> return as_send_cmd_and_wait(ptdev, as_nr, AS_COMMAND_UPDATE);
> }
>
> -static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr)
> +static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr,
> + bool recycle_slot)
> {
> int ret;
>
> @@ -595,6 +596,12 @@ static int panthor_mmu_as_disable(struct panthor_device
> *ptdev, u32 as_nr)
> if (ret)
> return ret;
>
> + /* If the slot is going to be used immediately, don't bother changing
> + * the config.
> + */
> + if (recycle_slot)
> + return 0;
> +
> gpu_write64(ptdev, AS_TRANSTAB(as_nr), 0);
> gpu_write64(ptdev, AS_MEMATTR(as_nr), 0);
> gpu_write64(ptdev, AS_TRANSCFG(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
> @@ -714,6 +721,11 @@ int panthor_vm_active(struct panthor_vm *vm)
>
> drm_WARN_ON(&ptdev->base,
> refcount_read(&lru_vm->as.active_cnt));
> as = lru_vm->as.id;
> +
> + ret = panthor_mmu_as_disable(ptdev, as, true);
> + if (ret)
> + goto out_unlock;
> +
> panthor_vm_release_as_locked(lru_vm);
> }
>
> @@ -853,7 +865,7 @@ static void panthor_vm_declare_unusable(struct panthor_vm
> *vm)
> vm->unusable = true;
> mutex_lock(&ptdev->mmu->as.slots_lock);
> if (vm->as.id >= 0 && drm_dev_enter(&ptdev->base, &cookie)) {
> - panthor_mmu_as_disable(ptdev, vm->as.id);
> + panthor_mmu_as_disable(ptdev, vm->as.id, false);
> drm_dev_exit(cookie);
> }
> mutex_unlock(&ptdev->mmu->as.slots_lock);
> @@ -1780,7 +1792,7 @@ static void panthor_mmu_irq_handler(struct
> panthor_device *ptdev, u32 status)
> ptdev->mmu->as.slots[as].vm->unhandled_fault = true;
>
> /* Disable the MMU to kill jobs on this AS. */
> - panthor_mmu_as_disable(ptdev, as);
> + panthor_mmu_as_disable(ptdev, as, false);
> mutex_unlock(&ptdev->mmu->as.slots_lock);
>
> status &= ~mask;
> @@ -1809,7 +1821,8 @@ void panthor_mmu_suspend(struct panthor_device *ptdev)
> struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm;
>
> if (vm) {
> - drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev,
> i));
> + drm_WARN_ON(&ptdev->base,
> + panthor_mmu_as_disable(ptdev, i, false));
> panthor_vm_release_as_locked(vm);
> }
> }
> @@ -1930,7 +1943,7 @@ static void panthor_vm_free(struct drm_gpuvm *gpuvm)
> int cookie;
>
> if (drm_dev_enter(&ptdev->base, &cookie)) {
> - panthor_mmu_as_disable(ptdev, vm->as.id);
> + panthor_mmu_as_disable(ptdev, vm->as.id, false);
> drm_dev_exit(cookie);
> }
>
> @@ -2790,7 +2803,8 @@ void panthor_mmu_unplug(struct panthor_device *ptdev)
> struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm;
>
> if (vm) {
> - drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev,
> i));
> + drm_WARN_ON(&ptdev->base,
> + panthor_mmu_as_disable(ptdev, i, false));
> panthor_vm_release_as_locked(vm);
> }
> }
> --
> 2.51.1
>