PTL will limit access to specific registers. Instead of silently dropping these attempts, log them in dmesg for reference. Also add a dev_debug option to show what pasid/addr/packet type failed.
Signed-off-by: Kent Russell <[email protected]> --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 34 +++++++++ .../gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 76 +++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/soc15_int.h | 1 + 3 files changed, 111 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 3572eb9b5758..1ce8313e3c26 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -171,6 +171,7 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev, struct amdgpu_cu_info *cu_info); static void gfx_v9_4_3_xcc_set_safe_mode(struct amdgpu_device *adev, int xcc_id); static void gfx_v9_4_3_xcc_unset_safe_mode(struct amdgpu_device *adev, int xcc_id); +static void gfx_v9_4_3_enable_ptl_skip_interrupt(struct amdgpu_device *adev); static void gfx_v9_4_3_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue_mask) @@ -2661,6 +2662,7 @@ static int gfx_v9_4_3_early_init(struct amdgpu_ip_block *ip_block) static int gfx_v9_4_3_late_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_ptl *ptl = &adev->psp.ptl; if (adev->gfx.ras && adev->gfx.ras->enable_watchdog_timer) @@ -2668,6 +2670,10 @@ static int gfx_v9_4_3_late_init(struct amdgpu_ip_block *ip_block) gfx_v9_4_3_ptl_hw_init(adev); + /* Enable PTL register skip notifications if PTL is supported */ + if (ptl->hw_supported_state == AMDGPU_PTL_HW_SUPPORTED) + gfx_v9_4_3_enable_ptl_skip_interrupt(adev); + return 0; } @@ -3327,6 +3333,34 @@ static int gfx_v9_4_3_set_bad_op_fault_state(struct amdgpu_device *adev, return 0; } +/* + * Enable GENERIC1 interrupt (bit 30) for PTL register skip notifications. + * When FW skips a privileged register access due to PTL, it signals via + * GENERIC1 and KFD receives interrupt source 177 with skip details. + */ +static void gfx_v9_4_3_enable_ptl_skip_interrupt(struct amdgpu_device *adev) +{ + u32 mec_int_cntl_reg, mec_int_cntl; + int i, j, k, num_xcc; + + num_xcc = NUM_XCC(adev->gfx.xcc_mask); + for (i = 0; i < num_xcc; i++) { + for (j = 0; j < adev->gfx.mec.num_mec; j++) { + for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) { + mec_int_cntl_reg = gfx_v9_4_3_get_cpc_int_cntl(adev, i, j + 1, k); + + if (mec_int_cntl_reg) { + mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, i); + mec_int_cntl = REG_SET_FIELD(mec_int_cntl, + CP_ME1_PIPE0_INT_CNTL, + GENERIC1_INT_ENABLE, 1); + WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, i); + } + } + } + } +} + static int gfx_v9_4_3_set_priv_inst_fault_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned type, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index e241ad7d55df..8dee8c43824d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -123,6 +123,28 @@ enum SQ_INTERRUPT_ERROR_TYPE { #define KFD_SQ_INT_DATA__ERR_TYPE_MASK 0xF00000 #define KFD_SQ_INT_DATA__ERR_TYPE__SHIFT 20 +/* + * PTL (Peak TOPS Limiter) register skip notification. + * When FW skips a privileged register access, it sends interrupt 177 + * with GENERIC1 and provides packet type info in CPC_INT_CNTX_ID[31:28]. + */ +#define CPC_PTL_PACKET_TYPE_SET_UCONFIG_REG 1 +#define CPC_PTL_PACKET_TYPE_SET_SH_REG 2 +#define CPC_PTL_PACKET_TYPE_COPY_DATA_READ 3 +#define CPC_PTL_PACKET_TYPE_COPY_DATA_WRITE 4 +#define CPC_PTL_PACKET_TYPE_WRITE_DATA 5 +#define CPC_PTL_PACKET_TYPE_COND_WRITE 6 +#define CPC_PTL_PACKET_TYPE_WAIT_REG_MEM 7 +#define CPC_PTL_PACKET_TYPE_WAIT_REG_MEM64 8 + +/* CPC_INT_CNTX_ID[31:28]: packet type that was skipped */ +#define CPC_INT_CNTX_ID__PACKET_TYPE__SHIFT 28 +#define CPC_INT_CNTX_ID__PACKET_TYPE_MASK 0xF0000000 + +/* CPC_INT_INFO[30:28]: queue ID */ +#define CPC_INT_INFO__QUEUE_ID__SHIFT 28 +#define CPC_INT_INFO__QUEUE_ID_MASK 0x70000000 + /* * The debugger will send user data(m0) with PRIV=1 to indicate it requires * notification from the KFD with the following queue id (DOORBELL_ID) and @@ -142,6 +164,30 @@ enum SQ_INTERRUPT_ERROR_TYPE { KFD_DEBUG_CP_BAD_OP_ECODE_MASK) \ >> KFD_DEBUG_CP_BAD_OP_ECODE_SHIFT) +static const char *cpc_packet_type_name(uint32_t packet_type) +{ + switch (packet_type) { + case CPC_PTL_PACKET_TYPE_SET_UCONFIG_REG: + return "SET_UCONFIG_REG"; + case CPC_PTL_PACKET_TYPE_SET_SH_REG: + return "SET_SH_REG"; + case CPC_PTL_PACKET_TYPE_COPY_DATA_READ: + return "COPY_DATA_READ"; + case CPC_PTL_PACKET_TYPE_COPY_DATA_WRITE: + return "COPY_DATA_WRITE"; + case CPC_PTL_PACKET_TYPE_WRITE_DATA: + return "WRITE_DATA"; + case CPC_PTL_PACKET_TYPE_COND_WRITE: + return "COND_WRITE"; + case CPC_PTL_PACKET_TYPE_WAIT_REG_MEM: + return "WAIT_REG_MEM"; + case CPC_PTL_PACKET_TYPE_WAIT_REG_MEM64: + return "WAIT_REG_MEM64"; + default: + return "UNKNOWN"; + } +} + static void event_interrupt_poison_consumption_v9(struct kfd_node *dev, uint16_t pasid, uint16_t client_id) { @@ -352,6 +398,8 @@ static bool event_interrupt_isr_v9(struct kfd_node *dev, source_id == SOC15_INTSRC_SDMA_ECC || source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG || source_id == SOC15_INTSRC_CP_BAD_OPCODE || + (client_id == SOC15_IH_CLIENTID_GRBM_CP && + source_id == SOC15_INTSRC_CP_PTL_REG_SKIP) || KFD_IRQ_IS_FENCE(client_id, source_id) || ((client_id == SOC15_IH_CLIENTID_VMC || client_id == SOC15_IH_CLIENTID_VMC1 || @@ -538,6 +586,34 @@ static void event_interrupt_wq_v9(struct kfd_node *dev, KFD_DEBUG_DOORBELL_ID(context_id0), KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)), NULL, 0); + } else if (source_id == SOC15_INTSRC_CP_PTL_REG_SKIP) { + uint32_t packet_type, queue_id; + uint32_t skipped_addr; + + /* + * PTL (Peak TOPS Limiter) register skip notification. + * FW skipped a privileged register access and is notifying KFD. + * Data from IH entry (not registers): + * - context_id0 contains CPC_INT_CNTX_ID with packet type in [31:28] + * - context_id1 contains CPC_INT_INFO with queue ID in [30:28] + * - context_id2 contains CPC_INT_ADDR (skipped register address) + * - PASID comes from CPC_INT_PASID (already extracted from IH entry) + */ + skipped_addr = SOC15_CONTEXT_ID2_FROM_IH_ENTRY(ih_ring_entry); + + /* Extract packet type from CPC_INT_CNTX_ID[31:28] */ + packet_type = (context_id0 & CPC_INT_CNTX_ID__PACKET_TYPE_MASK) >> + CPC_INT_CNTX_ID__PACKET_TYPE__SHIFT; + + /* Extract queue ID from CPC_INT_INFO[30:28] */ + queue_id = (context_id1 & CPC_INT_INFO__QUEUE_ID_MASK) >> + CPC_INT_INFO__QUEUE_ID__SHIFT; + + dev_info_ratelimited(dev->adev->dev, + "PTL: AQL request was rejected due to incompatible user input; please verify your PTL configuration."); + dev_dbg_ratelimited(dev->adev->dev, + "PTL: register access skipped - pasid 0x%x, queue %u, packet %s, addr 0x%x\n", + pasid, queue_id, cpc_packet_type_name(packet_type), skipped_addr); } } else if (client_id == SOC15_IH_CLIENTID_SDMA0 || client_id == SOC15_IH_CLIENTID_SDMA1 || diff --git a/drivers/gpu/drm/amd/amdkfd/soc15_int.h b/drivers/gpu/drm/amd/amdkfd/soc15_int.h index e5c0205f2618..736b02ccdefb 100644 --- a/drivers/gpu/drm/amd/amdkfd/soc15_int.h +++ b/drivers/gpu/drm/amd/amdkfd/soc15_int.h @@ -25,6 +25,7 @@ #include "soc15_ih_clientid.h" +#define SOC15_INTSRC_CP_PTL_REG_SKIP 177 #define SOC15_INTSRC_CP_END_OF_PIPE 181 #define SOC15_INTSRC_CP_BAD_OPCODE 183 #define SOC15_INTSRC_SQ_INTERRUPT_MSG 239 -- 2.43.0
