diff options
author | Evan Quan <evan.quan@amd.com> | 2019-10-31 09:15:29 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-11-07 00:27:48 +0300 |
commit | 5c5b2ba00667edd6c5c0df9f97ba2b179d013e1d (patch) | |
tree | 56d4e43b3cbdfc030ccb18703301b155dc90b49b /drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | |
parent | b0adca4d50169d9a05912e208a89cdd615da40d4 (diff) | |
download | linux-5c5b2ba00667edd6c5c0df9f97ba2b179d013e1d.tar.xz |
drm/amdgpu: fix possible pstate switch race condition
Added lock protection so that the p-state switch will
be guarded to be sequential. Also update the hive
pstate only all device from the hive are in the same
state.
Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Feifei Xu <Feifei.Xu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 167d9fbd2c4f..de20a9a1c444 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -274,12 +274,18 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) { int ret = 0; struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0); + struct amdgpu_device *tmp_adev; + bool update_hive_pstate = true; if (!hive) return 0; - if (hive->pstate == pstate) + mutex_lock(&hive->hive_lock); + + if (hive->pstate == pstate) { + mutex_unlock(&hive->hive_lock); return 0; + } dev_dbg(adev->dev, "Set xgmi pstate %d.\n", pstate); @@ -290,11 +296,32 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) ret = adev->powerplay.pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, pstate); - if (ret) + if (ret) { dev_err(adev->dev, "XGMI: Set pstate failure on device %llx, hive %llx, ret %d", adev->gmc.xgmi.node_id, adev->gmc.xgmi.hive_id, ret); + goto out; + } + + /* Update device pstate */ + adev->pstate = pstate; + + /* + * Update the hive pstate only all devices of the hive + * are in the same pstate + */ + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { + if (tmp_adev->pstate != adev->pstate) { + update_hive_pstate = false; + break; + } + } + if (update_hive_pstate) + hive->pstate = pstate; + +out: + mutex_unlock(&hive->hive_lock); return ret; } @@ -369,6 +396,9 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) goto exit; } + /* Set default device pstate */ + adev->pstate = -1; + top_info = &adev->psp.xgmi_context.top_info; list_add_tail(&adev->gmc.xgmi.head, &hive->device_list); |