The unwind loop drops the vm_bo reference taken while locking before
advancing to the next entry.  drm_gpuvm_bo_put() may drop the last
reference, removing and freeing the vm_bo, after which the plain list
iterator dereferences freed memory to advance.

Use the safe iterator, which saves the next entry before the body runs.

Fixes: fe4952b5f27cca5d ("drm/msm: Convert vm locking")
Cc: [email protected]
Signed-off-by: Wentao Liang <[email protected]>
---
 drivers/gpu/drm/msm/msm_gem_shrinker.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c 
b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index c8dda2b68cff..27b45165b213 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -51,6 +51,7 @@ with_vm_locks(void (*fn)(struct drm_gem_object *obj),
         * success paths
         */
        struct drm_gpuvm_bo *vm_bo, *last_locked = NULL;
+       struct drm_gpuvm_bo *next;
        bool locked = true;
 
        drm_gem_for_each_gpuvm_bo (vm_bo, obj) {
@@ -82,7 +83,7 @@ with_vm_locks(void (*fn)(struct drm_gem_object *obj),
 
 out_unlock:
        if (last_locked) {
-               drm_gem_for_each_gpuvm_bo (vm_bo, obj) {
+               drm_gem_for_each_gpuvm_bo_safe(vm_bo, next, obj) {
                        struct dma_resv *resv = drm_gpuvm_resv(vm_bo->vm);
 
                        if (resv == obj->resv)
-- 
2.34.1

Reply via email to