summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_gem.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2025-06-29 13:12:57 -0700
committerRob Clark <robin.clark@oss.qualcomm.com>2025-07-04 17:48:35 -0700
commitfe4952b5f27cca5d143d3de249562d4cc984c1d6 (patch)
tree93fd06a5cd30230c252cda5e32888c17c1cfdefe /drivers/gpu/drm/msm/msm_gem.c
parent111fdd2198e63b1e19ce015d95692d27bf6ce3fa (diff)
drm/msm: Convert vm locking
Convert to using the gpuvm's r_obj for serializing access to the VM. This way we can use the drm_exec helper for dealing with deadlock detection and backoff. This will let us deal with upcoming locking order conflicts with the VM_BIND implmentation (ie. in some scenarious we need to acquire the obj lock first, for ex. to iterate all the VMs an obj is bound in, and in other scenarious we need to acquire the VM lock first). Signed-off-by: Rob Clark <robdclark@chromium.org> Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com> Tested-by: Antonino Maniscalco <antomani103@gmail.com> Reviewed-by: Antonino Maniscalco <antomani103@gmail.com> Patchwork: https://patchwork.freedesktop.org/patch/661478/
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gem.c')
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 664fb801c221..82293806219a 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -48,6 +48,7 @@ static void put_iova_spaces(struct drm_gem_object *obj, struct drm_gpuvm *vm, bo
static void detach_vm(struct drm_gem_object *obj, struct msm_gem_vm *vm)
{
msm_gem_assert_locked(obj);
+ drm_gpuvm_resv_assert_held(&vm->base);
struct drm_gpuvm_bo *vm_bo = drm_gpuvm_bo_find(&vm->base, obj);
if (vm_bo) {
@@ -68,6 +69,7 @@ static void detach_vm(struct drm_gem_object *obj, struct msm_gem_vm *vm)
static void msm_gem_close(struct drm_gem_object *obj, struct drm_file *file)
{
struct msm_context *ctx = file->driver_priv;
+ struct drm_exec exec;
update_ctx_mem(file, -obj->size);
@@ -86,10 +88,10 @@ static void msm_gem_close(struct drm_gem_object *obj, struct drm_file *file)
dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_READ, false,
msecs_to_jiffies(1000));
- msm_gem_lock(obj);
+ msm_gem_lock_vm_and_obj(&exec, obj, ctx->vm);
put_iova_spaces(obj, &ctx->vm->base, true);
detach_vm(obj, ctx->vm);
- msm_gem_unlock(obj);
+ drm_exec_fini(&exec); /* drop locks */
}
/*
@@ -551,11 +553,12 @@ int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj,
struct msm_gem_vm *vm, uint64_t *iova,
u64 range_start, u64 range_end)
{
+ struct drm_exec exec;
int ret;
- msm_gem_lock(obj);
+ msm_gem_lock_vm_and_obj(&exec, obj, vm);
ret = get_and_pin_iova_range_locked(obj, vm, iova, range_start, range_end);
- msm_gem_unlock(obj);
+ drm_exec_fini(&exec); /* drop locks */
return ret;
}
@@ -575,16 +578,17 @@ int msm_gem_get_iova(struct drm_gem_object *obj,
struct msm_gem_vm *vm, uint64_t *iova)
{
struct msm_gem_vma *vma;
+ struct drm_exec exec;
int ret = 0;
- msm_gem_lock(obj);
+ msm_gem_lock_vm_and_obj(&exec, obj, vm);
vma = get_vma_locked(obj, vm, 0, U64_MAX);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
} else {
*iova = vma->base.va.addr;
}
- msm_gem_unlock(obj);
+ drm_exec_fini(&exec); /* drop locks */
return ret;
}
@@ -613,9 +617,10 @@ static int clear_iova(struct drm_gem_object *obj,
int msm_gem_set_iova(struct drm_gem_object *obj,
struct msm_gem_vm *vm, uint64_t iova)
{
+ struct drm_exec exec;
int ret = 0;
- msm_gem_lock(obj);
+ msm_gem_lock_vm_and_obj(&exec, obj, vm);
if (!iova) {
ret = clear_iova(obj, vm);
} else {
@@ -628,7 +633,7 @@ int msm_gem_set_iova(struct drm_gem_object *obj,
ret = -EBUSY;
}
}
- msm_gem_unlock(obj);
+ drm_exec_fini(&exec); /* drop locks */
return ret;
}
@@ -642,14 +647,15 @@ void msm_gem_unpin_iova(struct drm_gem_object *obj,
struct msm_gem_vm *vm)
{
struct msm_gem_vma *vma;
+ struct drm_exec exec;
- msm_gem_lock(obj);
+ msm_gem_lock_vm_and_obj(&exec, obj, vm);
vma = lookup_vma(obj, vm);
if (vma) {
msm_gem_unpin_locked(obj);
}
detach_vm(obj, vm);
- msm_gem_unlock(obj);
+ drm_exec_fini(&exec); /* drop locks */
}
int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
@@ -1021,12 +1027,27 @@ static void msm_gem_free_object(struct drm_gem_object *obj)
struct msm_gem_object *msm_obj = to_msm_bo(obj);
struct drm_device *dev = obj->dev;
struct msm_drm_private *priv = dev->dev_private;
+ struct drm_exec exec;
mutex_lock(&priv->obj_lock);
list_del(&msm_obj->node);
mutex_unlock(&priv->obj_lock);
+ /*
+ * We need to lock any VMs the object is still attached to, but not
+ * the object itself (see explaination in msm_gem_assert_locked()),
+ * so just open-code this special case:
+ */
+ drm_exec_init(&exec, 0, 0);
+ drm_exec_until_all_locked (&exec) {
+ struct drm_gpuvm_bo *vm_bo;
+ drm_gem_for_each_gpuvm_bo (vm_bo, obj) {
+ drm_exec_lock_obj(&exec, drm_gpuvm_resv_obj(vm_bo->vm));
+ drm_exec_retry_on_contention(&exec);
+ }
+ }
put_iova_spaces(obj, NULL, true);
+ drm_exec_fini(&exec); /* drop locks */
if (drm_gem_is_imported(obj)) {
GEM_WARN_ON(msm_obj->vaddr);