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

drm/amd/pm: avoid duplicate powergate/ungate setting

Just bail out if the target IP block is already in the desired
powergate/ungate state. This can avoid some duplicate settings
which sometimes may cause unexpected issues.

Link: https://lore.kernel.org/all/YV81vidWQLWvATMM@zn.tnic/
Bug: https://bugzilla.kernel.org/show_bug.cgi?id=214921
Bug: https://bugzilla.kernel.org/show_bug.cgi?id=215025
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1789
Fixes: bf756fb833cb ("drm/amdgpu: add missing cleanups for Polaris12 UVD/VCE on suspend")
Signed-off-by: Evan Quan <evan.quan@amd.com>
Tested-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org

authored by

Evan Quan and committed by
Alex Deucher
6ee27ee2 69650a87

+23 -1
+3
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 3509 3509 adev->rmmio_size = pci_resource_len(adev->pdev, 2); 3510 3510 } 3511 3511 3512 + for (i = 0; i < AMD_IP_BLOCK_TYPE_NUM; i++) 3513 + atomic_set(&adev->pm.pwr_state[i], POWER_STATE_UNKNOWN); 3514 + 3512 3515 adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); 3513 3516 if (adev->rmmio == NULL) { 3514 3517 return -ENOMEM;
+2 -1
drivers/gpu/drm/amd/include/amd_shared.h
··· 98 98 AMD_IP_BLOCK_TYPE_ACP, 99 99 AMD_IP_BLOCK_TYPE_VCN, 100 100 AMD_IP_BLOCK_TYPE_MES, 101 - AMD_IP_BLOCK_TYPE_JPEG 101 + AMD_IP_BLOCK_TYPE_JPEG, 102 + AMD_IP_BLOCK_TYPE_NUM, 102 103 }; 103 104 104 105 enum amd_clockgating_state {
+10
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
··· 927 927 { 928 928 int ret = 0; 929 929 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 930 + enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; 931 + 932 + if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) { 933 + dev_dbg(adev->dev, "IP block%d already in the target %s state!", 934 + block_type, gate ? "gate" : "ungate"); 935 + return 0; 936 + } 930 937 931 938 switch (block_type) { 932 939 case AMD_IP_BLOCK_TYPE_UVD: ··· 985 978 default: 986 979 break; 987 980 } 981 + 982 + if (!ret) 983 + atomic_set(&adev->pm.pwr_state[block_type], pwr_state); 988 984 989 985 return ret; 990 986 }
+8
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
··· 417 417 enum amd_dpm_forced_level forced_level; 418 418 }; 419 419 420 + enum ip_power_state { 421 + POWER_STATE_UNKNOWN, 422 + POWER_STATE_ON, 423 + POWER_STATE_OFF, 424 + }; 425 + 420 426 struct amdgpu_pm { 421 427 struct mutex mutex; 422 428 u32 current_sclk; ··· 458 452 struct i2c_adapter smu_i2c; 459 453 struct mutex smu_i2c_mutex; 460 454 struct list_head pm_attr_list; 455 + 456 + atomic_t pwr_state[AMD_IP_BLOCK_TYPE_NUM]; 461 457 }; 462 458 463 459 #define R600_SSTU_DFLT 0