diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 5839fab374bf..087332858853 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -69,7 +69,8 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, } } retry: - r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain, flags, NULL, &robj); + r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain, + flags, NULL, NULL, &robj); if (r) { if (r != -ERESTARTSYS) { if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) { @@ -114,9 +115,10 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va *bo_va; int r; - + mutex_lock(&vm->mutex); r = amdgpu_bo_reserve(rbo, false); if (r) { + mutex_unlock(&vm->mutex); return r; } @@ -127,7 +129,7 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri ++bo_va->ref_count; } amdgpu_bo_unreserve(rbo); - + mutex_unlock(&vm->mutex); return 0; } @@ -140,9 +142,10 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va *bo_va; int r; - + mutex_lock(&vm->mutex); r = amdgpu_bo_reserve(rbo, true); if (r) { + mutex_unlock(&vm->mutex); dev_err(adev->dev, "leaking bo va because " "we fail to reserve bo (%d)\n", r); return; @@ -154,6 +157,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, } } amdgpu_bo_unreserve(rbo); + mutex_unlock(&vm->mutex); } static int amdgpu_gem_handle_lockup(struct amdgpu_device *adev, int r) @@ -180,7 +184,6 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, bool kernel = false; int r; - down_read(&adev->exclusive_lock); /* create a gem object to contain this object in */ if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS | AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) { @@ -213,11 +216,9 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, memset(args, 0, sizeof(*args)); args->out.handle = handle; - up_read(&adev->exclusive_lock); return 0; error_unlock: - up_read(&adev->exclusive_lock); r = amdgpu_gem_handle_lockup(adev, r); return r; } @@ -249,8 +250,6 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, return -EACCES; } - down_read(&adev->exclusive_lock); - /* create a gem object to contain this object in */ r = amdgpu_gem_object_create(adev, args->size, 0, AMDGPU_GEM_DOMAIN_CPU, 0, @@ -292,14 +291,12 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, goto handle_lockup; args->handle = handle; - up_read(&adev->exclusive_lock); return 0; release_object: drm_gem_object_unreference_unlocked(gobj); handle_lockup: - up_read(&adev->exclusive_lock); r = amdgpu_gem_handle_lockup(adev, r); return r; @@ -426,6 +423,10 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data, &args->data.data_size_bytes, &args->data.flags); } else if (args->op == AMDGPU_GEM_METADATA_OP_SET_METADATA) { + if (args->data.data_size_bytes > sizeof(args->data.data)) { + r = -EINVAL; + goto unreserve; + } r = amdgpu_bo_set_tiling_flags(robj, args->data.tiling_info); if (!r) r = amdgpu_bo_set_metadata(robj, args->data.data, @@ -433,6 +434,7 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data, args->data.flags); } +unreserve: amdgpu_bo_unreserve(robj); out: drm_gem_object_unreference_unlocked(gobj); @@ -454,11 +456,12 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct ttm_validate_buffer tv, *entry; struct amdgpu_bo_list_entry *vm_bos; struct ww_acquire_ctx ticket; - struct list_head list; + struct list_head list, duplicates; unsigned domain; int r; INIT_LIST_HEAD(&list); + INIT_LIST_HEAD(&duplicates); tv.bo = &bo_va->bo->tbo; tv.shared = true; @@ -468,7 +471,8 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, if (!vm_bos) return; - r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL); + /* Provide duplicates to avoid -EALREADY */ + r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); if (r) goto error_free; @@ -480,18 +484,13 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, goto error_unreserve; } - mutex_lock(&bo_va->vm->mutex); r = amdgpu_vm_clear_freed(adev, bo_va->vm); if (r) - goto error_unlock; - + goto error_unreserve; if (operation == AMDGPU_VA_OP_MAP) r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem); -error_unlock: - mutex_unlock(&bo_va->vm->mutex); - error_unreserve: ttm_eu_backoff_reservation(&ticket, &list); @@ -548,10 +547,11 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) return -ENOENT; - + mutex_lock(&fpriv->vm.mutex); rbo = gem_to_amdgpu_bo(gobj); r = amdgpu_bo_reserve(rbo, false); if (r) { + mutex_unlock(&fpriv->vm.mutex); drm_gem_object_unreference_unlocked(gobj); return r; } @@ -559,6 +559,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, bo_va = amdgpu_vm_bo_find(&fpriv->vm, rbo); if (!bo_va) { amdgpu_bo_unreserve(rbo); + mutex_unlock(&fpriv->vm.mutex); return -ENOENT; } @@ -583,7 +584,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE)) amdgpu_gem_va_update_vm(adev, bo_va, args->operation); - + mutex_unlock(&fpriv->vm.mutex); drm_gem_object_unreference_unlocked(gobj); return r; } @@ -651,7 +652,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, int r; args->pitch = amdgpu_align_pitch(adev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); - args->size = args->pitch * args->height; + args->size = (u64)args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE); r = amdgpu_gem_object_create(adev, args->size, 0, |