aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amdfalconx86/recipes-kernel/linux/files/0995-drm-amd-dal-Fix-hanging-in-disable_output-test-issue.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/files/0995-drm-amd-dal-Fix-hanging-in-disable_output-test-issue.patch')
-rw-r--r--meta-amdfalconx86/recipes-kernel/linux/files/0995-drm-amd-dal-Fix-hanging-in-disable_output-test-issue.patch258
1 files changed, 258 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/files/0995-drm-amd-dal-Fix-hanging-in-disable_output-test-issue.patch b/meta-amdfalconx86/recipes-kernel/linux/files/0995-drm-amd-dal-Fix-hanging-in-disable_output-test-issue.patch
new file mode 100644
index 00000000..1996beca
--- /dev/null
+++ b/meta-amdfalconx86/recipes-kernel/linux/files/0995-drm-amd-dal-Fix-hanging-in-disable_output-test-issue.patch
@@ -0,0 +1,258 @@
+From 52852a1a03bb3a608af9a56a88c250915ea7b37a Mon Sep 17 00:00:00 2001
+From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Date: Wed, 30 Mar 2016 18:05:49 -0400
+Subject: [PATCH 0995/1110] drm/amd/dal: Fix hanging in disable_output test
+ issue.
+
+Add waiting for pflip submission done before commiting surface.
+Add debug prints on pflip status and surface address.
+
+Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c | 30 ++++++++---
+ .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 60 +++++++++++++++++++---
+ drivers/gpu/drm/amd/dal/dc/core/dc.c | 8 ++-
+ 3 files changed, 85 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
+index 038dea4..4defc70 100644
+--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
+@@ -149,8 +149,10 @@ static struct amdgpu_crtc *get_crtc_by_target(
+ * following if is check inherited from both functions where this one is
+ * used now. Need to be checked why it could happen.
+ */
+- if (dc_target == NULL)
++ if (dc_target == NULL) {
++ WARN_ON(1);
+ return adev->mode_info.crtcs[0];
++ }
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ amdgpu_crtc = to_amdgpu_crtc(crtc);
+@@ -176,16 +178,21 @@ static void dm_pflip_high_irq(void *interrupt_params)
+ amdgpu_crtc = get_crtc_by_target(adev, dc_target);
+
+ /* IRQ could occur when in initial stage */
+- if(amdgpu_crtc == NULL)
++ /*TODO work and BO cleanup */
++ if (amdgpu_crtc == NULL) {
++ DRM_DEBUG_DRIVER("CRTC is null, returning.\n");
+ return;
++ }
+
+ spin_lock_irqsave(&adev->ddev->event_lock, flags);
+ works = amdgpu_crtc->pflip_works;
++
+ if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
+- DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
+- "AMDGPU_FLIP_SUBMITTED(%d)\n",
++ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
+ amdgpu_crtc->pflip_status,
+- AMDGPU_FLIP_SUBMITTED);
++ AMDGPU_FLIP_SUBMITTED,
++ amdgpu_crtc->crtc_id,
++ amdgpu_crtc);
+ spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+ return;
+ }
+@@ -203,6 +210,9 @@ static void dm_pflip_high_irq(void *interrupt_params)
+
+ spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+
++ DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE, work: %p,\n",
++ __func__, amdgpu_crtc->crtc_id, amdgpu_crtc, works);
++
+ drm_crtc_vblank_put(&amdgpu_crtc->base);
+ schedule_work(&works->unpin_work);
+ }
+@@ -1131,12 +1141,20 @@ static void dm_page_flip(struct amdgpu_device *adev,
+ * Received a page flip call after the display has been reset.
+ * Just return in this case. Everything should be clean-up on reset.
+ */
+- if (!target)
++
++ if (!target) {
++ WARN_ON(1);
+ return;
++ }
+
+ addr.address.grph.addr.low_part = lower_32_bits(crtc_base);
+ addr.address.grph.addr.high_part = upper_32_bits(crtc_base);
+
++ DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
++ __func__,
++ addr.address.grph.addr.high_part,
++ addr.address.grph.addr.low_part);
++
+ dc_flip_surface_addrs(
+ adev->dm.dc,
+ dc_target_get_status(target)->surfaces,
+diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+index 9f02d3e..d2548b6 100644
+--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
++++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+@@ -624,7 +624,8 @@ static void calculate_stream_scaling_settings(
+ static void dm_dc_surface_commit(
+ struct dc *dc,
+ struct drm_crtc *crtc,
+- struct dm_connector_state *dm_state)
++ struct dm_connector_state *dm_state
++ )
+ {
+ struct dc_surface *dc_surface;
+ const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+@@ -2023,6 +2024,38 @@ static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state)
+ }
+ }
+
++
++typedef bool (*predicate)(struct amdgpu_crtc *acrtc);
++
++static void wait_while_pflip_status(struct amdgpu_device *adev,
++ struct amdgpu_crtc *acrtc, predicate f) {
++ int count = 0;
++ while (f(acrtc)) {
++ /* Spin Wait*/
++ msleep(1);
++ count++;
++ if (count == 1000) {
++ DRM_ERROR("%s - crtc:%d[%p], pflip_stat:%d, probable hang!\n",
++ __func__, acrtc->crtc_id,
++ acrtc,
++ acrtc->pflip_status);
++ BUG_ON(1);
++ }
++ }
++
++ DRM_DEBUG_DRIVER("%s - Finished waiting for:%d msec, crtc:%d[%p], pflip_stat:%d \n",
++ __func__,
++ count,
++ acrtc->crtc_id,
++ acrtc,
++ acrtc->pflip_status);
++}
++
++static bool pflip_in_progress_predicate(struct amdgpu_crtc *acrtc)
++{
++ return acrtc->pflip_status != AMDGPU_FLIP_NONE;
++}
++
+ static void manage_dm_interrupts(
+ struct amdgpu_device *adev,
+ struct amdgpu_crtc *acrtc,
+@@ -2044,9 +2077,8 @@ static void manage_dm_interrupts(
+ &adev->pageflip_irq,
+ irq_type);
+ } else {
+- while (acrtc->pflip_status != AMDGPU_FLIP_NONE) {
+- msleep(1);
+- }
++ wait_while_pflip_status(adev, acrtc,
++ pflip_in_progress_predicate);
+
+ amdgpu_irq_put(
+ adev,
+@@ -2056,6 +2088,12 @@ static void manage_dm_interrupts(
+ }
+ }
+
++
++static bool pflip_pending_predicate(struct amdgpu_crtc *acrtc)
++{
++ return acrtc->pflip_status == AMDGPU_FLIP_PENDING;
++}
++
+ int amdgpu_dm_atomic_commit(
+ struct drm_device *dev,
+ struct drm_atomic_state *state,
+@@ -2130,7 +2168,7 @@ int amdgpu_dm_atomic_commit(
+ aconnector,
+ &crtc->state->mode);
+
+- DRM_INFO("Atomic commit: SET.\n");
++ DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc);
+
+ if (!new_target) {
+ /*
+@@ -2182,7 +2220,7 @@ int amdgpu_dm_atomic_commit(
+
+ case DM_COMMIT_ACTION_DPMS_OFF:
+ case DM_COMMIT_ACTION_RESET:
+- DRM_INFO("Atomic commit: RESET.\n");
++ DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc);
+ /* i.e. reset mode */
+ if (acrtc->target) {
+ manage_dm_interrupts(adev, acrtc, false);
+@@ -2214,6 +2252,7 @@ int amdgpu_dm_atomic_commit(
+ for_each_plane_in_state(state, plane, old_plane_state, i) {
+ struct drm_plane_state *plane_state = plane->state;
+ struct drm_crtc *crtc = plane_state->crtc;
++ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_connector *connector;
+ struct dm_connector_state *dm_state = NULL;
+@@ -2258,6 +2297,14 @@ int amdgpu_dm_atomic_commit(
+ if (!dm_state)
+ continue;
+
++ /*
++ * if flip is pending (ie, still waiting for fence to return
++ * before address is submitted) here, we cannot commit_surface
++ * as commit_surface will pre-maturely write out the future
++ * address. wait until flip is submitted before proceeding.
++ */
++ wait_while_pflip_status(adev, acrtc, pflip_pending_predicate);
++
+ dm_dc_surface_commit(
+ dm->dc,
+ crtc,
+@@ -2367,6 +2414,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector
+ /* DC is optimized not to do anything if 'targets' didn't change. */
+ dc_commit_targets(dc, commit_targets, commit_targets_count);
+
++
+ dm_dc_surface_commit(dc, &disconnected_acrtc->base,
+ to_dm_connector_state(
+ connector->state));
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+index c5aa460..e71088d 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+@@ -825,6 +825,7 @@ bool dc_commit_surfaces_to_target(
+ if (core_dc->current_context.target_count == 0)
+ return false;
+
++
+ context = dm_alloc(sizeof(struct validate_context));
+
+ resource_validate_ctx_copy_construct(&core_dc->current_context, context);
+@@ -916,10 +917,14 @@ bool dc_commit_surfaces_to_target(
+ dal_logger_write(core_dc->ctx->logger,
+ LOG_MAJOR_INTERFACE_TRACE,
+ LOG_MINOR_COMPONENT_DC,
+- "Pipe:%d 0x%x: src: %d, %d, %d,"
++ "Pipe:%d 0x%x: addr hi:0x%x, "
++ "addr low:0x%x, "
++ "src: %d, %d, %d,"
+ " %d; dst: %d, %d, %d, %d;\n",
+ pipe_ctx->pipe_idx,
+ dc_surface,
++ dc_surface->address.grph.addr.high_part,
++ dc_surface->address.grph.addr.low_part,
+ dc_surface->src_rect.x,
+ dc_surface->src_rect.y,
+ dc_surface->src_rect.width,
+@@ -951,6 +956,7 @@ bool dc_commit_surfaces_to_target(
+ &context->pp_display_cfg);
+ }
+
++
+ resource_validate_ctx_destruct(&(core_dc->current_context));
+ core_dc->current_context = *context;
+ dm_free(context);
+--
+2.7.4
+