drm/amdgpu: add helper for rlcg indirect reg access
The helper will be used to access registers from sriov guest in full access time Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Zhou, Peng Ju <PengJu.Zhou@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
f8f96b17f0
commit
5d447e2967
@ -855,3 +855,114 @@ bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_fl
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag)
|
||||||
|
{
|
||||||
|
struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl;
|
||||||
|
uint32_t timeout = 50000;
|
||||||
|
uint32_t i, tmp;
|
||||||
|
uint32_t ret = 0;
|
||||||
|
static void *scratch_reg0;
|
||||||
|
static void *scratch_reg1;
|
||||||
|
static void *scratch_reg2;
|
||||||
|
static void *scratch_reg3;
|
||||||
|
static void *spare_int;
|
||||||
|
|
||||||
|
if (!adev->gfx.rlc.rlcg_reg_access_supported) {
|
||||||
|
dev_err(adev->dev,
|
||||||
|
"indirect registers access through rlcg is not available\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_reg0 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg0;
|
||||||
|
scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1;
|
||||||
|
scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2;
|
||||||
|
scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3;
|
||||||
|
if (reg_access_ctrl->spare_int)
|
||||||
|
spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int;
|
||||||
|
|
||||||
|
if (offset == reg_access_ctrl->grbm_cntl) {
|
||||||
|
/* if the target reg offset is grbm_cntl, write to scratch_reg2 */
|
||||||
|
writel(v, scratch_reg2);
|
||||||
|
writel(v, ((void __iomem *)adev->rmmio) + (offset * 4));
|
||||||
|
} else if (offset == reg_access_ctrl->grbm_idx) {
|
||||||
|
/* if the target reg offset is grbm_idx, write to scratch_reg3 */
|
||||||
|
writel(v, scratch_reg3);
|
||||||
|
writel(v, ((void __iomem *)adev->rmmio) + (offset * 4));
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* SCRATCH_REG0 = read/write value
|
||||||
|
* SCRATCH_REG1[30:28] = command
|
||||||
|
* SCRATCH_REG1[19:0] = address in dword
|
||||||
|
* SCRATCH_REG1[26:24] = Error reporting
|
||||||
|
*/
|
||||||
|
writel(v, scratch_reg0);
|
||||||
|
writel((offset | flag), scratch_reg1);
|
||||||
|
if (reg_access_ctrl->spare_int)
|
||||||
|
writel(1, spare_int);
|
||||||
|
|
||||||
|
for (i = 0; i < timeout; i++) {
|
||||||
|
tmp = readl(scratch_reg1);
|
||||||
|
if (!(tmp & flag))
|
||||||
|
break;
|
||||||
|
udelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= timeout) {
|
||||||
|
if (amdgpu_sriov_rlcg_error_report_enabled(adev)) {
|
||||||
|
if (tmp & AMDGPU_RLCG_VFGATE_DISABLED) {
|
||||||
|
dev_err(adev->dev,
|
||||||
|
"vfgate is disabled, rlcg failed to program reg: 0x%05x\n", offset);
|
||||||
|
} else if (tmp & AMDGPU_RLCG_WRONG_OPERATION_TYPE) {
|
||||||
|
dev_err(adev->dev,
|
||||||
|
"wrong operation type, rlcg failed to program reg: 0x%05x\n", offset);
|
||||||
|
} else if (tmp & AMDGPU_RLCG_REG_NOT_IN_RANGE) {
|
||||||
|
dev_err(adev->dev,
|
||||||
|
"regiser is not in range, rlcg failed to program reg: 0x%05x\n", offset);
|
||||||
|
} else {
|
||||||
|
dev_err(adev->dev,
|
||||||
|
"unknown error type, rlcg failed to program reg: 0x%05x\n", offset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dev_err(adev->dev,
|
||||||
|
"timeout: rlcg faled to program reg: 0x%05x\n", offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = readl(scratch_reg0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amdgpu_sriov_wreg(struct amdgpu_device *adev,
|
||||||
|
u32 offset, u32 value,
|
||||||
|
u32 acc_flags, u32 hwip)
|
||||||
|
{
|
||||||
|
u32 rlcg_flag;
|
||||||
|
|
||||||
|
if (!amdgpu_sriov_runtime(adev) &&
|
||||||
|
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) {
|
||||||
|
amdgpu_virt_rlcg_reg_rw(adev, offset, value, rlcg_flag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||||
|
WREG32_NO_KIQ(offset, value);
|
||||||
|
else
|
||||||
|
WREG32(offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
||||||
|
u32 offset, u32 acc_flags, u32 hwip)
|
||||||
|
{
|
||||||
|
u32 rlcg_flag;
|
||||||
|
|
||||||
|
if (!amdgpu_sriov_runtime(adev) &&
|
||||||
|
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag))
|
||||||
|
return amdgpu_virt_rlcg_reg_rw(adev, offset, 0, rlcg_flag);
|
||||||
|
|
||||||
|
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||||
|
return RREG32_NO_KIQ(offset);
|
||||||
|
else
|
||||||
|
return RREG32(offset);
|
||||||
|
}
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
#define AMDGPU_RLCG_GC_READ (0x1 << 28)
|
#define AMDGPU_RLCG_GC_READ (0x1 << 28)
|
||||||
#define AMDGPU_RLCG_MMHUB_WRITE (0x2 << 28)
|
#define AMDGPU_RLCG_MMHUB_WRITE (0x2 << 28)
|
||||||
|
|
||||||
|
/* error code for indirect register access path supported by rlcg for sriov */
|
||||||
|
#define AMDGPU_RLCG_VFGATE_DISABLED 0x4000000
|
||||||
|
#define AMDGPU_RLCG_WRONG_OPERATION_TYPE 0x2000000
|
||||||
|
#define AMDGPU_RLCG_REG_NOT_IN_RANGE 0x1000000
|
||||||
|
|
||||||
/* all asic after AI use this offset */
|
/* all asic after AI use this offset */
|
||||||
#define mmRCC_IOV_FUNC_IDENTIFIER 0xDE5
|
#define mmRCC_IOV_FUNC_IDENTIFIER 0xDE5
|
||||||
/* tonga/fiji use this offset */
|
/* tonga/fiji use this offset */
|
||||||
@ -281,6 +286,9 @@ struct amdgpu_video_codec_info;
|
|||||||
(amdgpu_sriov_vf((adev)) && \
|
(amdgpu_sriov_vf((adev)) && \
|
||||||
((adev)->virt.reg_access & (AMDGIM_FEATURE_GC_REG_RLC_EN)))
|
((adev)->virt.reg_access & (AMDGIM_FEATURE_GC_REG_RLC_EN)))
|
||||||
|
|
||||||
|
#define amdgpu_sriov_rlcg_error_report_enabled(adev) \
|
||||||
|
(amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev))
|
||||||
|
|
||||||
#define amdgpu_passthrough(adev) \
|
#define amdgpu_passthrough(adev) \
|
||||||
((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE)
|
((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE)
|
||||||
|
|
||||||
@ -299,7 +307,6 @@ static inline bool is_virtual_machine(void)
|
|||||||
((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug)
|
((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug)
|
||||||
#define amdgpu_sriov_is_normal(adev) \
|
#define amdgpu_sriov_is_normal(adev) \
|
||||||
((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug))
|
((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug))
|
||||||
|
|
||||||
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
|
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
|
||||||
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
|
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
|
||||||
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
|
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
|
||||||
@ -329,4 +336,9 @@ void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_video_codec_info *decode, uint32_t decode_array_size);
|
struct amdgpu_video_codec_info *decode, uint32_t decode_array_size);
|
||||||
bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_flags,
|
bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_flags,
|
||||||
u32 hwip, bool write, u32 *rlcg_flag);
|
u32 hwip, bool write, u32 *rlcg_flag);
|
||||||
|
void amdgpu_sriov_wreg(struct amdgpu_device *adev,
|
||||||
|
u32 offset, u32 value,
|
||||||
|
u32 acc_flags, u32 hwip);
|
||||||
|
u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
||||||
|
u32 offset, u32 acc_flags, u32 hwip);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user