<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body>
<p style="font-family:Arial;font-size:10pt;color:#008000;margin:15pt;" align="Left">
[Public]<br>
</p>
<br>
<div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
Ah.. didn't notice that. As I mentioned, it's mainly a cosmetic/semantic thing. AFAIU, hw_fini() is expected to be called once when hw is removed/reset or driver is removed. Suspend is temporary and may be called multiple times during the lifetime. So calling
 hw_fini() from suspend() appears a bit odd (probably just for me).</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
<br>
</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
If it's worth, something like this -</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
<br>
</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
vce_4_2_suspend() {</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
<br>
</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
__vce_4_2_suspend();</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
....</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
// Anything extra</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
}</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
<br>
</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
vce_4_2_hw_fini() {</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
<br>
</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
__vce_4_2_suspend();</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
<br>
</div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
}</div>
<div id="ms-outlook-mobile-signature" dir="auto">
<div dir="auto"><br>
</div>
Thanks,<br>
Lijo</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Grodzovsky, Andrey <Andrey.Grodzovsky@amd.com><br>
<b>Sent:</b> Thursday, September 16, 2021 9:47:41 PM<br>
<b>To:</b> Lazar, Lijo <Lijo.Lazar@amd.com>; amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org><br>
<b>Cc:</b> Quan, Evan <Evan.Quan@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; Deucher, Alexander <Alexander.Deucher@amd.com><br>
<b>Subject:</b> Re: [PATCH] drm/amdgpu: Fix crash on device remove/driver unload</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText"><br>
On 2021-09-16 11:51 a.m., Lazar, Lijo wrote:<br>
><br>
><br>
> On 9/16/2021 9:15 PM, Andrey Grodzovsky wrote:<br>
>><br>
>> On 2021-09-16 4:20 a.m., Lazar, Lijo wrote:<br>
>>> A minor comment below.<br>
>>><br>
>>> On 9/16/2021 1:11 AM, Andrey Grodzovsky wrote:<br>
>>>> Crash:<br>
>>>> BUG: unable to handle page fault for address: 00000000000010e1<br>
>>>> RIP: 0010:vega10_power_gate_vce+0x26/0x50 [amdgpu]<br>
>>>> Call Trace:<br>
>>>> pp_set_powergating_by_smu+0x16a/0x2b0 [amdgpu]<br>
>>>> amdgpu_dpm_set_powergating_by_smu+0x92/0xf0 [amdgpu]<br>
>>>> amdgpu_dpm_enable_vce+0x2e/0xc0 [amdgpu]<br>
>>>> vce_v4_0_hw_fini+0x95/0xa0 [amdgpu]<br>
>>>> amdgpu_device_fini_hw+0x232/0x30d [amdgpu]<br>
>>>> amdgpu_driver_unload_kms+0x5c/0x80 [amdgpu]<br>
>>>> amdgpu_pci_remove+0x27/0x40 [amdgpu]<br>
>>>> pci_device_remove+0x3e/0xb0<br>
>>>> device_release_driver_internal+0x103/0x1d0<br>
>>>> device_release_driver+0x12/0x20<br>
>>>> pci_stop_bus_device+0x79/0xa0<br>
>>>> pci_stop_and_remove_bus_device_locked+0x1b/0x30<br>
>>>> remove_store+0x7b/0x90<br>
>>>> dev_attr_store+0x17/0x30<br>
>>>> sysfs_kf_write+0x4b/0x60<br>
>>>> kernfs_fop_write_iter+0x151/0x1e0<br>
>>>><br>
>>>> Why:<br>
>>>> VCE/UVD had dependency on SMC block for their suspend but<br>
>>>> SMC block is the first to do HW fini due to some constraints<br>
>>>><br>
>>>> How:<br>
>>>> Since the original patch was dealing with suspend issues<br>
>>>> move the SMC block dependency back into suspend hooks as<br>
>>>> was done in V1 of the original patches.<br>
>>>> Keep flushing idle work both in suspend and HW fini seuqnces<br>
>>>> since it's essential in both cases.<br>
>>>><br>
>>>> Fixes:<br>
>>>> 2178d3c189b9 drm/amdgpu: add missing cleanups for more ASICs on <br>
>>>> UVD/VCE suspend<br>
>>>> ee6679aaa61c drm/amdgpu: add missing cleanups for Polaris12 UVD/VCE <br>
>>>> on suspend<br>
>>>> Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com><br>
>>>> ---<br>
>>>>   drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 24 ++++++++-------<br>
>>>>   drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 24 ++++++++-------<br>
>>>>   drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 24 ++++++++-------<br>
>>>>   drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 32 ++++++++++---------<br>
>>>>   drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 19 +++++++-----<br>
>>>>   drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 28 +++++++++--------<br>
>>>>   drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 44 <br>
>>>> ++++++++++++++-------------<br>
>>>>   7 files changed, 105 insertions(+), 90 deletions(-)<br>
>>>><br>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c <br>
>>>> b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c<br>
>>>> index 7232241e3bfb..0fef925b6602 100644<br>
>>>> --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c<br>
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c<br>
>>>> @@ -698,6 +698,19 @@ static int uvd_v3_1_hw_fini(void *handle)<br>
>>>>   {<br>
>>>>       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>>   + cancel_delayed_work_sync(&adev->uvd.idle_work);<br>
>>>> +<br>
>>>> +    if (RREG32(mmUVD_STATUS) != 0)<br>
>>>> +        uvd_v3_1_stop(adev);<br>
>>>> +<br>
>>>> +    return 0;<br>
>>>> +}<br>
>>>> +<br>
>>>> +static int uvd_v3_1_suspend(void *handle)<br>
>>>> +{<br>
>>>> +    int r;<br>
>>>> +    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> +<br>
>>>>       /*<br>
>>>>        * Proper cleanups before halting the HW engine:<br>
>>>>        *   - cancel the delayed idle work<br>
>>>> @@ -722,17 +735,6 @@ static int uvd_v3_1_hw_fini(void *handle)<br>
>>>>                                  AMD_CG_STATE_GATE);<br>
>>>>       }<br>
>>>>   -    if (RREG32(mmUVD_STATUS) != 0)<br>
>>>> -        uvd_v3_1_stop(adev);<br>
>>>> -<br>
>>>> -    return 0;<br>
>>>> -}<br>
>>>> -<br>
>>>> -static int uvd_v3_1_suspend(void *handle)<br>
>>>> -{<br>
>>>> -    int r;<br>
>>>> -    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> -<br>
>>>>       r = uvd_v3_1_hw_fini(adev);<br>
>>><br>
>>> "cosmetic change" comment - hw_fini is supposed to be the final tear <br>
>>> down call. So instead of suspend calling hw_fini, perhaps it makes <br>
>>> sense to read the other way - hw_fini just suspends the hardware?<br>
>>><br>
>>> Thanks,<br>
>>> Lijo<br>
>><br>
>><br>
>> Not sure what you mean ?<br>
><br>
> Now it is - suspend()-> calls hw_fini()<br>
><br>
> What I meant is hw_fini() -> calls suspend() and that is read as "to <br>
> do hw_fini() only suspend the hardware and nothing extra is needed".<br>
><br>
> In short implementation stays in suspend() and hw_fini() calls suspend().<br>
<br>
<br>
Sorry, still confused, what about amdgpu_vce_suspend being called from <br>
vce_v4_0_suspend for example - we don't want that to be called from hw_fini.<br>
Can you maybe show draft change of what you mean for one specific UVD or <br>
VCE version ?<br>
<br>
Andrey<br>
<br>
<br>
><br>
> Thanks,<br>
> Lijo<br>
><br>
>><br>
>> Andrey<br>
>><br>
>><br>
>>><br>
>>>>       if (r)<br>
>>>>           return r;<br>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c <br>
>>>> b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c<br>
>>>> index 52d6de969f46..c108b8381795 100644<br>
>>>> --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c<br>
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c<br>
>>>> @@ -212,6 +212,19 @@ static int uvd_v4_2_hw_fini(void *handle)<br>
>>>>   {<br>
>>>>       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>>   + cancel_delayed_work_sync(&adev->uvd.idle_work);<br>
>>>> +<br>
>>>> +    if (RREG32(mmUVD_STATUS) != 0)<br>
>>>> +        uvd_v4_2_stop(adev);<br>
>>>> +<br>
>>>> +    return 0;<br>
>>>> +}<br>
>>>> +<br>
>>>> +static int uvd_v4_2_suspend(void *handle)<br>
>>>> +{<br>
>>>> +    int r;<br>
>>>> +    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> +<br>
>>>>       /*<br>
>>>>        * Proper cleanups before halting the HW engine:<br>
>>>>        *   - cancel the delayed idle work<br>
>>>> @@ -236,17 +249,6 @@ static int uvd_v4_2_hw_fini(void *handle)<br>
>>>>                                  AMD_CG_STATE_GATE);<br>
>>>>       }<br>
>>>>   -    if (RREG32(mmUVD_STATUS) != 0)<br>
>>>> -        uvd_v4_2_stop(adev);<br>
>>>> -<br>
>>>> -    return 0;<br>
>>>> -}<br>
>>>> -<br>
>>>> -static int uvd_v4_2_suspend(void *handle)<br>
>>>> -{<br>
>>>> -    int r;<br>
>>>> -    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> -<br>
>>>>       r = uvd_v4_2_hw_fini(adev);<br>
>>>>       if (r)<br>
>>>>           return r;<br>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c <br>
>>>> b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c<br>
>>>> index db6d06758e4d..563493d1f830 100644<br>
>>>> --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c<br>
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c<br>
>>>> @@ -210,6 +210,19 @@ static int uvd_v5_0_hw_fini(void *handle)<br>
>>>>   {<br>
>>>>       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>>   + cancel_delayed_work_sync(&adev->uvd.idle_work);<br>
>>>> +<br>
>>>> +    if (RREG32(mmUVD_STATUS) != 0)<br>
>>>> +        uvd_v5_0_stop(adev);<br>
>>>> +<br>
>>>> +    return 0;<br>
>>>> +}<br>
>>>> +<br>
>>>> +static int uvd_v5_0_suspend(void *handle)<br>
>>>> +{<br>
>>>> +    int r;<br>
>>>> +    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> +<br>
>>>>       /*<br>
>>>>        * Proper cleanups before halting the HW engine:<br>
>>>>        *   - cancel the delayed idle work<br>
>>>> @@ -234,17 +247,6 @@ static int uvd_v5_0_hw_fini(void *handle)<br>
>>>>                                  AMD_CG_STATE_GATE);<br>
>>>>       }<br>
>>>>   -    if (RREG32(mmUVD_STATUS) != 0)<br>
>>>> -        uvd_v5_0_stop(adev);<br>
>>>> -<br>
>>>> -    return 0;<br>
>>>> -}<br>
>>>> -<br>
>>>> -static int uvd_v5_0_suspend(void *handle)<br>
>>>> -{<br>
>>>> -    int r;<br>
>>>> -    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> -<br>
>>>>       r = uvd_v5_0_hw_fini(adev);<br>
>>>>       if (r)<br>
>>>>           return r;<br>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c <br>
>>>> b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c<br>
>>>> index b6e82d75561f..1fd9ca21a091 100644<br>
>>>> --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c<br>
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c<br>
>>>> @@ -606,6 +606,23 @@ static int uvd_v7_0_hw_fini(void *handle)<br>
>>>>   {<br>
>>>>       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>>   + cancel_delayed_work_sync(&adev->uvd.idle_work);<br>
>>>> +<br>
>>>> +    if (!amdgpu_sriov_vf(adev))<br>
>>>> +        uvd_v7_0_stop(adev);<br>
>>>> +    else {<br>
>>>> +        /* full access mode, so don't touch any UVD register */<br>
>>>> +        DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");<br>
>>>> +    }<br>
>>>> +<br>
>>>> +    return 0;<br>
>>>> +}<br>
>>>> +<br>
>>>> +static int uvd_v7_0_suspend(void *handle)<br>
>>>> +{<br>
>>>> +    int r;<br>
>>>> +    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> +<br>
>>>>       /*<br>
>>>>        * Proper cleanups before halting the HW engine:<br>
>>>>        *   - cancel the delayed idle work<br>
>>>> @@ -630,21 +647,6 @@ static int uvd_v7_0_hw_fini(void *handle)<br>
>>>>                                  AMD_CG_STATE_GATE);<br>
>>>>       }<br>
>>>>   -    if (!amdgpu_sriov_vf(adev))<br>
>>>> -        uvd_v7_0_stop(adev);<br>
>>>> -    else {<br>
>>>> -        /* full access mode, so don't touch any UVD register */<br>
>>>> -        DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");<br>
>>>> -    }<br>
>>>> -<br>
>>>> -    return 0;<br>
>>>> -}<br>
>>>> -<br>
>>>> -static int uvd_v7_0_suspend(void *handle)<br>
>>>> -{<br>
>>>> -    int r;<br>
>>>> -    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> -<br>
>>>>       r = uvd_v7_0_hw_fini(adev);<br>
>>>>       if (r)<br>
>>>>           return r;<br>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c <br>
>>>> b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c<br>
>>>> index 84e488f189f5..67eb01fef789 100644<br>
>>>> --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c<br>
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c<br>
>>>> @@ -481,6 +481,17 @@ static int vce_v2_0_hw_fini(void *handle)<br>
>>>>   {<br>
>>>>       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>>   + cancel_delayed_work_sync(&adev->vce.idle_work);<br>
>>>> +<br>
>>>> +    return 0;<br>
>>>> +}<br>
>>>> +<br>
>>>> +static int vce_v2_0_suspend(void *handle)<br>
>>>> +{<br>
>>>> +    int r;<br>
>>>> +    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> +<br>
>>>> +<br>
>>>>       /*<br>
>>>>        * Proper cleanups before halting the HW engine:<br>
>>>>        *   - cancel the delayed idle work<br>
>>>> @@ -504,14 +515,6 @@ static int vce_v2_0_hw_fini(void *handle)<br>
>>>>                                  AMD_CG_STATE_GATE);<br>
>>>>       }<br>
>>>>   -    return 0;<br>
>>>> -}<br>
>>>> -<br>
>>>> -static int vce_v2_0_suspend(void *handle)<br>
>>>> -{<br>
>>>> -    int r;<br>
>>>> -    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> -<br>
>>>>       r = vce_v2_0_hw_fini(adev);<br>
>>>>       if (r)<br>
>>>>           return r;<br>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c <br>
>>>> b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c<br>
>>>> index 2a18c1e089fd..142e291983b4 100644<br>
>>>> --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c<br>
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c<br>
>>>> @@ -492,6 +492,21 @@ static int vce_v3_0_hw_fini(void *handle)<br>
>>>>       int r;<br>
>>>>       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>>   + cancel_delayed_work_sync(&adev->vce.idle_work);<br>
>>>> +<br>
>>>> +    r = vce_v3_0_wait_for_idle(handle);<br>
>>>> +    if (r)<br>
>>>> +        return r;<br>
>>>> +<br>
>>>> +    vce_v3_0_stop(adev);<br>
>>>> +    return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE);<br>
>>>> +}<br>
>>>> +<br>
>>>> +static int vce_v3_0_suspend(void *handle)<br>
>>>> +{<br>
>>>> +    int r;<br>
>>>> +    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> +<br>
>>>>       /*<br>
>>>>        * Proper cleanups before halting the HW engine:<br>
>>>>        *   - cancel the delayed idle work<br>
>>>> @@ -515,19 +530,6 @@ static int vce_v3_0_hw_fini(void *handle)<br>
>>>>                                  AMD_CG_STATE_GATE);<br>
>>>>       }<br>
>>>>   -    r = vce_v3_0_wait_for_idle(handle);<br>
>>>> -    if (r)<br>
>>>> -        return r;<br>
>>>> -<br>
>>>> -    vce_v3_0_stop(adev);<br>
>>>> -    return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE);<br>
>>>> -}<br>
>>>> -<br>
>>>> -static int vce_v3_0_suspend(void *handle)<br>
>>>> -{<br>
>>>> -    int r;<br>
>>>> -    struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>> -<br>
>>>>       r = vce_v3_0_hw_fini(adev);<br>
>>>>       if (r)<br>
>>>>           return r;<br>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c <br>
>>>> b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c<br>
>>>> index 044cf9d74b85..226b79254db8 100644<br>
>>>> --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c<br>
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c<br>
>>>> @@ -544,29 +544,8 @@ static int vce_v4_0_hw_fini(void *handle)<br>
>>>>   {<br>
>>>>       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
>>>>   -    /*<br>
>>>> -     * Proper cleanups before halting the HW engine:<br>
>>>> -     *   - cancel the delayed idle work<br>
>>>> -     *   - enable powergating<br>
>>>> -     *   - enable clockgating<br>
>>>> -     *   - disable dpm<br>
>>>> -     *<br>
>>>> -     * TODO: to align with the VCN implementation, move the<br>
>>>> -     * jobs for clockgating/powergating/dpm setting to<br>
>>>> -     * ->set_powergating_state().<br>
>>>> -     */<br>
>>>>       cancel_delayed_work_sync(&adev->vce.idle_work);<br>
>>>>   -    if (adev->pm.dpm_enabled) {<br>
>>>> -        amdgpu_dpm_enable_vce(adev, false);<br>
>>>> -    } else {<br>
>>>> -        amdgpu_asic_set_vce_clocks(adev, 0, 0);<br>
>>>> -        amdgpu_device_ip_set_powergating_state(adev, <br>
>>>> AMD_IP_BLOCK_TYPE_VCE,<br>
>>>> -                               AMD_PG_STATE_GATE);<br>
>>>> -        amdgpu_device_ip_set_clockgating_state(adev, <br>
>>>> AMD_IP_BLOCK_TYPE_VCE,<br>
>>>> -                               AMD_CG_STATE_GATE);<br>
>>>> -    }<br>
>>>> -<br>
>>>>       if (!amdgpu_sriov_vf(adev)) {<br>
>>>>           /* vce_v4_0_wait_for_idle(handle); */<br>
>>>>           vce_v4_0_stop(adev);<br>
>>>> @@ -596,6 +575,29 @@ static int vce_v4_0_suspend(void *handle)<br>
>>>>           drm_dev_exit(idx);<br>
>>>>       }<br>
>>>>   +    /*<br>
>>>> +     * Proper cleanups before halting the HW engine:<br>
>>>> +     *   - cancel the delayed idle work<br>
>>>> +     *   - enable powergating<br>
>>>> +     *   - enable clockgating<br>
>>>> +     *   - disable dpm<br>
>>>> +     *<br>
>>>> +     * TODO: to align with the VCN implementation, move the<br>
>>>> +     * jobs for clockgating/powergating/dpm setting to<br>
>>>> +     * ->set_powergating_state().<br>
>>>> +     */<br>
>>>> +    cancel_delayed_work_sync(&adev->vce.idle_work);<br>
>>>> +<br>
>>>> +    if (adev->pm.dpm_enabled) {<br>
>>>> +        amdgpu_dpm_enable_vce(adev, false);<br>
>>>> +    } else {<br>
>>>> +        amdgpu_asic_set_vce_clocks(adev, 0, 0);<br>
>>>> +        amdgpu_device_ip_set_powergating_state(adev, <br>
>>>> AMD_IP_BLOCK_TYPE_VCE,<br>
>>>> +                               AMD_PG_STATE_GATE);<br>
>>>> +        amdgpu_device_ip_set_clockgating_state(adev, <br>
>>>> AMD_IP_BLOCK_TYPE_VCE,<br>
>>>> +                               AMD_CG_STATE_GATE);<br>
>>>> +    }<br>
>>>> +<br>
>>>>       r = vce_v4_0_hw_fini(adev);<br>
>>>>       if (r)<br>
>>>>           return r;<br>
>>>><br>
</div>
</span></font></div>
</div>
</body>
</html>