drm/amdgpu: add spin lock to protect freed list in vm (v2)
authorjimqu <Jim.Qu@amd.com>
Fri, 4 Dec 2015 09:17:00 +0000 (17:17 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 4 Dec 2015 18:08:13 +0000 (13:08 -0500)
there is a protection fault about freed list when OCL test.
add a spin lock to protect it.

v2: drop changes in vm_fini

Signed-off-by: JimQu <jim.qu@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 670fefb56945258faf899b708047a2bd83685a59..5a5f04d0902d662548ebae9f82525e1363e8457c 100644 (file)
@@ -956,6 +956,8 @@ struct amdgpu_vm {
        struct amdgpu_vm_id     ids[AMDGPU_MAX_RINGS];
        /* for interval tree */
        spinlock_t              it_lock;
+       /* protecting freed */
+       spinlock_t              freed_lock;
 };
 
 struct amdgpu_vm_manager {
index a582ef5534992f7d2e1e3b69bc6a666591958016..b53d273eb7a1003a719fff9d1bd32a8b4fa20b78 100644 (file)
@@ -885,17 +885,21 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
        struct amdgpu_bo_va_mapping *mapping;
        int r;
 
+       spin_lock(&vm->freed_lock);
        while (!list_empty(&vm->freed)) {
                mapping = list_first_entry(&vm->freed,
                        struct amdgpu_bo_va_mapping, list);
                list_del(&mapping->list);
-
+               spin_unlock(&vm->freed_lock);
                r = amdgpu_vm_bo_update_mapping(adev, vm, mapping, 0, 0, NULL);
                kfree(mapping);
                if (r)
                        return r;
 
+               spin_lock(&vm->freed_lock);
        }
+       spin_unlock(&vm->freed_lock);
+
        return 0;
 
 }
@@ -1155,10 +1159,13 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
        spin_unlock(&vm->it_lock);
        trace_amdgpu_vm_bo_unmap(bo_va, mapping);
 
-       if (valid)
+       if (valid) {
+               spin_lock(&vm->freed_lock);
                list_add(&mapping->list, &vm->freed);
-       else
+               spin_unlock(&vm->freed_lock);
+       } else {
                kfree(mapping);
+       }
 
        return 0;
 }
@@ -1191,7 +1198,9 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
                interval_tree_remove(&mapping->it, &vm->va);
                spin_unlock(&vm->it_lock);
                trace_amdgpu_vm_bo_unmap(bo_va, mapping);
+               spin_lock(&vm->freed_lock);
                list_add(&mapping->list, &vm->freed);
+               spin_unlock(&vm->freed_lock);
        }
        list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) {
                list_del(&mapping->list);
@@ -1252,6 +1261,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        INIT_LIST_HEAD(&vm->cleared);
        INIT_LIST_HEAD(&vm->freed);
        spin_lock_init(&vm->it_lock);
+       spin_lock_init(&vm->freed_lock);
        pd_size = amdgpu_vm_directory_size(adev);
        pd_entries = amdgpu_vm_num_pdes(adev);