This patch resolves a kernel warning that occurs during user queue 
initialization:

[  428.714241] WARNING: CPU: 23 PID: 1965 at drivers/gpu/drm/ttm/ttm_bo.c:823 
ttm_bo_validate+0x15c/0x1a0 [ttm]
[  428.714758] Call Trace:
[  428.714758]  amdgpu_bo_pin+0x1b5/0x310 [amdgpu]
[  428.714915]  amdgpu_userq_get_doorbell_index+0x71/0x270 [amdgpu]

The warning occurs due to improper buffer object state management when
setting up doorbells for user queues. The key issues addressed are:

1. Incorrect locking sequence - pinning before reservation
2. Inadequate error handling paths
3. Race conditions during BO validation

Changes made:
1. Reordered operations to reserve BO before pinning
2. Added proper cleanup path for reservation failures
3. Improved error handling with separate unpin/unreserve paths

Signed-off-by: Jesse Zhang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 33 +++++++++++++----------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 0f1cb6bc63db..444a0f5d98ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -283,28 +283,31 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr 
*uq_mgr,
        uint64_t index;
        struct drm_gem_object *gobj;
        struct amdgpu_userq_obj *db_obj = db_info->db_obj;
+       struct amdgpu_bo *bo;
        int r, db_size;
 
        gobj = drm_gem_object_lookup(filp, db_info->doorbell_handle);
-       if (gobj == NULL) {
+       if (!gobj) {
                drm_file_err(uq_mgr->file, "Can't find GEM object for 
doorbell\n");
                return -EINVAL;
        }
 
-       db_obj->obj = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
+       bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
        drm_gem_object_put(gobj);
+       db_obj->obj = bo;
 
-       /* Pin the BO before generating the index, unpin in queue destroy */
-       r = amdgpu_bo_pin(db_obj->obj, AMDGPU_GEM_DOMAIN_DOORBELL);
+       /* First reserve the BO to ensure proper state */
+       r = amdgpu_bo_reserve(bo, true);
        if (r) {
-               drm_file_err(uq_mgr->file, "[Usermode queues] Failed to pin 
doorbell object\n");
+               drm_file_err(uq_mgr->file, "[Usermode queues] Failed to reserve 
doorbell BO\n");
                goto unref_bo;
        }
 
-       r = amdgpu_bo_reserve(db_obj->obj, true);
+       /* Validate and pin the BO */
+       r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_DOORBELL);
        if (r) {
-               drm_file_err(uq_mgr->file, "[Usermode queues] Failed to pin 
doorbell object\n");
-               goto unpin_bo;
+               drm_file_err(uq_mgr->file, "[Usermode queues] Failed to pin 
doorbell BO\n");
+               goto unreserve_bo;
        }
 
        switch (db_info->queue_type) {
@@ -325,24 +328,26 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr 
*uq_mgr,
                break;
 
        default:
-               drm_file_err(uq_mgr->file, "[Usermode queues] IP %d not 
support\n",
+               drm_file_err(uq_mgr->file, "IP %d not supported\n",
                             db_info->queue_type);
                r = -EINVAL;
                goto unpin_bo;
        }
 
-       index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
+       index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, bo,
                                             db_info->doorbell_offset, db_size);
        drm_dbg_driver(adev_to_drm(uq_mgr->adev),
                       "[Usermode queues] doorbell index=%lld\n", index);
-       amdgpu_bo_unreserve(db_obj->obj);
+
+       amdgpu_bo_unreserve(bo);
        return index;
 
 unpin_bo:
-       amdgpu_bo_unpin(db_obj->obj);
-
+       amdgpu_bo_unpin(bo);
+unreserve_bo:
+       amdgpu_bo_unreserve(bo);
 unref_bo:
-       amdgpu_bo_unref(&db_obj->obj);
+       amdgpu_bo_unref(&bo);
        return r;
 }
 
-- 
2.49.0

Reply via email to