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
