Skip to content

Commit b6fe4ff

Browse files
ChristianKoenigAMDalexdeucher
authored andcommitted
drm/amdgpu: fix handling in amdgpu_userq_create
Well mostly the same issues the other code had as well: 1. Memory allocation while holding the userq_mutex lock is forbidden! 2. Things were created/started/published in the wrong order. 3. The reset lock was taken in the wrong order and seems to be unecessary in the first place. 4. Error messages on invalid input parameters can spam the logs. 5. Error messages on memory allocation failures are usually superflous as well. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Sunil Khatri <sunil.khatri@amd.com> Reviewed-by: Prike Liang <Prike.Liang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 89e50de)
1 parent d093c01 commit b6fe4ff

1 file changed

Lines changed: 52 additions & 66 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c

Lines changed: 52 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -708,14 +708,14 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
708708
const struct amdgpu_userq_funcs *uq_funcs;
709709
struct amdgpu_usermode_queue *queue;
710710
struct amdgpu_db_info db_info;
711-
bool skip_map_queue;
712-
u32 qid;
713711
uint64_t index;
714-
int r = 0;
715-
int priority =
716-
(args->in.flags & AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_MASK) >>
717-
AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_SHIFT;
712+
int priority;
713+
u32 qid;
714+
int r;
718715

716+
priority =
717+
(args->in.flags & AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_MASK)
718+
>> AMDGPU_USERQ_CREATE_FLAGS_QUEUE_PRIORITY_SHIFT;
719719
r = amdgpu_userq_priority_permit(filp, priority);
720720
if (r)
721721
return r;
@@ -728,47 +728,54 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
728728

729729
uq_funcs = adev->userq_funcs[args->in.ip_type];
730730
if (!uq_funcs) {
731-
drm_file_err(uq_mgr->file, "Usermode queue is not supported for this IP (%u)\n",
732-
args->in.ip_type);
733731
r = -EINVAL;
734732
goto err_pm_runtime;
735733
}
736734

737735
queue = kzalloc_obj(struct amdgpu_usermode_queue);
738736
if (!queue) {
739-
drm_file_err(uq_mgr->file, "Failed to allocate memory for queue\n");
740737
r = -ENOMEM;
741738
goto err_pm_runtime;
742739
}
743740

741+
kref_init(&queue->refcount);
744742
INIT_LIST_HEAD(&queue->userq_va_list);
745743
queue->doorbell_handle = args->in.doorbell_handle;
746744
queue->queue_type = args->in.ip_type;
747745
queue->vm = &fpriv->vm;
748746
queue->priority = priority;
749-
750-
db_info.queue_type = queue->queue_type;
751-
db_info.doorbell_handle = queue->doorbell_handle;
752-
db_info.db_obj = &queue->db_obj;
753-
db_info.doorbell_offset = args->in.doorbell_offset;
754-
755747
queue->userq_mgr = uq_mgr;
748+
INIT_DELAYED_WORK(&queue->hang_detect_work,
749+
amdgpu_userq_hang_detect_work);
756750

757-
/* Validate the userq virtual address.*/
758-
r = amdgpu_bo_reserve(fpriv->vm.root.bo, false);
751+
mutex_init(&queue->fence_drv_lock);
752+
xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
753+
r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
759754
if (r)
760755
goto free_queue;
761756

762-
if (amdgpu_userq_input_va_validate(adev, queue, args->in.queue_va, args->in.queue_size) ||
763-
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va, AMDGPU_GPU_PAGE_SIZE) ||
764-
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va, AMDGPU_GPU_PAGE_SIZE)) {
757+
/* Make sure the queue can actually run with those virtual addresses. */
758+
r = amdgpu_bo_reserve(fpriv->vm.root.bo, false);
759+
if (r)
760+
goto free_fence_drv;
761+
762+
if (amdgpu_userq_input_va_validate(adev, queue, args->in.queue_va,
763+
args->in.queue_size) ||
764+
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va,
765+
AMDGPU_GPU_PAGE_SIZE) ||
766+
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va,
767+
AMDGPU_GPU_PAGE_SIZE)) {
765768
r = -EINVAL;
766769
amdgpu_bo_unreserve(fpriv->vm.root.bo);
767770
goto clean_mapping;
768771
}
769772
amdgpu_bo_unreserve(fpriv->vm.root.bo);
770773

771774
/* Convert relative doorbell offset into absolute doorbell index */
775+
db_info.queue_type = queue->queue_type;
776+
db_info.doorbell_handle = queue->doorbell_handle;
777+
db_info.db_obj = &queue->db_obj;
778+
db_info.doorbell_offset = args->in.doorbell_offset;
772779
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
773780
if (index == (uint64_t)-EINVAL) {
774781
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
@@ -777,85 +784,64 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
777784
}
778785

