diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0616-drm-amd-dal-clean-up-MST-sem-usage.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0616-drm-amd-dal-clean-up-MST-sem-usage.patch | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0616-drm-amd-dal-clean-up-MST-sem-usage.patch b/common/recipes-kernel/linux/files/0616-drm-amd-dal-clean-up-MST-sem-usage.patch new file mode 100644 index 00000000..b06e3c13 --- /dev/null +++ b/common/recipes-kernel/linux/files/0616-drm-amd-dal-clean-up-MST-sem-usage.patch @@ -0,0 +1,153 @@ +From f6b6c40260c9fda070dcfd495d46ca7cd49a7cef Mon Sep 17 00:00:00 2001 +From: Mykola Lysenko <Mykola.Lysenko@amd.com> +Date: Mon, 14 Dec 2015 19:13:28 +0800 +Subject: [PATCH 0616/1110] drm/amd/dal: clean-up MST sem usage + +In previous implementation semaphore update was +done in the same loop as crtc. It was dependent +on crtc order and could lead to dead-lock. + +Consider the following sitatuation, crtc is moved +from one connector to another. + +Initial state: +CRTC1 - CONNECTOR1 +CRTC2 - CONNECTOR2 + +CONNECTOR1 got disconnected + +Set mode received to use CRTC1 on CONNECTOR2 +In state we have both connectors and crtcs, +added as affected. +First would be set on CRTC1, and then reset on CRTC2. +And this will deadlock. + +This issue addressed by the current change. Also +now all semaphore management done in one place. + +Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com> +Signed-off-by: Harry Wentland <harry.wentland@amd.com> +Acked-by: Harry Wentland<harry.wentland@amd.com> +--- + .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 51 +++++++++++----------- + 1 file changed, 25 insertions(+), 26 deletions(-) + +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 fff17cd..326242f 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 +@@ -2071,6 +2071,25 @@ static void handle_headless_hotplug( + } + } + ++static void update_connector_sem_state(struct drm_atomic_state *state) ++{ ++ struct drm_connector *connector; ++ struct drm_connector_state *old_con_state; ++ struct amdgpu_connector *aconnector = NULL; ++ int i; ++ ++ for_each_connector_in_state(state, connector, old_con_state, i) { ++ aconnector = to_amdgpu_connector(connector); ++ if (old_con_state->crtc) { ++ if (!connector->state->crtc) ++ up(&aconnector->mst_sem); ++ } else { ++ if (connector->state->crtc) ++ down(&aconnector->mst_sem); ++ } ++ } ++} ++ + int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, +@@ -2119,8 +2138,7 @@ int amdgpu_dm_atomic_commit( + /* update changed items */ + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc; +- struct amdgpu_connector *aconnector_new = NULL; +- struct amdgpu_connector *aconnector_old = NULL; ++ struct amdgpu_connector *aconnector = NULL; + enum dm_commit_action action; + struct drm_crtc_state *new_state = crtc->state; + struct drm_connector *connector; +@@ -2134,24 +2152,7 @@ int amdgpu_dm_atomic_commit( + old_con_state, + j) { + if (connector->state->crtc == crtc) { +- aconnector_new = to_amdgpu_connector(connector); +- break; +- } +- } +- +- for_each_connector_in_state( +- state, +- connector, +- old_con_state, +- j) { +- /* +- * this is the case when reset occur, connector +- * is removed from new crtc state. We need to +- * update connector state anyway. Access it from +- * old_con_state +- */ +- if (old_con_state->crtc == crtc) { +- aconnector_old = to_amdgpu_connector(connector); ++ aconnector = to_amdgpu_connector(connector); + break; + } + } +@@ -2159,7 +2160,7 @@ int amdgpu_dm_atomic_commit( + /* handles headless hotplug case, updating new_state and + * aconnector as needed + */ +- handle_headless_hotplug(acrtc, new_state, &aconnector_new); ++ handle_headless_hotplug(acrtc, new_state, &aconnector); + + action = get_dm_commit_action(new_state); + +@@ -2168,7 +2169,7 @@ int amdgpu_dm_atomic_commit( + case DM_COMMIT_ACTION_SET: { + struct dc_target *new_target = + create_target_for_sink( +- aconnector_new, ++ aconnector, + &crtc->state->mode); + + DRM_DEBUG_KMS("Atomic commit: SET.\n"); +@@ -2198,7 +2199,6 @@ int amdgpu_dm_atomic_commit( + /* this is the update mode case */ + dc_target_release(acrtc->target); + acrtc->target = NULL; +- up(&aconnector_old->mst_sem); + } + + /* +@@ -2212,7 +2212,6 @@ int amdgpu_dm_atomic_commit( + acrtc->target = new_target; + acrtc->enabled = true; + +- down(&aconnector_new->mst_sem); + break; + } + +@@ -2229,13 +2228,13 @@ int amdgpu_dm_atomic_commit( + dc_target_release(acrtc->target); + acrtc->target = NULL; + acrtc->enabled = false; +- +- up(&aconnector_old->mst_sem); + } + break; + } /* switch() */ + } /* for_each_crtc_in_state() */ + ++ update_connector_sem_state(state); ++ + commit_targets_count = 0; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +-- +2.7.4 + |