On 2022-02-02 13:49, Fangzhi Zuo wrote: > From: Wayne Lin <Wayne.Lin@xxxxxxx> > > [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" I don't see this revert as part of this commit. Generally, if we revert code it should be done in a single revert commit that is generated via "git revert". Harry > - 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@xxxxxxx> > Signed-off-by: Fangzhi Zuo <Jerry.Zuo@xxxxxxx> > --- > .../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..411b55596b00 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.