aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0616-drm-amd-dal-clean-up-MST-sem-usage.patch
diff options
context:
space:
mode:
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.patch153
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
+