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 | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c 
b/drivers/gpu/drm/panthor/panthor_mmu.c
index 93e9d55da783..5672d437d52d 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -107,12 +107,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;
 
@@ -427,6 +430,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;
 
@@ -1669,10 +1675,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;
        }
@@ -1727,13 +1742,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;
 }
 
 /**
@@ -3118,6 +3139,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);
@@ -3626,6 +3648,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