[PATCH v2] drm/amd/display: Handle removed connector in early_unregister
Harry Wentland
harry.wentland at amd.com
Thu Feb 3 18:18:58 UTC 2022
On 2022-02-03 13:17, Fangzhi Zuo wrote:
> From: Wayne Lin <Wayne.Lin at amd.com>
>
> This patch lived in our internal branch since August
> but somehow missed the merge to upstream.
>
> Original patch description:
>
> [Why]
> commit "drm/amd/display: turn DPMS off on connector unplug" and
> commit "drm/amd/display: Clear dc remote sinks on MST disconnect"
> were trying to resolve the resource problem when we connectors get
> disconnected under MST scenarios. However, these patches don't
> really clean up all remote sinks. Nor turns DPMS off on all affected
> streams. Also, these can't handle disconnected connectors reported by CSN.
>
> [How]
> - Revise commit "drm/amd/display: turn DPMS off on connector unplug"
> a bit to handle none mst case only.
> - Revert commit "drm/amd/display: Clear dc remote sinks on MST disconnect"
> - Revise a bit the logic in above patches and change to turn DPMS
> off/clear dc remote sink within amdgpu_dm_mst_connector_early_unregister().
> Since drm will call .early_unregister for all disconnected connectors,
> we can ensure to also handle disconnected connectors reported by CSN.
>
> Signed-off-by: Wayne Lin <Wayne.Lin at amd.com>
> Signed-off-by: Fangzhi Zuo <Jerry.Zuo at amd.com>
Reviewed-by: Harry Wentland <harry.wentland at amd.com>
Harry
> ---
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++
> .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 41 +++++++++++++++++--
> .../gpu/drm/amd/display/dc/core/dc_stream.c | 12 ++++++
> drivers/gpu/drm/amd/display/dc/dc_stream.h | 1 +
> 4 files changed, 58 insertions(+), 3 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 f5941e59e5ad..529b3ddaa10b 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -3034,6 +3034,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
> struct drm_connector *connector = &aconnector->base;
> struct drm_device *dev = connector->dev;
> enum dc_connection_type new_connection_type = dc_connection_none;
> + enum dc_connection_type old_connection_type = aconnector->dc_link->type;
> struct amdgpu_device *adev = drm_to_adev(dev);
> struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
> struct dm_crtc_state *dm_crtc_state = NULL;
> @@ -3074,7 +3075,13 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
> drm_kms_helper_hotplug_event(dev);
>
> } else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
> + /**
> + * MST cases are handled within .early_unregister where we
> + * can handle disconnected conectors reported by long HPD
> + * and CSN.
> + */
> if (new_connection_type == dc_connection_none &&
> + old_connection_type != dc_connection_mst_branch &&
> aconnector->dc_link->type == dc_connection_none &&
> dm_crtc_state)
> dm_set_dpms_off(aconnector->dc_link, dm_crtc_state);
> 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 8e97d21bdf5c..7cd1f1f57d6e 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
> @@ -139,11 +139,46 @@ 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 =
> - to_amdgpu_dm_connector(connector);
> - struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
> + struct amdgpu_dm_connector *aconnector =
> + to_amdgpu_dm_connector(connector);
> + struct drm_dp_mst_port *port = aconnector->port;
> + struct dc_stream_update stream_update;
> + struct dc_stream_state *stream_state;
> + struct drm_device *ddev = aconnector->base.dev;
> + struct amdgpu_device *adev = drm_to_adev(ddev);
> + struct dc_link *dc_link = aconnector->dc_link;
> + struct dc_sink *dc_sink = aconnector->dc_sink;
> + bool dpms_off = true;
>
> drm_dp_mst_connector_early_unregister(connector, port);
> +
> + ASSERT(dc_link);
> +
> + if (dc_sink) {
> + mutex_lock(&ddev->mode_config.mutex);
> + mutex_lock(&adev->dm.dc_lock);
> +
> + memset(&stream_update, 0, sizeof(stream_update));
> + stream_update.dpms_off = &dpms_off;
> +
> + /*set stream dpms_off*/
> + stream_state = dc_stream_get_stream_by_sink(dc_sink);
> + if (stream_state != NULL) {
> + stream_update.stream = stream_state;
> + dc_commit_updates_for_stream(stream_state->ctx->dc, NULL, 0,
> + stream_state, &stream_update,
> + stream_state->ctx->dc->current_state);
> + }
> +
> + /*clear the remote sink of the link*/
> + dc_link_remove_remote_sink(dc_link, dc_sink);
> + dc_sink_release(dc_sink);
> + aconnector->dc_sink = NULL;
> +
> + mutex_unlock(&adev->dm.dc_lock);
> + mutex_unlock(&ddev->mode_config.mutex);
> + }
> +
> }
>
> static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
> index 57cf4cb82370..a77c90c14e85 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
> @@ -739,3 +739,15 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
> stream->link->link_index);
> }
>
> +struct dc_stream_state *dc_stream_get_stream_by_sink(struct dc_sink *sink)
> +{
> + uint8_t i;
> + struct dc_context *ctx = sink->ctx;
> +
> + for (i = 0; i < ctx->dc->current_state->stream_count; i++) {
> + if (ctx->dc->current_state->streams[i]->sink == sink)
> + return ctx->dc->current_state->streams[i];
> + }
> +
> + return NULL;
> +}
> \ No newline at end of file
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> index f631b61abedd..89f67c711161 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> @@ -321,6 +321,7 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream);
> uint8_t dc_get_current_stream_count(struct dc *dc);
> struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i);
> struct dc_stream_state *dc_stream_find_from_link(const struct dc_link *link);
> +struct dc_stream_state *dc_stream_get_stream_by_sink(struct dc_sink *sink);
>
> /*
> * Return the current frame counter.
More information about the amd-gfx
mailing list