Add the per-IP hardware wiring that drives the mes_dbgext core on
mes12.1 (mes_v12_1 / gfx_v12_1): handle MES_MISC_OP_SETUP_MES_DBGEXT in
the misc-op path, unmask the MES host (TIME_STAMP) interrupt across both
me3 pipes via the XCC-aware GRBM select, select the zoned buffer format
in sw_init(), start/stop the feature from hw_init()/hw_fini(), and drain
the log from the me3 EOP interrupt handler while the feature is active.

Signed-off-by: Yongqiang Sun <[email protected]>
Reviewed-by: Shaoyun Liu <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c | 19 +++++++
 drivers/gpu/drm/amd/amdgpu/mes_v12_1.c | 68 ++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
index 1589fc6413af5..4449691744a96 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
@@ -3515,6 +3515,25 @@ static int gfx_v12_1_eop_irq(struct amdgpu_device *adev,
 
        DRM_DEBUG("IH: CP EOP\n");
 
+       if (((entry->ring_id & 0x0c) >> 2) == 3) {
+               u32 type = amdgpu_mes_ih_int_type(doorbell_offset);
+
+               switch (type) {
+               case AMDGPU_MES_IH_INT_TYPE_DBGMSG:
+                       /*
+                        * MES firmware debug-extension ("mes_dbgext") messages 
are
+                        * delivered as an EOP interrupt from the MES scheduler 
pipe
+                        * (me 3).  Type is in context dword bits 31:26 
(MES_DBGMSG = 7).
+                        */
+                       if (adev->mes.dbgext_active)
+                               amdgpu_mes_dbgext_notify(adev, doorbell_offset);
+                       break;
+               default:
+                       break;
+               }
+               return 0;
+       }
+
        if (adev->enable_mes && doorbell_offset) {
                amdgpu_userq_process_fence_irq(adev, doorbell_offset);
        } else {
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c 
b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
index 5573fe981a220..5e4f929ba6b5c 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
@@ -42,6 +42,7 @@ static int mes_v12_1_hw_fini(struct amdgpu_ip_block 
*ip_block);
 static int mes_v12_1_kiq_hw_init(struct amdgpu_device *adev, uint32_t xcc_id);
 static int mes_v12_1_kiq_hw_fini(struct amdgpu_device *adev, uint32_t xcc_id);
 static int mes_v12_1_setup_coop_mode(struct amdgpu_device *adev, int xcc_id);
+static int mes_v12_1_enable_dbgext_irq(struct amdgpu_mes *mes, bool enable);
 
 #define MES_EOP_SIZE   2048
 #define MES12_HUNG_DB_OFFSET_ARRAY_SIZE 8 /* [0:3] = db offset [4:7] hqd info 
*/
@@ -639,6 +640,13 @@ static int mes_v12_1_misc_op(struct amdgpu_mes *mes,
                misc_pkt.change_config.option.bits.limit_single_process =
                        input->change_config.option.limit_single_process;
                break;
+       case MES_MISC_OP_SETUP_MES_DBGEXT:
+               misc_pkt.opcode = MESAPI_MISC__SETUP_MES_DBGEXT;
+               misc_pkt.dbgext_init_data.dbg_ext_mc_addr =
+                               input->setup_mes_dbgext.log_buffer_mc_addr;
+               misc_pkt.dbgext_init_data.u64_all =
+                               input->setup_mes_dbgext.log_options;
+               break;
        default:
                DRM_ERROR("unsupported misc op (%d) \n", input->op);
                return -EINVAL;
@@ -962,6 +970,52 @@ static int mes_v12_1_inv_tlbs_pasid(struct amdgpu_mes *mes,
 
 }
 
+/*
+ * Enable/disable delivery of the MES firmware host interrupts at the CP.  The
+ * MES firmware debug-message ("mes_dbgext") interrupt is delivered to the IH
+ * as a CP EOP (src_id 181) on the MES scheduler pipe (me 3) and handled in
+ * gfx_v12_1_eop_irq(); it is gated by CPC_INT_CNTL in the me3/MES pipe 
context,
+ * selected via GRBM_GFX_CNTL.  Must run in process context (takes srbm_mutex).
+ *
+ * Although the firmware C code passes Rs64HostIntrGeneric1IntEnable, the RS64
+ * library routine that actually raises the interrupt (AsmRs64SetHostIntr)
+ * hardcodes the TIME_STAMP assertion bit (CP_INT_STAT_DEBUG bit 26).  So
+ * TIME_STAMP_INT_ENABLE - not GENERIC1_INT_ENABLE - is the CPC_INT_CNTL bit
+ * that lets the CP forward the assertion to the host IH.  CPC_INT_CNTL is
+ * per-(me,pipe); the enable must be set on both me3 pipes (0 and 1), matching
+ * the Windows/SR-IOV KMD path - setting it only on the scheduler pipe is not
+ * sufficient.  Armed on every XCC, since each runs its own MES and logs into
+ * its own per-XCC buffer region.
+ */
+static int mes_v12_1_enable_dbgext_irq(struct amdgpu_mes *mes, bool enable)
+{
+       struct amdgpu_device *adev = mes->adev;
+       int num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+       u32 cp_int_cntl;
+       int pipe, xcc_id, inst;
+
+       mutex_lock(&adev->srbm_mutex);
+
+       for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
+               inst = GET_INST(GC, xcc_id);
+
+               for (pipe = 0; pipe < 2; pipe++) {
+                       soc_v1_0_grbm_select(adev, 3, pipe, 0, 0, inst);
+
+                       cp_int_cntl = RREG32_SOC15(GC, inst, regCPC_INT_CNTL);
+                       cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CPC_INT_CNTL,
+                                                   TIME_STAMP_INT_ENABLE, 
enable ? 1 : 0);
+                       WREG32_SOC15(GC, inst, regCPC_INT_CNTL, cp_int_cntl);
+               }
+
+               soc_v1_0_grbm_select(adev, 0, 0, 0, 0, inst);
+       }
+
+       mutex_unlock(&adev->srbm_mutex);
+
+       return 0;
+}
+
 static const struct amdgpu_mes_funcs mes_v12_1_funcs = {
        .add_hw_queue = mes_v12_1_add_hw_queue,
        .remove_hw_queue = mes_v12_1_remove_hw_queue,
@@ -973,6 +1027,7 @@ static const struct amdgpu_mes_funcs mes_v12_1_funcs = {
        .reset_hw_queue = mes_v12_1_reset_hw_queue,
        .detect_and_reset_hung_queues = mes_v12_1_detect_and_reset_hung_queues,
        .invalidate_tlbs_pasid = mes_v12_1_inv_tlbs_pasid,
+       .enable_dbgext_irq = mes_v12_1_enable_dbgext_irq,
 };
 
 static int mes_v12_1_allocate_ucode_buffer(struct amdgpu_device *adev,
@@ -1532,6 +1587,15 @@ static int mes_v12_1_sw_init(struct amdgpu_ip_block 
*ip_block)
        adev->mes.kiq_hw_fini = &mes_v12_1_kiq_hw_fini;
        adev->mes.enable_legacy_queue_map = true;
 
+       /*
+        * Enable mes_dbgext by default on mes12.1: seed an 8 KB runtime
+        * request so hw_init() -> amdgpu_mes_dbgext_start() brings the log up 
at
+        * boot with no mes_dbgext_buffer_size module param needed.  The
+        * collection mode still follows mes_dbgext_options (default bit0 = 1,
+        * interrupt-driven).  Both module params continue to override this.
+        */
+       adev->mes.dbgext_runtime_kb = 8;
+
        adev->mes.event_log_size = AMDGPU_MAX_MES_PIPES *
                                   AMDGPU_MES_LOG_BUFFER_SIZE * num_xcc;
 
@@ -1826,11 +1890,15 @@ static int mes_v12_1_hw_init(struct amdgpu_ip_block 
*ip_block)
                        return r;
        }
 
+       amdgpu_mes_dbgext_start(adev);
+
        return 0;
 }
 
 static int mes_v12_1_hw_fini(struct amdgpu_ip_block *ip_block)
 {
+       amdgpu_mes_dbgext_stop(ip_block->adev);
+
        return 0;
 }
 
-- 
2.43.0

Reply via email to