This is a note to let you know that I've just added the patch titled drm/msm/dp: promote irq_hpd handle to handle link training correctly to the 5.10-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: drm-msm-dp-promote-irq_hpd-handle-to-handle-link-tra.patch and it can be found in the queue-5.10 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 57c6435a0b3195c904bb1792d9f50584ce87588f Author: Kuogee Hsieh <khsieh@xxxxxxxxxxxxxx> Date: Tue Nov 3 12:49:02 2020 -0800 drm/msm/dp: promote irq_hpd handle to handle link training correctly [ Upstream commit 26b8d66a399e625f3aa2c02ccbab1bff2e00040c ] Some dongles require link training done at irq_hpd request instead of plugin request. This patch promote irq_hpd handler to handle link training and setup hpd_state correctly. Signed-off-by: Kuogee Hsieh <khsieh@xxxxxxxxxxxxxx> Signed-off-by: Rob Clark <robdclark@xxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index d504cf68283a..f1f777baa2c4 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -476,10 +476,9 @@ static int dp_display_handle_irq_hpd(struct dp_display_private *dp) sink_request = dp->link->sink_request; if (sink_request & DS_PORT_STATUS_CHANGED) { - dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); if (dp_display_is_sink_count_zero(dp)) { DRM_DEBUG_DP("sink count is zero, nothing to do\n"); - return 0; + return -ENOTCONN; } return dp_display_process_hpd_high(dp); @@ -496,7 +495,9 @@ static int dp_display_handle_irq_hpd(struct dp_display_private *dp) static int dp_display_usbpd_attention_cb(struct device *dev) { int rc = 0; + u32 sink_request; struct dp_display_private *dp; + struct dp_usbpd *hpd; if (!dev) { DRM_ERROR("invalid dev\n"); @@ -510,10 +511,26 @@ static int dp_display_usbpd_attention_cb(struct device *dev) return -ENODEV; } + hpd = dp->usbpd; + /* check for any test request issued by sink */ rc = dp_link_process_request(dp->link); - if (!rc) - dp_display_handle_irq_hpd(dp); + if (!rc) { + sink_request = dp->link->sink_request; + if (sink_request & DS_PORT_STATUS_CHANGED) { + /* same as unplugged */ + hpd->hpd_high = 0; + dp->hpd_state = ST_DISCONNECT_PENDING; + dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); + } + + rc = dp_display_handle_irq_hpd(dp); + + if (!rc && (sink_request & DS_PORT_STATUS_CHANGED)) { + hpd->hpd_high = 1; + dp->hpd_state = ST_CONNECT_PENDING; + } + } return rc; }