aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/4990-drm-amdgpu-split-ip-suspend-into-2-phases.patch
diff options
context:
space:
mode:
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.patch129
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
+