Signed-off-by: Kenneth Feng <kenneth.feng@xxxxxxx>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +++
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 23 +++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 30 ++++++++++++++++++++++++++++--
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 19 +++++++++++++++++++
drivers/gpu/drm/amd/include/amd_shared.h | 1 +
5 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 4d096ff..6e5a41b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -259,6 +259,9 @@ int amdgpu_device_ip_set_clockgating_state(void *dev,
int amdgpu_device_ip_set_powergating_state(void *dev,
enum amd_ip_block_type block_type,
enum amd_powergating_state state);
+int amdgpu_device_ip_set_instance_state(void *dev,
+ enum amd_ip_block_type block_type,
+ bool busy_state, int inst);
void amdgpu_device_ip_get_clockgating_state(struct amdgpu_device *adev,
u32 *flags);
int amdgpu_device_ip_wait_for_idle(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 93ed3cb..e65e251 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1127,6 +1127,29 @@ int amdgpu_device_ip_set_powergating_state(void *dev,
return r;
}
+int amdgpu_device_ip_set_instance_state(void *dev,
+ enum amd_ip_block_type block_type,
+ bool busy_state, int inst)
+{
+ struct amdgpu_device *adev = dev;
+ int i, r = 0;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.valid)
+ continue;
+ if (adev->ip_blocks[i].version->type != block_type)
+ continue;
+ if (!adev->ip_blocks[i].version->funcs->set_instance_state)
+ continue;
+ r = adev->ip_blocks[i].version->funcs->set_instance_state(
+ (void *)adev, busy_state, inst);
+ if (r)
+ DRM_ERROR("set_instance_state of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
+ }
+ return r;
+}
+
/**
* amdgpu_device_ip_get_clockgating_state - get the CG state
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 4e5d13e4..d3496ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -1180,13 +1180,22 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
struct amdgpu_device *adev =
container_of(work, struct amdgpu_device, uvd.idle_work.work);
unsigned fences = 0, i, j;
+ unsigned *fences_inst = (unsigned *)kzalloc(adev->uvd.num_uvd_inst*sizeof(unsigned), GFP_KERNEL);
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
if (adev->uvd.harvest_config & (1 << i))
continue;
- fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring);
+ fences_inst[i] = amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring);
+ fences += fences_inst[i];
for (j = 0; j < adev->uvd.num_enc_rings; ++j) {
- fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring_enc[j]);
+ fences_inst[i] += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring_enc[j]);
+ fences += fences_inst[i];
+ }
+ /* workaround for the tools to show UVD busy status */
+ if (fences_inst[i] == 0) {
+ amdgpu_device_ip_set_instance_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ false, i);
+ printk("Kenneth - set instance idle!\n");
}
}
@@ -1210,10 +1219,27 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
bool set_clocks;
+ unsigned i,j;
+ unsigned *fences_inst = (unsigned *)kzalloc(adev->uvd.num_uvd_inst*sizeof(unsigned), GFP_KERNEL);
if (amdgpu_sriov_vf(adev))
return;
+ for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
+ printk("Kenneth - run after set_clock!\n");
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
+ fences_inst[i] = amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring);
+ for (j = 0; j < adev->uvd.num_enc_rings; ++j)
+ fences_inst[i] += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring_enc[j]);
+ /* workaround for the tools to show UVD busy */
+ if (fences_inst[i] != 0) {
+ amdgpu_device_ip_set_instance_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ true, i);
+ printk("Kenneth - run in setting instance state!\n");
+ }
+ }
+
set_clocks = !cancel_delayed_work_sync(&adev->uvd.idle_work);
if (set_clocks) {
if (adev->pm.dpm_enabled) {
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index 2f3d4e8..bf0f33a 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -1738,6 +1738,24 @@ static int uvd_v7_0_set_clockgating_state(void *handle,
return 0;
}
+/* workaround for tools to fetch the UVD busy status */
+static int uvd_v7_0_set_instance_state(void *handle, bool busy_state, int inst)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ if(inst >= adev->uvd.num_uvd_inst)
+ return -EINVAL;
+
+ if(busy_state)
+ WREG32_P(SOC15_REG_OFFSET(UVD, inst, mmUVD_STATUS), (1 << UVD_STATUS__VCPU_REPORT__SHIFT),
+ ~(1 << UVD_STATUS__VCPU_REPORT__SHIFT));
+ else
+ WREG32_P(SOC15_REG_OFFSET(UVD, inst, mmUVD_STATUS), 0,
+ ~(1 << UVD_STATUS__VCPU_REPORT__SHIFT));
+
+ return 0;
+}
+
const struct amd_ip_funcs uvd_v7_0_ip_funcs = {
.name = "uvd_v7_0",
.early_init = uvd_v7_0_early_init,
@@ -1756,6 +1774,7 @@ const struct amd_ip_funcs uvd_v7_0_ip_funcs = {
.post_soft_reset = NULL /* uvd_v7_0_post_soft_reset */,
.set_clockgating_state = uvd_v7_0_set_clockgating_state,
.set_powergating_state = NULL /* uvd_v7_0_set_powergating_state */,
+ .set_instance_state = uvd_v7_0_set_instance_state,
};
static const struct amdgpu_ring_funcs uvd_v7_0_ring_vm_funcs = {
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index 779c9e7..8cc54c9 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -198,6 +198,7 @@ struct amd_ip_funcs {
void (*get_clockgating_state)(void *handle, u32 *flags);
/** @enable_umd_pstate: enable UMD powerstate */
int (*enable_umd_pstate)(void *handle, enum amd_dpm_forced_level *level);
+ int (*set_instance_state)(void *handle, bool busy_state, int inst);
};