[why] Some register values span two consecutive dwords and must be sampled with one MES operation.
[how] Add amdgpu_mes_rreg64(), set READ_REG read64Bits for MES 11 and MES 12, and combine the two returned dwords into a 64-bit value. Reject 64-bit reads on MES 11 scheduler firmware older than 0x42, which predates read64Bits support. v2: add MES 11 support with the same read64Bits option v3: return read status separately and require MES 11 firmware 0x42 or newer Signed-off-by: Victor Zhao <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 43 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 3 ++ drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 6 +++ drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 2 + drivers/gpu/drm/amd/amdgpu/mes_v12_1.c | 2 + drivers/gpu/drm/amd/include/mes_v11_api_def.h | 7 +++ 6 files changed, 63 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index 5bebe74de01ad..3be6e577a8aa7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -582,6 +582,7 @@ uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg, op_input.op = MES_MISC_OP_READ_REG; op_input.read_reg.reg_offset = reg; op_input.read_reg.buffer_addr = read_val_gpu_addr; + op_input.read_reg.read64_bits = false; if (!adev->mes.funcs->misc_op) { dev_err(adev->dev, "mes rreg is not supported!\n"); @@ -602,6 +603,48 @@ uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg, return val; } +int amdgpu_mes_rreg64(struct amdgpu_device *adev, uint32_t reg, + uint32_t xcc_id, uint64_t *val) +{ + struct mes_misc_op_input op_input = { 0 }; + uint32_t addr_offset; + uint32_t *read_val_ptr; + int r; + + r = amdgpu_wb_get(adev, &addr_offset); + if (r) { + dev_err(adev->dev, "critical bug! too many mes readers\n"); + return r; + } + + read_val_ptr = (uint32_t *)&adev->wb.wb[addr_offset]; + op_input.xcc_id = xcc_id; + op_input.op = MES_MISC_OP_READ_REG; + op_input.read_reg.reg_offset = reg; + op_input.read_reg.buffer_addr = adev->wb.gpu_addr + addr_offset * 4; + op_input.read_reg.read64_bits = true; + + if (!adev->mes.funcs->misc_op) { + dev_err(adev->dev, "mes rreg is not supported!\n"); + r = -EINVAL; + goto error; + } + + amdgpu_mes_lock(&adev->mes); + r = adev->mes.funcs->misc_op(&adev->mes, &op_input); + amdgpu_mes_unlock(&adev->mes); + if (r) { + dev_err(adev->dev, "failed to read reg (0x%x)\n", reg); + } else { + *val = READ_ONCE(read_val_ptr[0]); + *val |= (uint64_t)READ_ONCE(read_val_ptr[1]) << 32; + } + +error: + amdgpu_wb_free(adev, addr_offset); + return r; +} + int amdgpu_mes_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t val, uint32_t xcc_id) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index 33a426f58e723..1e801f427ddb2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -373,6 +373,7 @@ struct mes_misc_op_input { struct { uint32_t reg_offset; uint64_t buffer_addr; + bool read64_bits; } read_reg; struct { @@ -545,6 +546,8 @@ int amdgpu_mes_detect_and_reset_hung_queues(struct amdgpu_device *adev, uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_id); +int amdgpu_mes_rreg64(struct amdgpu_device *adev, uint32_t reg, + uint32_t xcc_id, uint64_t *val); int amdgpu_mes_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t val, uint32_t xcc_id); int amdgpu_mes_reg_write_reg_wait(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index d8b4d3deff605..ef82f7536e449 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -902,9 +902,15 @@ static int mes_v11_0_misc_op(struct amdgpu_mes *mes, switch (input->op) { case MES_MISC_OP_READ_REG: + if (input->read_reg.read64_bits && + (mes->sched_version & AMDGPU_MES_VERSION_MASK) < 0x42) + return -EOPNOTSUPP; + misc_pkt.opcode = MESAPI_MISC__READ_REG; misc_pkt.read_reg.reg_offset = input->read_reg.reg_offset; misc_pkt.read_reg.buffer_addr = input->read_reg.buffer_addr; + misc_pkt.read_reg.option.bits.read64Bits = + input->read_reg.read64_bits; break; case MES_MISC_OP_WRITE_REG: misc_pkt.opcode = MESAPI_MISC__WRITE_REG; diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c index 04465804c2544..0d2a60528802e 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c @@ -858,6 +858,8 @@ static int mes_v12_0_misc_op(struct amdgpu_mes *mes, misc_pkt.opcode = MESAPI_MISC__READ_REG; misc_pkt.read_reg.reg_offset = input->read_reg.reg_offset; misc_pkt.read_reg.buffer_addr = input->read_reg.buffer_addr; + misc_pkt.read_reg.option.bits.read64Bits = + input->read_reg.read64_bits; break; case MES_MISC_OP_WRITE_REG: misc_pkt.opcode = MESAPI_MISC__WRITE_REG; diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c index d17ced46d5f73..e0a488e516c09 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c @@ -581,6 +581,8 @@ static int mes_v12_1_misc_op(struct amdgpu_mes *mes, case MES_MISC_OP_READ_REG: misc_pkt.opcode = MESAPI_MISC__READ_REG; misc_pkt.read_reg.buffer_addr = input->read_reg.buffer_addr; + misc_pkt.read_reg.option.bits.read64Bits = + input->read_reg.read64_bits; mes_v12_1_get_rrmt(input->read_reg.reg_offset, GET_INST(GC, input->xcc_id), &misc_pkt.read_reg.rrmt_opt, diff --git a/drivers/gpu/drm/amd/include/mes_v11_api_def.h b/drivers/gpu/drm/amd/include/mes_v11_api_def.h index 1fe824b41f2a5..b27ec78da3b08 100644 --- a/drivers/gpu/drm/amd/include/mes_v11_api_def.h +++ b/drivers/gpu/drm/amd/include/mes_v11_api_def.h @@ -635,6 +635,13 @@ struct WRITE_REG { struct READ_REG { uint32_t reg_offset; uint64_t buffer_addr; + union { + struct { + uint32_t read64Bits : 1; + uint32_t reserved : 31; + } bits; + uint32_t all; + } option; }; enum WRM_OPERATION { -- 2.50.1
