diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0360-drm-amdgpu-add-fence-suspend-resume-functions.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0360-drm-amdgpu-add-fence-suspend-resume-functions.patch | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0360-drm-amdgpu-add-fence-suspend-resume-functions.patch b/common/recipes-kernel/linux/files/0360-drm-amdgpu-add-fence-suspend-resume-functions.patch new file mode 100644 index 00000000..cab2a363 --- /dev/null +++ b/common/recipes-kernel/linux/files/0360-drm-amdgpu-add-fence-suspend-resume-functions.patch @@ -0,0 +1,158 @@ +From 5ceb54c68a28fc8af5cf8d32c4fde29c97dd3c18 Mon Sep 17 00:00:00 2001 +From: Alex Deucher <alexander.deucher@amd.com> +Date: Wed, 5 Aug 2015 12:41:48 -0400 +Subject: [PATCH 0360/1050] drm/amdgpu: add fence suspend/resume functions + +Added to: +- handle draining the ring on suspend +- properly enable/disable interrupts on suspend and resume + +Fix breakages from: +commit 467ee3be53d240d08beed2e82a941e820c1ac323 +Author: Chunming Zhou <david1.zhou@amd.com> +Date: Mon Jun 1 14:14:32 2015 +0800 + + drm/amdgpu: always enable EOP interrupt v2 + +Tested-by: Audrey Grodzovsky <audrey.grodzovsky@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 + + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 ++-------- + drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 61 ++++++++++++++++++++++++++++++ + 3 files changed, 67 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index 1ec89d2..5511432 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -426,6 +426,8 @@ void amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring); + int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, + struct amdgpu_irq_src *irq_src, + unsigned irq_type); ++void amdgpu_fence_driver_suspend(struct amdgpu_device *adev); ++void amdgpu_fence_driver_resume(struct amdgpu_device *adev); + int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner, + struct amdgpu_fence **fence); + void amdgpu_fence_process(struct amdgpu_ring *ring); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 99f158e..a816580 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -1627,8 +1627,7 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) + struct amdgpu_device *adev; + struct drm_crtc *crtc; + struct drm_connector *connector; +- int i, r; +- bool force_completion = false; ++ int r; + + if (dev == NULL || dev->dev_private == NULL) { + return -ENODEV; +@@ -1667,21 +1666,7 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) + /* evict vram memory */ + amdgpu_bo_evict_vram(adev); + +- /* wait for gpu to finish processing current batch */ +- for (i = 0; i < AMDGPU_MAX_RINGS; i++) { +- struct amdgpu_ring *ring = adev->rings[i]; +- if (!ring) +- continue; +- +- r = amdgpu_fence_wait_empty(ring); +- if (r) { +- /* delay GPU reset to resume */ +- force_completion = true; +- } +- } +- if (force_completion) { +- amdgpu_fence_driver_force_completion(adev); +- } ++ amdgpu_fence_driver_suspend(adev); + + r = amdgpu_suspend(adev); + +@@ -1739,6 +1724,8 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) + + r = amdgpu_resume(adev); + ++ amdgpu_fence_driver_resume(adev); ++ + r = amdgpu_ib_ring_tests(adev); + if (r) + DRM_ERROR("ib ring test failed (%d).\n", r); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +index b89dafe..1b0bc07 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +@@ -956,6 +956,67 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev) + } + + /** ++ * amdgpu_fence_driver_suspend - suspend the fence driver ++ * for all possible rings. ++ * ++ * @adev: amdgpu device pointer ++ * ++ * Suspend the fence driver for all possible rings (all asics). ++ */ ++void amdgpu_fence_driver_suspend(struct amdgpu_device *adev) ++{ ++ int i, r; ++ ++ mutex_lock(&adev->ring_lock); ++ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { ++ struct amdgpu_ring *ring = adev->rings[i]; ++ if (!ring || !ring->fence_drv.initialized) ++ continue; ++ ++ /* wait for gpu to finish processing current batch */ ++ r = amdgpu_fence_wait_empty(ring); ++ if (r) { ++ /* delay GPU reset to resume */ ++ amdgpu_fence_driver_force_completion(adev); ++ } ++ ++ /* disable the interrupt */ ++ amdgpu_irq_put(adev, ring->fence_drv.irq_src, ++ ring->fence_drv.irq_type); ++ } ++ mutex_unlock(&adev->ring_lock); ++} ++ ++/** ++ * amdgpu_fence_driver_resume - resume the fence driver ++ * for all possible rings. ++ * ++ * @adev: amdgpu device pointer ++ * ++ * Resume the fence driver for all possible rings (all asics). ++ * Not all asics have all rings, so each asic will only ++ * start the fence driver on the rings it has using ++ * amdgpu_fence_driver_start_ring(). ++ * Returns 0 for success. ++ */ ++void amdgpu_fence_driver_resume(struct amdgpu_device *adev) ++{ ++ int i; ++ ++ mutex_lock(&adev->ring_lock); ++ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { ++ struct amdgpu_ring *ring = adev->rings[i]; ++ if (!ring || !ring->fence_drv.initialized) ++ continue; ++ ++ /* enable the interrupt */ ++ amdgpu_irq_get(adev, ring->fence_drv.irq_src, ++ ring->fence_drv.irq_type); ++ } ++ mutex_unlock(&adev->ring_lock); ++} ++ ++/** + * amdgpu_fence_driver_force_completion - force all fence waiter to complete + * + * @adev: amdgpu device pointer +-- +1.9.1 + |