diff options
| author | Simona Vetter <simona.vetter@ffwll.ch> | 2026-01-16 20:27:20 +0100 |
|---|---|---|
| committer | Simona Vetter <simona.vetter@ffwll.ch> | 2026-01-16 20:27:21 +0100 |
| commit | 9dd1f5f3eb8cb175e2f7fd2a685bdb6b1bd2a726 (patch) | |
| tree | 6c0e2161bd49b35b791bbe2f95efa3fc5177a63a /drivers/gpu/drm/drm_gpuvm.c | |
| parent | 52456a62174f5e917060486fd84cac877c3e25e5 (diff) | |
| parent | b91a565ed14fcf900b4d95e86882b4b763860986 (diff) | |
Merge tag 'drm-misc-fixes-2026-01-16' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
drm-misc-fixes for v6.19-rc6:
vmwgfx:
- Fix hw regression from refactoring cursor handling on v10 'hardware'
- Fix warnings in destructor by merging the 2 release functions
- kernel doc fix
- error handling in vmw_compat_shader_add()
rockchip:
- fix vop2 polling
- fix regression waiting for cfgdone without config change
- fix warning when enabling encoder
core:
- take gem lock when preallocating in gpuvm.
- add single byte read fallback to dp for broken usb-c adapters
- remove duplicate drm_sysfb declarations
gud:
- Fix oops on usb disconnect
Simple panel:
- Re-add fallback when connector is not set to fix regressions
- Set correct type in DataImage SCF0700C48GGU18
nouveau:
- locking fixes for cursor handling.
Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patch.msgid.link/ce0acfe2-9c1a-42b7-8782-f1e7f34b8544@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/drm_gpuvm.c')
| -rw-r--r-- | drivers/gpu/drm/drm_gpuvm.c | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c index 8a06d296561d..0de47e83d84d 100644 --- a/drivers/gpu/drm/drm_gpuvm.c +++ b/drivers/gpu/drm/drm_gpuvm.c @@ -1602,14 +1602,48 @@ drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm, } EXPORT_SYMBOL_GPL(drm_gpuvm_bo_create); +/* + * drm_gpuvm_bo_destroy_not_in_lists() - final part of drm_gpuvm_bo cleanup + * @vm_bo: the &drm_gpuvm_bo to destroy + * + * It is illegal to call this method if the @vm_bo is present in the GEMs gpuva + * list, the extobj list, or the evicted list. + * + * Note that this puts a refcount on the GEM object, which may destroy the GEM + * object if the refcount reaches zero. It's illegal for this to happen if the + * caller holds the GEMs gpuva mutex because it would free the mutex. + */ +static void +drm_gpuvm_bo_destroy_not_in_lists(struct drm_gpuvm_bo *vm_bo) +{ + struct drm_gpuvm *gpuvm = vm_bo->vm; + const struct drm_gpuvm_ops *ops = gpuvm->ops; + struct drm_gem_object *obj = vm_bo->obj; + + if (ops && ops->vm_bo_free) + ops->vm_bo_free(vm_bo); + else + kfree(vm_bo); + + drm_gpuvm_put(gpuvm); + drm_gem_object_put(obj); +} + +static void +drm_gpuvm_bo_destroy_not_in_lists_kref(struct kref *kref) +{ + struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo, + kref); + + drm_gpuvm_bo_destroy_not_in_lists(vm_bo); +} + static void drm_gpuvm_bo_destroy(struct kref *kref) { struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo, kref); struct drm_gpuvm *gpuvm = vm_bo->vm; - const struct drm_gpuvm_ops *ops = gpuvm->ops; - struct drm_gem_object *obj = vm_bo->obj; bool lock = !drm_gpuvm_resv_protected(gpuvm); if (!lock) @@ -1618,16 +1652,10 @@ drm_gpuvm_bo_destroy(struct kref *kref) drm_gpuvm_bo_list_del(vm_bo, extobj, lock); drm_gpuvm_bo_list_del(vm_bo, evict, lock); - drm_gem_gpuva_assert_lock_held(gpuvm, obj); + drm_gem_gpuva_assert_lock_held(gpuvm, vm_bo->obj); list_del(&vm_bo->list.entry.gem); - if (ops && ops->vm_bo_free) - ops->vm_bo_free(vm_bo); - else - kfree(vm_bo); - - drm_gpuvm_put(gpuvm); - drm_gem_object_put(obj); + drm_gpuvm_bo_destroy_not_in_lists(vm_bo); } /** @@ -1745,9 +1773,7 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put_deferred); void drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm) { - const struct drm_gpuvm_ops *ops = gpuvm->ops; struct drm_gpuvm_bo *vm_bo; - struct drm_gem_object *obj; struct llist_node *bo_defer; bo_defer = llist_del_all(&gpuvm->bo_defer); @@ -1766,14 +1792,7 @@ drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm) while (bo_defer) { vm_bo = llist_entry(bo_defer, struct drm_gpuvm_bo, list.entry.bo_defer); bo_defer = bo_defer->next; - obj = vm_bo->obj; - if (ops && ops->vm_bo_free) - ops->vm_bo_free(vm_bo); - else - kfree(vm_bo); - - drm_gpuvm_put(gpuvm); - drm_gem_object_put(obj); + drm_gpuvm_bo_destroy_not_in_lists(vm_bo); } } EXPORT_SYMBOL_GPL(drm_gpuvm_bo_deferred_cleanup); @@ -1861,6 +1880,9 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain); * count is decreased. If not found @__vm_bo is returned without further * increase of the reference count. * + * The provided @__vm_bo must not already be in the gpuva, evict, or extobj + * lists prior to calling this method. + * * A new &drm_gpuvm_bo is added to the GEMs gpuva list. * * Returns: a pointer to the found &drm_gpuvm_bo or @__vm_bo if no existing @@ -1873,14 +1895,19 @@ drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *__vm_bo) struct drm_gem_object *obj = __vm_bo->obj; struct drm_gpuvm_bo *vm_bo; + drm_WARN_ON(gpuvm->drm, !drm_gpuvm_immediate_mode(gpuvm)); + + mutex_lock(&obj->gpuva.lock); vm_bo = drm_gpuvm_bo_find(gpuvm, obj); if (vm_bo) { - drm_gpuvm_bo_put(__vm_bo); + mutex_unlock(&obj->gpuva.lock); + kref_put(&__vm_bo->kref, drm_gpuvm_bo_destroy_not_in_lists_kref); return vm_bo; } drm_gem_gpuva_assert_lock_held(gpuvm, obj); list_add_tail(&__vm_bo->list.entry.gem, &obj->gpuva.list); + mutex_unlock(&obj->gpuva.lock); return __vm_bo; } |
