We will soon need this to fix the unplug logic and make sure panthor_vm
objects are not left behind after an unplug.

Signed-off-by: Boris Brezillon <[email protected]>
---
 drivers/gpu/drm/panthor/panthor_mmu.c | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c 
b/drivers/gpu/drm/panthor/panthor_mmu.c
index 47c57b39bd12..6368bf57b8f5 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -117,12 +117,15 @@ struct panthor_mmu {
 
        /** @vm: VMs management fields */
        struct {
-               /** @vm.lock: Lock protecting access to list. */
+               /** @vm.lock: Lock protecting access to list and user_owned. */
                struct mutex lock;
 
                /** @vm.list: List containing all VMs. */
                struct list_head list;
 
+               /** @vm.list: List containing VMs with a valid handle. */
+               struct list_head user_owned;
+
                /** @vm.reset_in_progress: True if a reset is in progress. */
                bool reset_in_progress;
 
@@ -447,6 +450,9 @@ struct panthor_vm {
        /** @node: Used to insert the VM in the panthor_mmu::vm::list. */
        struct list_head node;
 
+       /* @user_node: Used to insert the VM in the panthor_mmu::vm::user_owned 
list. */
+       struct list_head user_node;
+
        /** @for_mcu: True if this is the MCU VM. */
        bool for_mcu;
 
@@ -1681,10 +1687,19 @@ int panthor_vm_pool_create_vm(struct panthor_device 
*ptdev,
        drm_gem_object_get(&pool->dummy->base);
        vm->dummy = pool->dummy;
 
+       /* Insert in the list before xa_alloc() so we can't race with
+        * panthor_vm_pool_destroy_vm() have the VM inserted in the
+        * user_owned list after it's been destroyed.
+        */
+       scoped_guard(mutex, &ptdev->mmu->vm.lock)
+               list_add_tail(&vm->user_node, &ptdev->mmu->vm.user_owned);
+
        ret = xa_alloc(&pool->xa, &id, vm,
                       XA_LIMIT(1, PANTHOR_MAX_VMS_PER_FILE), GFP_KERNEL);
 
        if (ret) {
+               scoped_guard(mutex, &ptdev->mmu->vm.lock)
+                       list_del_init(&vm->user_node);
                panthor_vm_put(vm);
                return ret;
        }
@@ -1739,13 +1754,19 @@ static void panthor_vm_destroy(struct panthor_vm *vm)
  */
 int panthor_vm_pool_destroy_vm(struct panthor_vm_pool *pool, u32 handle)
 {
+       struct panthor_device *ptdev;
        struct panthor_vm *vm;
 
        vm = xa_erase(&pool->xa, handle);
+       if (!vm)
+               return -EINVAL;
+
+       ptdev = container_of(vm->as->base.drm, struct panthor_device, base);
+       scoped_guard(mutex, &ptdev->mmu->vm.lock)
+               list_del_init(&vm->user_node);
 
        panthor_vm_destroy(vm);
-
-       return vm ? 0 : -EINVAL;
+       return 0;
 }
 
 /**
@@ -1785,7 +1806,7 @@ void panthor_vm_pool_destroy(struct panthor_file *pfile)
                return;
 
        xa_for_each(&pfile->vms->xa, i, vm)
-               panthor_vm_destroy(vm);
+               panthor_vm_pool_destroy_vm(pfile->vms, i);
 
        if (pfile->vms->dummy)
                drm_gem_object_put(&pfile->vms->dummy->base);
@@ -3182,6 +3203,7 @@ panthor_vm_create(struct panthor_device *ptdev, bool 
for_mcu,
                goto err_put_as;
        }
 
+       INIT_LIST_HEAD(&vm->user_node);
        vm->user_va_range = kernel_va_start;
        vm->as = as;
        mutex_init(&vm->heaps.lock);
@@ -3707,6 +3729,7 @@ int panthor_mmu_init(struct panthor_device *ptdev)
                return ret;
 
        INIT_LIST_HEAD(&mmu->vm.list);
+       INIT_LIST_HEAD(&mmu->vm.user_owned);
        ret = drmm_mutex_init(&ptdev->base, &mmu->vm.lock);
        if (ret)
                return ret;

-- 
2.55.0

Reply via email to