Am 29.04.24 um 08:43 schrieb Arunpravin Paneer Selvam:
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.

Signed-off-by: Arunpravin Paneer Selvam <arunpravin.paneersel...@amd.com>
---
  drivers/gpu/drm/amd/amdgpu/amdgpu.h           |  2 ++
  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |  5 ++--
  .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c   |  6 +++++
  drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c        | 25 ++++++++++---------
  drivers/gpu/drm/amd/amdgpu/mes_v10_1.c        |  5 ----
  drivers/gpu/drm/amd/amdgpu/mes_v11_0.c        |  7 ------
  6 files changed, 23 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 4ca14b02668b..2d5ef2e74c71 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1043,6 +1043,8 @@ struct amdgpu_device {
        struct amdgpu_mqd               mqds[AMDGPU_HW_IP_NUM];
        const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
+ struct xarray userq_xa;
+
        /* df */
        struct amdgpu_df                df;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 7753a2e64d41..fd919105a181 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3982,6 +3982,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        spin_lock_init(&adev->audio_endpt_idx_lock);
        spin_lock_init(&adev->mm_stats.lock);
+ xa_init_flags(&adev->userq_xa, XA_FLAGS_LOCK_IRQ);
+
        INIT_LIST_HEAD(&adev->shadow_list);
        mutex_init(&adev->shadow_list_lock);
@@ -4719,9 +4721,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
        }
        adev->in_suspend = false;
- if (adev->enable_mes)
-               amdgpu_mes_self_test(adev);
-

Since this patch here breaks the in kernel MES self test you should probably create a follow up patch to completely remove it.

(Or even better remove it before applying this patch).

        if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0))
                DRM_WARN("smart shift update failed\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 6fb75cc1d20c..614953b0fc19 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -70,6 +70,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);
@@ -96,6 +97,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;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index a786e25432ae..d6cdca0a652f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -49,6 +49,7 @@
  #include "gfx_v11_0_3.h"
  #include "nbio_v4_3.h"
  #include "mes_v11_0.h"
+#include "amdgpu_userq_fence.h"
#define GFX11_NUM_GFX_RINGS 1
  #define GFX11_MEC_HPD_SIZE    2048
@@ -5939,25 +5940,25 @@ 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 index, flags;
- mes_queue_id &= AMDGPU_FENCE_MES_QUEUE_ID_MASK;
+               xa_lock_irqsave(xa, flags);
+               xa_for_each(xa, index, fence_drv)
+                       if (doorbell_offset == index)
+                               break;

The array is indexed by the doorbell offset, so instead of going over all the entries you can just use xa_load().

+               xa_unlock_irqrestore(xa, flags);
- 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);
+               amdgpu_userq_fence_driver_process(fence_drv);

You need to make sure that the fence_drv isn't freed until this completes.

The easiest way would be to keep the xa lock until that is done.

        } else {
                me_id = (entry->ring_id & 0x0c) >> 2;
                pipe_id = (entry->ring_id & 0x03) >> 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c 
b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
index 4d1121d1a1e7..faa489c75fea 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -1163,11 +1163,6 @@ static int mes_v10_0_early_init(void *handle)
static int mes_v10_0_late_init(void *handle)
  {
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (!amdgpu_in_reset(adev))
-               amdgpu_mes_self_test(adev);
-
        return 0;
  }

You can completely drop the function. The callback is ignored when NULL.

diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index feb7fa2c304c..0051e2d6af86 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -1276,13 +1276,6 @@ static int mes_v11_0_early_init(void *handle)
static int mes_v11_0_late_init(void *handle)
  {
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       /* it's only intended for use in mes_self_test case, not for s0ix and 
reset */
-       if (!amdgpu_in_reset(adev) && !adev->in_s0ix && !adev->in_suspend &&
-           (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(11, 0, 3)))
-               amdgpu_mes_self_test(adev);
-
        return 0;
  }

Same here.

Regards,
Christian.


Reply via email to