[PATCH] drm/amd/amdgpu: workaround for UVD busy status
Christian König
ckoenig.leichtzumerken at gmail.com
Wed Aug 14 17:20:59 UTC 2019
Am 14.08.19 um 18:58 schrieb Liu, Leo:
> On 2019-08-14 7:11 a.m., Kenneth Feng wrote:
>> On Vega20, tools depends on UVD_STATUS.VCPU_REPORT bit0
>> to decide if UVD instances are in busy state or idle state.
>> This workaround fixes the issue that tools always fetch the
>> UVD instances state as busy state no matter if there is a UVD work.
> The VCPU_REPORT is really for FW to report status to driver, not the
> other way around. Sounds to me this is a FW bug.
Agreed, but I wanted to double check the underlying background.
Looks like this is just for internal testing and shouldn't be upstreamed,
Christian.
>
> Regards,
>
> Leo
>
>
>> Signed-off-by: Kenneth Feng <kenneth.feng at amd.com>
>> ---
>> 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);
>> };
>>
>>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list