This commit introduces HQD PQ address retrieval functionality for GFX11 hardware by:
1. Adding hqd_get_pq_addr function pointer to amdgpu_mqd structure 2. Implementing gfx_v11_0_hqd_get_pq_addr() for GFX11 3. Registering the function in gfx_v11_0_set_mqd_funcs() Key features: - Supports XCC instances for Compute queues - Checks HQD active status before accessing registers - Provides accurate queue address calculation combining high/low registers - Maintains compatibility with existing reset mechanisms This functionality will be used for hang detection and queue management operations that need to identify specific hardware queues. Signed-off-by: Jesse Zhang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +++ drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 49 ++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 7365558f47a1..927375ebafa1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -892,6 +892,10 @@ struct amdgpu_mqd { unsigned mqd_size; int (*init_mqd)(struct amdgpu_device *adev, void *mqd, struct amdgpu_mqd_prop *p); + uint64_t (*hqd_get_pq_addr)(struct amdgpu_device *adev, uint32_t queue_type, + uint32_t me_id, uint32_t pipe_id, uint32_t queue_id, + uint32_t xcc_id, uint32_t *vmid); + }; struct amdgpu_pcie_reset_ctx { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index afd6d59164bf..95509adabd77 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4152,6 +4152,51 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, return 0; } +static uint64_t gfx_v11_0_hqd_get_pq_addr(struct amdgpu_device *adev, uint32_t queue_type, + uint32_t me_id, uint32_t pipe_id, uint32_t queue_id, + uint32_t xcc_id, uint32_t *vmid) +{ + uint32_t low = 0, high = 0, active = 0; + uint64_t queue_addr = 0; + + mutex_lock(&adev->srbm_mutex); + /* Enter safe mode to safely access HQD registers */ + amdgpu_gfx_rlc_enter_safe_mode(adev, xcc_id); + + + /* Select the specific ME/PIPE/QUEUE to access its HQD registers */ + soc21_grbm_select(adev, me_id, pipe_id, queue_id, 0); + + if (queue_type == AMDGPU_RING_TYPE_GFX) { + active = RREG32_SOC15(GC, 0, regCP_GFX_HQD_ACTIVE); + if (!(active & 1)) + goto unlock_out; + + *vmid = RREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID); + low = RREG32_SOC15(GC, 0, regCP_GFX_HQD_BASE); + high = RREG32_SOC15(GC, 0, regCP_GFX_HQD_BASE_HI); + + queue_addr = (((uint64_t)high << 32) | low) << 8; + } else if (queue_type == AMDGPU_RING_TYPE_COMPUTE) { + active = RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE); + if (!(active & 1)) + goto unlock_out; + + *vmid = RREG32_SOC15(GC, 0, regCP_HQD_VMID); + low = RREG32_SOC15(GC, 0, regCP_HQD_PQ_BASE); + high = RREG32_SOC15(GC, 0, regCP_HQD_PQ_BASE_HI); + + queue_addr = (((uint64_t)high << 32) | low) << 8; + } + +unlock_out: + soc21_grbm_select(adev, 0, 0, 0, 0); + amdgpu_gfx_rlc_exit_safe_mode(adev, 0); + mutex_unlock(&adev->srbm_mutex); + + return queue_addr; +} + static int gfx_v11_0_kgq_init_queue(struct amdgpu_ring *ring, bool reset) { struct amdgpu_device *adev = ring->adev; @@ -7400,11 +7445,15 @@ static void gfx_v11_0_set_mqd_funcs(struct amdgpu_device *adev) sizeof(struct v11_gfx_mqd); adev->mqds[AMDGPU_HW_IP_GFX].init_mqd = gfx_v11_0_gfx_mqd_init; + adev->mqds[AMDGPU_HW_IP_GFX].hqd_get_pq_addr = + gfx_v11_0_hqd_get_pq_addr; /* set compute eng mqd */ adev->mqds[AMDGPU_HW_IP_COMPUTE].mqd_size = sizeof(struct v11_compute_mqd); adev->mqds[AMDGPU_HW_IP_COMPUTE].init_mqd = gfx_v11_0_compute_mqd_init; + adev->mqds[AMDGPU_HW_IP_COMPUTE].hqd_get_pq_addr = + gfx_v11_0_hqd_get_pq_addr; } static void gfx_v11_0_set_user_wgp_inactive_bitmap_per_sh(struct amdgpu_device *adev, -- 2.49.0
