From patchwork Tue Sep 27 06:59:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai-Heng Feng X-Patchwork-Id: 1682975 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=canonical.com header.i=@canonical.com header.a=rsa-sha256 header.s=20210705 header.b=OSPdE/7r; dkim-atps=neutral Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Mc9Vx1Nvzz1yq7 for ; Tue, 27 Sep 2022 17:00:23 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1od4Zf-0000FL-Rz; Tue, 27 Sep 2022 07:00:11 +0000 Received: from smtp-relay-canonical-0.internal ([10.131.114.83] helo=smtp-relay-canonical-0.canonical.com) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1od4Zd-0000EU-Ct for kernel-team@lists.ubuntu.com; Tue, 27 Sep 2022 07:00:09 +0000 Received: from HP-EliteBook-x360-830-G8-Notebook-PC.. (1-171-217-173.dynamic-ip.hinet.net [1.171.217.173]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id 4B40C421DB for ; Tue, 27 Sep 2022 07:00:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1664262009; bh=PLNTwHkF8e9la0+2J0LkvMsO+XhTvKqbTw6PPi0J7M4=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=OSPdE/7roai/GJZLmKaChDa7EZoqwtDmcTPMMFYM8AX9H395tc6KUN5s/cbZqolYx isvzHUh7uqdpFtxRochrcUQAnGZ0PqiOWEF1L13KkrrJT0NuGgeekExaS1GFmA8zrF ofVTkUb0KIBknbWipVID2VCNidrtX95b9U19LaZTku+Mi1Vpkh6P1QNnXnJssj++O5 G0v3Qc/vY6CE7KcOHw2u2+ZRFU0mNIP8TXHr11ZjYfoY/DyKr3FsQPxbcUSmSoKZA8 eplR5rOV7iYkG/t00NSLUCWNhYkpv773OMpYGDE56x3KUqonwe5JueaVhurv2b+p7Y +rQpIMBLxygPw== From: Kai-Heng Feng To: kernel-team@lists.ubuntu.com Subject: [J/OEM-5.17] [PATCH 3/3] drm/amd/display: Release remote dc_sink under mst scenario Date: Tue, 27 Sep 2022 14:59:56 +0800 Message-Id: <20220927065958.269033-4-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220927065958.269033-1-kai.heng.feng@canonical.com> References: <20220927065958.269033-1-kai.heng.feng@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Wayne Lin BugLink: https://bugs.launchpad.net/bugs/1990920 [Why] Observe that we have several problems while releasing remote dc_sink under mst cases. - When unplug mst branch device from the source, we now try to free all remote dc_sinks in dm_helpers_dp_mst_stop_top_mgr(). However, there are bugs while we're releasing dc_sinks here. First of all, link->remote_sinks[] array get shuffled within dc_link_remove_remote_sink(). As the result, increasing the array index within the releasing loop is wrong. Secondly, it tries to call dc_sink_release() to release the dc_sink of the same aconnector every time in the loop. Which can't release dc_sink of all aconnector in the mst topology. - There is no code path for us to release remote dc_sink for disconnected sst monitor which unplug event is notified by CSN sideband message. Which means we'll use stale dc_sink data to represent later on connected monitor. Also, has chance to break the maximum remote dc_sink number constraint. [How] Distinguish unplug event of mst scenario into 2 cases. * Unplug sst/legacy stream sink off the mst topology - Release related remote dc_sink in detec_ctx(). * Unplug mst branch device off the mst topology - Release related remote dc_sink in early_unregister() Tested-by: Daniel Wheeler Reviewed-by: Aurabindo Jayamohanan Pillai Acked-by: Rodrigo Siqueira Acked-by: Lyude Paul Signed-off-by: Wayne Lin Signed-off-by: Alex Deucher (backported from commit 84a8b3908285d007db49532fd4b51d4b183d1242) [khfeng: git-am complains but can git-cherry-pick cleanly] Signed-off-by: Kai-Heng Feng --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +-- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 18 +--------- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 34 +++++++++++++++++-- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d1be2b272eb2d..90ff792e80ec5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2174,7 +2174,8 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) } else { ret = drm_dp_mst_topology_mgr_resume(mgr, true); if (ret < 0) { - drm_dp_mst_topology_mgr_set_mst(mgr, false); + dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx, + aconnector->dc_link); need_hotplug = true; } } @@ -10216,7 +10217,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, * added MST connectors not found in existing crtc_state in the chained mode * TODO: need to dig out the root cause of that */ - if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port)) + if (!aconnector) goto skip_modeset; if (modereset_required(new_crtc_state)) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index cee1664a9065b..55cef1d6bf15e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -456,7 +456,6 @@ void dm_helpers_dp_mst_stop_top_mgr( struct dc_link *link) { struct amdgpu_dm_connector *aconnector = link->priv; - uint8_t i; if (!aconnector) { DRM_ERROR("Failed to find connector for link!"); @@ -468,22 +467,7 @@ void dm_helpers_dp_mst_stop_top_mgr( if (aconnector->mst_mgr.mst_state == true) { drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false); - - for (i = 0; i < MAX_SINKS_PER_LINK; i++) { - if (link->remote_sinks[i] == NULL) - continue; - - if (link->remote_sinks[i]->sink_signal == - SIGNAL_TYPE_DISPLAY_PORT_MST) { - dc_link_remove_remote_sink(link, link->remote_sinks[i]); - - if (aconnector->dc_sink) { - dc_sink_release(aconnector->dc_sink); - aconnector->dc_sink = NULL; - aconnector->dc_link->cur_link_settings.lane_count = 0; - } - } - } + link->cur_link_settings.lane_count = 0; } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 424f4cfc0e04f..d1bee74749abd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -154,11 +154,28 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector) static void amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector) { - struct amdgpu_dm_connector *amdgpu_dm_connector = + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct drm_dp_mst_port *port = amdgpu_dm_connector->port; + struct drm_dp_mst_port *port = aconnector->port; + struct amdgpu_dm_connector *root = aconnector->mst_port; + struct dc_link *dc_link = aconnector->dc_link; + struct dc_sink *dc_sink = aconnector->dc_sink; drm_dp_mst_connector_early_unregister(connector, port); + + /* + * Release dc_sink for connector which its attached port is + * no longer in the mst topology + */ + drm_modeset_lock(&root->mst_mgr.base.lock, NULL); + if (dc_sink) { + if (dc_link->sink_count) + dc_link_remove_remote_sink(dc_link, dc_sink); + + dc_sink_release(dc_sink); + aconnector->dc_sink = NULL; + } + drm_modeset_unlock(&root->mst_mgr.base.lock); } static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { @@ -342,7 +359,7 @@ dm_dp_mst_detect(struct drm_connector *connector, return connector_status_disconnected; connection_status = drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr, - aconnector->port); + aconnector->port); if (port->pdt != DP_PEER_DEVICE_NONE && !port->dpcd_rev) { uint8_t dpcd_rev; @@ -376,6 +393,17 @@ dm_dp_mst_detect(struct drm_connector *connector, port->dpcd_rev = 0; } + /* + * Release dc_sink for connector which unplug event is notified by CSN msg + */ + if (connection_status == connector_status_disconnected && aconnector->dc_sink) { + if (aconnector->dc_link->sink_count) + dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink); + + dc_sink_release(aconnector->dc_sink); + aconnector->dc_sink = NULL; + } + return connection_status; }