diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4990-drm-amdgpu-split-ip-suspend-into-2-phases.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4990-drm-amdgpu-split-ip-suspend-into-2-phases.patch | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4990-drm-amdgpu-split-ip-suspend-into-2-phases.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4990-drm-amdgpu-split-ip-suspend-into-2-phases.patch new file mode 100644 index 00000000..f17967ef --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4990-drm-amdgpu-split-ip-suspend-into-2-phases.patch @@ -0,0 +1,129 @@ +From d50d606afb8d7e95f44bae0c617fbbc4c5a426ba Mon Sep 17 00:00:00 2001 +From: Alex Deucher <alexander.deucher@amd.com> +Date: Thu, 19 Jul 2018 13:10:07 -0500 +Subject: [PATCH 4990/5725] drm/amdgpu: split ip suspend into 2 phases + +We need to do some IPs earlier to deal with ordering issues +similar to how resume is split into two phases. Do DCE first +to deal with atomic, then do the rest. + +Acked-by: Harry Wentland <harry.wentland@amd.com> +Reviewed-and-tested-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 78 +++++++++++++++++++++++++++++- + 1 file changed, 76 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 8c85387..c4a9156 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -1975,7 +1975,7 @@ static void amdgpu_device_ip_late_init_func_handler(struct work_struct *work) + } + + /** +- * amdgpu_device_ip_suspend - run suspend for hardware IPs ++ * amdgpu_device_ip_suspend_phase1 - run suspend for hardware IPs (phase 1) + * + * @adev: amdgpu_device pointer + * +@@ -1985,7 +1985,55 @@ static void amdgpu_device_ip_late_init_func_handler(struct work_struct *work) + * in each IP into a state suitable for suspend. + * Returns 0 on success, negative error code on failure. + */ +-int amdgpu_device_ip_suspend(struct amdgpu_device *adev) ++static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev) ++{ ++ int i, r; ++ ++ if (amdgpu_sriov_vf(adev)) ++ amdgpu_virt_request_full_gpu(adev, false); ++ ++ for (i = adev->num_ip_blocks - 1; i >= 0; i--) { ++ if (!adev->ip_blocks[i].status.valid) ++ continue; ++ /* displays are handled separately */ ++ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) { ++ /* ungate blocks so that suspend can properly shut them down */ ++ if (adev->ip_blocks[i].version->funcs->set_clockgating_state) { ++ r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev, ++ AMD_CG_STATE_UNGATE); ++ if (r) { ++ DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", ++ adev->ip_blocks[i].version->funcs->name, r); ++ } ++ } ++ /* XXX handle errors */ ++ r = adev->ip_blocks[i].version->funcs->suspend(adev); ++ /* XXX handle errors */ ++ if (r) { ++ DRM_ERROR("suspend of IP block <%s> failed %d\n", ++ adev->ip_blocks[i].version->funcs->name, r); ++ } ++ } ++ } ++ ++ if (amdgpu_sriov_vf(adev)) ++ amdgpu_virt_release_full_gpu(adev, false); ++ ++ return 0; ++} ++ ++/** ++ * amdgpu_device_ip_suspend_phase2 - run suspend for hardware IPs (phase 2) ++ * ++ * @adev: amdgpu_device pointer ++ * ++ * Main suspend function for hardware IPs. The list of all the hardware ++ * IPs that make up the asic is walked, clockgating is disabled and the ++ * suspend callbacks are run. suspend puts the hardware and software state ++ * in each IP into a state suitable for suspend. ++ * Returns 0 on success, negative error code on failure. ++ */ ++static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev) + { + int i, r; + +@@ -2006,6 +2054,9 @@ int amdgpu_device_ip_suspend(struct amdgpu_device *adev) + for (i = adev->num_ip_blocks - 1; i >= 0; i--) { + if (!adev->ip_blocks[i].status.valid) + continue; ++ /* displays are handled in phase1 */ ++ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) ++ continue; + /* ungate blocks so that suspend can properly shut them down */ + if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_SMC && + adev->ip_blocks[i].version->funcs->set_clockgating_state) { +@@ -2031,6 +2082,29 @@ int amdgpu_device_ip_suspend(struct amdgpu_device *adev) + return 0; + } + ++/** ++ * amdgpu_device_ip_suspend - run suspend for hardware IPs ++ * ++ * @adev: amdgpu_device pointer ++ * ++ * Main suspend function for hardware IPs. The list of all the hardware ++ * IPs that make up the asic is walked, clockgating is disabled and the ++ * suspend callbacks are run. suspend puts the hardware and software state ++ * in each IP into a state suitable for suspend. ++ * Returns 0 on success, negative error code on failure. ++ */ ++int amdgpu_device_ip_suspend(struct amdgpu_device *adev) ++{ ++ int r; ++ ++ r = amdgpu_device_ip_suspend_phase1(adev); ++ if (r) ++ return r; ++ r = amdgpu_device_ip_suspend_phase2(adev); ++ ++ return r; ++} ++ + static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) + { + int i, r; +-- +2.7.4 + |