drm/amd/pm: avoid duplicate powergate/ungate setting
authorEvan Quan <evan.quan@amd.com>
Fri, 5 Nov 2021 07:25:30 +0000 (15:25 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 17 Nov 2021 22:41:20 +0000 (17:41 -0500)
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
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h

index 5625f77..188accb 100644 (file)
@@ -3509,6 +3509,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
                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);
        if (adev->rmmio == NULL) {
                return -ENOMEM;
index f1a46d1..4b9e68a 100644 (file)
@@ -98,7 +98,8 @@ enum amd_ip_block_type {
        AMD_IP_BLOCK_TYPE_ACP,
        AMD_IP_BLOCK_TYPE_VCN,
        AMD_IP_BLOCK_TYPE_MES,
-       AMD_IP_BLOCK_TYPE_JPEG
+       AMD_IP_BLOCK_TYPE_JPEG,
+       AMD_IP_BLOCK_TYPE_NUM,
 };
 
 enum amd_clockgating_state {
index 03581d5..08362d5 100644 (file)
@@ -927,6 +927,13 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block
 {
        int ret = 0;
        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) {
        case AMD_IP_BLOCK_TYPE_UVD:
@@ -979,6 +986,9 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block
                break;
        }
 
+       if (!ret)
+               atomic_set(&adev->pm.pwr_state[block_type], pwr_state);
+
        return ret;
 }
 
index 98f1b3d..16e3f72 100644 (file)
@@ -417,6 +417,12 @@ struct amdgpu_dpm {
        enum amd_dpm_forced_level forced_level;
 };
 
+enum ip_power_state {
+       POWER_STATE_UNKNOWN,
+       POWER_STATE_ON,
+       POWER_STATE_OFF,
+};
+
 struct amdgpu_pm {
        struct mutex            mutex;
        u32                     current_sclk;
@@ -452,6 +458,8 @@ struct amdgpu_pm {
        struct i2c_adapter smu_i2c;
        struct mutex            smu_i2c_mutex;
        struct list_head        pm_attr_list;
+
+       atomic_t                pwr_state[AMD_IP_BLOCK_TYPE_NUM];
 };
 
 #define R600_SSTU_DFLT                               0