drm/amdgpu/mes11: Use a separate fence per transaction
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 19 Apr 2024 03:30:46 +0000 (23:30 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 26 Apr 2024 21:22:41 +0000 (17:22 -0400)
We can't use a shared fence location because each transaction
should be considered independently.

Reviewed-by: Shaoyun.liu <shaoyunl@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c

index 310c8f0c21da99a20491dcf182fc60b4bbd14918..21d1d508ee106ffcead7ab00c2e0d5905d385cbb 100644 (file)
 #define AMDGPU_MES_MAX_NUM_OF_QUEUES_PER_PROCESS 1024
 #define AMDGPU_ONE_DOORBELL_SIZE 8
 
+signed long amdgpu_mes_fence_wait_polling(u64 *fence,
+                                         u64 wait_seq,
+                                         signed long timeout)
+{
+
+       while ((s64)(wait_seq - *fence) > 0 && timeout > 0) {
+               udelay(2);
+               timeout -= 2;
+       }
+       return timeout > 0 ? timeout : 0;
+}
+
 int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev)
 {
        return roundup(AMDGPU_ONE_DOORBELL_SIZE *
index 6b3e1844eac58752f9cbdec812175a60c7abf713..b99a2b3cffe3fe4b5b8ac54a5d201128c1aa64af 100644 (file)
@@ -340,6 +340,10 @@ struct amdgpu_mes_funcs {
 #define amdgpu_mes_kiq_hw_init(adev) (adev)->mes.kiq_hw_init((adev))
 #define amdgpu_mes_kiq_hw_fini(adev) (adev)->mes.kiq_hw_fini((adev))
 
+signed long amdgpu_mes_fence_wait_polling(u64 *fence,
+                                         u64 wait_seq,
+                                         signed long timeout);
+
 int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);
 
 int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
index 5c08ad234439e83f62a87fd3f1b23d381eb525f1..0d1407f250059642f03eaf1e21fa4b83deee7975 100644 (file)
@@ -163,6 +163,10 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
        unsigned long flags;
        signed long timeout = 3000000; /* 3000 ms */
        const char *op_str, *misc_op_str;
+       u32 fence_offset;
+       u64 fence_gpu_addr;
+       u64 *fence_ptr;
+       int ret;
 
        if (x_pkt->header.opcode >= MES_SCH_API_MAX)
                return -EINVAL;
@@ -175,15 +179,24 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
        }
        BUG_ON(size % 4 != 0);
 
+       ret = amdgpu_device_wb_get(adev, &fence_offset);
+       if (ret)
+               return ret;
+       fence_gpu_addr =
+               adev->wb.gpu_addr + (fence_offset * 4);
+       fence_ptr = (u64 *)&adev->wb.wb[fence_offset];
+       *fence_ptr = 0;
+
        spin_lock_irqsave(&mes->ring_lock, flags);
        if (amdgpu_ring_alloc(ring, ndw)) {
                spin_unlock_irqrestore(&mes->ring_lock, flags);
+               amdgpu_device_wb_free(adev, fence_offset);
                return -ENOMEM;
        }
 
        api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
-       api_status->api_completion_fence_addr = mes->ring.fence_drv.gpu_addr;
-       api_status->api_completion_fence_value = ++mes->ring.fence_drv.sync_seq;
+       api_status->api_completion_fence_addr = fence_gpu_addr;
+       api_status->api_completion_fence_value = 1;
 
        amdgpu_ring_write_multiple(ring, pkt, ndw);
        amdgpu_ring_commit(ring);
@@ -199,8 +212,8 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
        else
                dev_dbg(adev->dev, "MES msg=%d was emitted\n", x_pkt->header.opcode);
 
-       r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq,
-                     timeout);
+       r = amdgpu_mes_fence_wait_polling(fence_ptr, (u64)1, timeout);
+       amdgpu_device_wb_free(adev, fence_offset);
        if (r < 1) {
 
                if (misc_op_str)