Commit 6ee27ee2 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher

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: bf756fb8 ("drm/amdgpu: add missing cleanups for Polaris12 UVD/VCE on suspend")
Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Tested-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent 69650a87
...@@ -3509,6 +3509,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, ...@@ -3509,6 +3509,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->rmmio_size = pci_resource_len(adev->pdev, 2); adev->rmmio_size = pci_resource_len(adev->pdev, 2);
} }
for (i = 0; i < AMD_IP_BLOCK_TYPE_NUM; i++)
atomic_set(&adev->pm.pwr_state[i], POWER_STATE_UNKNOWN);
adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size);
if (adev->rmmio == NULL) { if (adev->rmmio == NULL) {
return -ENOMEM; return -ENOMEM;
......
...@@ -98,7 +98,8 @@ enum amd_ip_block_type { ...@@ -98,7 +98,8 @@ enum amd_ip_block_type {
AMD_IP_BLOCK_TYPE_ACP, AMD_IP_BLOCK_TYPE_ACP,
AMD_IP_BLOCK_TYPE_VCN, AMD_IP_BLOCK_TYPE_VCN,
AMD_IP_BLOCK_TYPE_MES, AMD_IP_BLOCK_TYPE_MES,
AMD_IP_BLOCK_TYPE_JPEG AMD_IP_BLOCK_TYPE_JPEG,
AMD_IP_BLOCK_TYPE_NUM,
}; };
enum amd_clockgating_state { enum amd_clockgating_state {
......
...@@ -927,6 +927,13 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block ...@@ -927,6 +927,13 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block
{ {
int ret = 0; int ret = 0;
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON;
if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) {
dev_dbg(adev->dev, "IP block%d already in the target %s state!",
block_type, gate ? "gate" : "ungate");
return 0;
}
switch (block_type) { switch (block_type) {
case AMD_IP_BLOCK_TYPE_UVD: case AMD_IP_BLOCK_TYPE_UVD:
...@@ -979,6 +986,9 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block ...@@ -979,6 +986,9 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block
break; break;
} }
if (!ret)
atomic_set(&adev->pm.pwr_state[block_type], pwr_state);
return ret; return ret;
} }
......
...@@ -417,6 +417,12 @@ struct amdgpu_dpm { ...@@ -417,6 +417,12 @@ struct amdgpu_dpm {
enum amd_dpm_forced_level forced_level; enum amd_dpm_forced_level forced_level;
}; };
enum ip_power_state {
POWER_STATE_UNKNOWN,
POWER_STATE_ON,
POWER_STATE_OFF,
};
struct amdgpu_pm { struct amdgpu_pm {
struct mutex mutex; struct mutex mutex;
u32 current_sclk; u32 current_sclk;
...@@ -452,6 +458,8 @@ struct amdgpu_pm { ...@@ -452,6 +458,8 @@ struct amdgpu_pm {
struct i2c_adapter smu_i2c; struct i2c_adapter smu_i2c;
struct mutex smu_i2c_mutex; struct mutex smu_i2c_mutex;
struct list_head pm_attr_list; struct list_head pm_attr_list;
atomic_t pwr_state[AMD_IP_BLOCK_TYPE_NUM];
}; };
#define R600_SSTU_DFLT 0 #define R600_SSTU_DFLT 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment