drm/amdgpu: Enable userq fence interrupt support
authorArunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Wed, 30 Oct 2024 05:08:46 +0000 (10:38 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 8 Apr 2025 20:48:16 +0000 (16:48 -0400)
Add support to handle the userqueue protected fence signal hardware
interrupt.

Create a xarray which maps the doorbell index to the fence driver address.
This would help to retrieve the fence driver information when an userq fence
interrupt is triggered. Firmware sends the doorbell offset value and
this info is compared with the queue's mqd doorbell offset value.
If they are same, we process the userq fence interrupt.

v1:(Christian):
  - use xa_load to extract the fence driver.
  - move the amdgpu_userq_fence_driver_process call within the xa_lock
    as there is a chance that fence_drv might be freed.

Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c

index cfaa5d77b20acb047a88f100eadf576e2ac5cf47..fdd271edb0b913850fd732293e6743e03f2393b9 100644 (file)
@@ -4336,6 +4336,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        spin_lock_init(&adev->virt.rlcg_reg_lock);
        spin_lock_init(&adev->wb.lock);
 
+       xa_init_flags(&adev->userq_xa, XA_FLAGS_LOCK_IRQ);
+
        INIT_LIST_HEAD(&adev->reset_list);
 
        INIT_LIST_HEAD(&adev->ras_list);
index 1a9565b61266a357f47697a8995788a7b7820ad2..cd473c985e369ff2ff5f686a82d353e8af242015 100644 (file)
@@ -71,6 +71,7 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
                                    struct amdgpu_usermode_queue *userq)
 {
        struct amdgpu_userq_fence_driver *fence_drv;
+       unsigned long flags;
        int r;
 
        fence_drv = kzalloc(sizeof(*fence_drv), GFP_KERNEL);
@@ -98,6 +99,11 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
        fence_drv->context = dma_fence_context_alloc(1);
        get_task_comm(fence_drv->timeline_name, current);
 
+       xa_lock_irqsave(&adev->userq_xa, flags);
+       __xa_store(&adev->userq_xa, userq->doorbell_index,
+                  fence_drv, GFP_KERNEL);
+       xa_unlock_irqrestore(&adev->userq_xa, flags);
+
        userq->fence_drv = fence_drv;
 
        return 0;
index 62a6da083a8fef5c12f49ae539ff4afac982429b..b061b654d1ec27827e91e0c283694375697a4a5e 100644 (file)
@@ -49,6 +49,7 @@
 #include "nbio_v4_3.h"
 #include "mes_v11_0.h"
 #include "mes_v11_0_userqueue.h"
+#include "amdgpu_userq_fence.h"
 
 #define GFX11_NUM_GFX_RINGS            1
 #define GFX11_MEC_HPD_SIZE     2048
@@ -6334,25 +6335,23 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
                             struct amdgpu_irq_src *source,
                             struct amdgpu_iv_entry *entry)
 {
-       int i;
+       u32 doorbell_offset = entry->src_data[0];
        u8 me_id, pipe_id, queue_id;
        struct amdgpu_ring *ring;
-       uint32_t mes_queue_id = entry->src_data[0];
+       int i;
 
        DRM_DEBUG("IH: CP EOP\n");
 
-       if (adev->enable_mes && (mes_queue_id & AMDGPU_FENCE_MES_QUEUE_FLAG)) {
-               struct amdgpu_mes_queue *queue;
+       if (adev->enable_mes && doorbell_offset) {
+               struct amdgpu_userq_fence_driver *fence_drv = NULL;
+               struct xarray *xa = &adev->userq_xa;
+               unsigned long flags;
 
-               mes_queue_id &= AMDGPU_FENCE_MES_QUEUE_ID_MASK;
-
-               spin_lock(&adev->mes.queue_id_lock);
-               queue = idr_find(&adev->mes.queue_id_idr, mes_queue_id);
-               if (queue) {
-                       DRM_DEBUG("process mes queue id = %d\n", mes_queue_id);
-                       amdgpu_fence_process(queue->ring);
-               }
-               spin_unlock(&adev->mes.queue_id_lock);
+               xa_lock_irqsave(xa, flags);
+               fence_drv = xa_load(xa, doorbell_offset);
+               if (fence_drv)
+                       amdgpu_userq_fence_driver_process(fence_drv);
+               xa_unlock_irqrestore(xa, flags);
        } else {
                me_id = (entry->ring_id & 0x0c) >> 2;
                pipe_id = (entry->ring_id & 0x03) >> 0;