779786
queue->doorbell_index = index;
780-
mutex_init(&queue->fence_drv_lock);
781-
xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
782-
r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
783-
if (r) {
784-
drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
785-
goto clean_mapping;
786-
}
787-
788787
r = uq_funcs->mqd_create(queue, &args->in);
789788
if (r) {
790789
drm_file_err(uq_mgr->file, "Failed to create Queue\n");
791-
goto clean_fence_driver;
790+
goto clean_mapping;
792791
}
793792

794793
/* Update VM owner at userq submit-time for page-fault attribution. */
795794
amdgpu_vm_set_task_info(&fpriv->vm);
796795

796+
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue,
797+
GFP_KERNEL));
798+
if (r)
799+
goto clean_mqd;
800+
797801
amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
798802

799803
/* don't map the queue if scheduling is halted */
800-
if (adev->userq_halt_for_enforce_isolation &&
801-
((queue->queue_type == AMDGPU_HW_IP_GFX) ||
802-
(queue->queue_type == AMDGPU_HW_IP_COMPUTE)))
803-
skip_map_queue = true;
804-
else
805-
skip_map_queue = false;
806-
if (!skip_map_queue) {
804+
if (!adev->userq_halt_for_enforce_isolation ||
805+
((queue->queue_type != AMDGPU_HW_IP_GFX) &&
806+
(queue->queue_type != AMDGPU_HW_IP_COMPUTE))) {
807807
r = amdgpu_userq_map_helper(queue);
808808
if (r) {
809809
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
810-
goto clean_mqd;
810+
mutex_unlock(&uq_mgr->userq_mutex);
811+
goto clean_doorbell;
811812
}
812813
}
813814

814-
/* drop this refcount during queue destroy */
815-
kref_init(&queue->refcount);
816-
817-
/* Wait for mode-1 reset to complete */
818-
down_read(&adev->reset_domain->sem);
815+
atomic_inc(&uq_mgr->userq_count[queue->queue_type]);
816+
mutex_unlock(&uq_mgr->userq_mutex);
819817

820818
r = xa_alloc(&uq_mgr->userq_xa, &qid, queue,
821-
XA_LIMIT(1, AMDGPU_MAX_USERQ_COUNT), GFP_KERNEL);
822-
if (r) {
823-
if (!skip_map_queue)
824-
amdgpu_userq_unmap_helper(queue);
825-
r = -ENOMEM;
826-
goto clean_reset_domain;
827-
}
828-
829-
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
819+
XA_LIMIT(1, AMDGPU_MAX_USERQ_COUNT),
820+
GFP_KERNEL);
830821
if (r) {
831-
xa_erase(&uq_mgr->userq_xa, qid);
832-
if (!skip_map_queue)
833-
amdgpu_userq_unmap_helper(queue);
834-
goto clean_reset_domain;
822+
/*
823+
* This drops the last reference which should take care of
824+
* all cleanup.
825+
*/
826+
amdgpu_userq_put(queue);
827+
return r;
835828
}
836-
up_read(&adev->reset_domain->sem);
837829

838830
amdgpu_debugfs_userq_init(filp, queue, qid);
839-
INIT_DELAYED_WORK(&queue->hang_detect_work,
840-
amdgpu_userq_hang_detect_work);
841-
842831
args->out.queue_id = qid;
843-
atomic_inc(&uq_mgr->userq_count[queue->queue_type]);
844-
mutex_unlock(&uq_mgr->userq_mutex);
845832
return 0;
846833

847-
clean_reset_domain:
848-
up_read(&adev->reset_domain->sem);
834+
clean_doorbell:
835+
xa_erase_irq(&adev->userq_doorbell_xa, index);
849836
clean_mqd:
850-
mutex_unlock(&uq_mgr->userq_mutex);
851837
uq_funcs->mqd_destroy(queue);
852-
clean_fence_driver:
853-
amdgpu_userq_fence_driver_free(queue);
854838
clean_mapping:
855839
amdgpu_bo_reserve(fpriv->vm.root.bo, true);
856840
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
857841
amdgpu_bo_unreserve(fpriv->vm.root.bo);
858842
mutex_destroy(&queue->fence_drv_lock);
843+
free_fence_drv:
844+
amdgpu_userq_fence_driver_free(queue);
859845
free_queue:
860846
kfree(queue);
861847
err_pm_runtime:

0 commit comments

Comments
 (0)