From f6b6c40260c9fda070dcfd495d46ca7cd49a7cef Mon Sep 17 00:00:00 2001 From: Mykola Lysenko 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 Signed-off-by: Harry Wentland Acked-by: Harry Wentland --- .../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