Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu: Ensure HDA function is suspended before ASIC reset

DP/HDMI audio on AMD PRO VII stops working after S3:
[ 149.450391] amdgpu 0000:63:00.0: amdgpu: MODE1 reset
[ 149.450395] amdgpu 0000:63:00.0: amdgpu: GPU mode1 reset
[ 149.450494] amdgpu 0000:63:00.0: amdgpu: GPU psp mode1 reset
[ 149.983693] snd_hda_intel 0000:63:00.1: refused to change power state from D0 to D3hot
[ 150.003439] amdgpu 0000:63:00.0: refused to change power state from D0 to D3hot
...
[ 155.432975] snd_hda_intel 0000:63:00.1: CORB reset timeout#2, CORBRP = 65535

The offending commit is daf8de0874ab5b ("drm/amdgpu: always reset the asic in
suspend (v2)"). Commit 34452ac3038a7 ("drm/amdgpu: don't use BACO for
reset in S3 ") doesn't help, so the issue is something different.

Assuming that to make HDA resume to D0 fully realized, it needs to be
successfully put to D3 first. And this guesswork proves working, by
moving amdgpu_asic_reset() to noirq callback, so it's called after HDA
function is in D3.

Fixes: daf8de0874ab5b ("drm/amdgpu: always reset the asic in suspend (v2)")
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Kai-Heng Feng and committed by
Alex Deucher
9e051720 dd481828

+12 -6
+12 -6
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 2323 2323 { 2324 2324 struct drm_device *drm_dev = dev_get_drvdata(dev); 2325 2325 struct amdgpu_device *adev = drm_to_adev(drm_dev); 2326 - int r; 2327 2326 2328 2327 if (amdgpu_acpi_is_s0ix_active(adev)) 2329 2328 adev->in_s0ix = true; 2330 2329 else 2331 2330 adev->in_s3 = true; 2332 - r = amdgpu_device_suspend(drm_dev, true); 2333 - if (r) 2334 - return r; 2331 + return amdgpu_device_suspend(drm_dev, true); 2332 + } 2333 + 2334 + static int amdgpu_pmops_suspend_noirq(struct device *dev) 2335 + { 2336 + struct drm_device *drm_dev = dev_get_drvdata(dev); 2337 + struct amdgpu_device *adev = drm_to_adev(drm_dev); 2338 + 2335 2339 if (!adev->in_s0ix) 2336 - r = amdgpu_asic_reset(adev); 2337 - return r; 2340 + return amdgpu_asic_reset(adev); 2341 + 2342 + return 0; 2338 2343 } 2339 2344 2340 2345 static int amdgpu_pmops_resume(struct device *dev) ··· 2580 2575 .prepare = amdgpu_pmops_prepare, 2581 2576 .complete = amdgpu_pmops_complete, 2582 2577 .suspend = amdgpu_pmops_suspend, 2578 + .suspend_noirq = amdgpu_pmops_suspend_noirq, 2583 2579 .resume = amdgpu_pmops_resume, 2584 2580 .freeze = amdgpu_pmops_freeze, 2585 2581 .thaw = amdgpu_pmops_thaw,