On Fri, Apr 05, 2024 at 05:17:14PM -0700, Abhinav Kumar wrote: > From: Kuogee Hsieh <quic_khsieh@xxxxxxxxxxx> > > In the external HPD case, hotplug event is delivered by pmic glink to DP driver > using drm_aux_hpd_bridge_notify(). There can be other drivers in front of the DP chain. For example, altmode driver uses drm_connector_oob_hotplug_event() to deliver HPD events. > > The stacktrace showing the sequence of events is below: > > dp_bridge_hpd_notify+0x18/0x70 [msm] > drm_bridge_connector_detect+0x60/0xe8 [drm_kms_helper] > drm_helper_probe_detect+0x94/0xc0 [drm_kms_helper] > drm_helper_probe_single_connector_modes+0x43c/0x53c [drm_kms_helper] > drm_client_modeset_probe+0x240/0x1114 [drm] > drm_fb_helper_hotplug_event.part.26+0x9c/0xe8 [drm_kms_helper] > drm_fb_helper_hotplug_event+0x24/0x38 [drm_kms_helper] > msm_fbdev_client_hotplug+0x24/0xd4 [msm] > drm_client_dev_hotplug+0xd8/0x148 [drm] > drm_kms_helper_connector_hotplug_event+0x30/0x3c [drm_kms_helper] > drm_bridge_connector_handle_hpd+0x84/0x94 [drm_kms_helper] > drm_bridge_connector_hpd_cb+0xc/0x14 [drm_kms_helper] > drm_bridge_hpd_notify+0x38/0x50 [drm] > drm_aux_hpd_bridge_notify+0x14/0x20 [aux_hpd_bridge] > pmic_glink_altmode_worker+0xec/0x27c [pmic_glink_altmode] > process_scheduled_works+0x17c/0x2cc > worker_thread+0x2ac/0x2d0 > kthread+0xfc/0x120 > > There are three notifications delivered to DP driver for each notification event. > > 1) From the drm_aux_hpd_bridge_notify() itself as shown above > > 2) From output_poll_execute() thread which arises due to > drm_helper_probe_single_connector_modes() call of the above stacktrace > as shown in more detail here. > > dp_bridge_hpd_notify+0x18/0x70 [msm] > drm_bridge_connector_detect+0x60/0xe8 [drm_kms_helper] > drm_helper_probe_detect+0x94/0xc0 [drm_kms_helper] > drm_helper_probe_single_connector_modes+0x43c/0x53c [drm_kms_helper] > drm_client_modeset_probe+0x240/0x1114 [drm] > drm_fb_helper_hotplug_event.part.26+0x9c/0xe8 [drm_kms_helper] > drm_fb_helper_hotplug_event+0x24/0x38 [drm_kms_helper] > msm_fbdev_client_hotplug+0x24/0xd4 [msm] > drm_client_dev_hotplug+0xd8/0x148 [drm] > drm_kms_helper_hotplug_event+0x30/0x3c [drm_kms_helper] > output_poll_execute+0xe0/0x210 [drm_kms_helper] > > 3) From the DP driver as the dp_bridge_hpd_notify() callback today triggers > the hpd_event_thread for connect and disconnect events respectively via below stack > > dp_bridge_hpd_notify+0x18/0x70 [msm] > drm_bridge_connector_detect+0x60/0xe8 [drm_kms_helper] > drm_helper_probe_detect_ctx+0x98/0x110 [drm_kms_helper] > check_connector_changed+0x4c/0x20c [drm_kms_helper] > drm_helper_hpd_irq_event+0x98/0x120 [drm_kms_helper] > hpd_event_thread+0x478/0x5bc [msm] > > We have to address why we end up with 3 events for every single event so something > is broken with how we work with the drm_bridge_connector. > > But, the dp_bridge_hpd_notify() delivered from output_poll_execute() thread will > return the incorrect HPD status DP driver because the .detect() returns the value > of link_ready and not the HPD status currently. > > And because the HPD event thread has not run yet and this results in the two complementary > events. > > To fix this problem lets have dp_bridge_hpd_notify() call > dp_hpd_plug_handle/unplug_handle() directly instead of going through the > event thread. > > Then the following .detect() called by drm_kms_helper_connector_hotplug_event() > will return correct value of HPD status since it uses the correct link_ready value. > > With this change, the HPD status delivered by both drm_bridge_connector_hpd_notify() > and drm_kms_helper_connector_hotplug_event() will match each other consistently. Please take a look at Documentation/process/submitting-patches.rst With the commit message fixed, the change LGTM. Thanks a lot for describing the call chains leading to this issue. I must admit, initially I thought that the change should be rejected on a basis of being a band-aid, but after studying the call graphs and the locking within the DP driver, the change looks correct to me. > > changes in v2: > - Fix the commit message to explain the scenario > - Fix the subject a little as well > > Fixes: 542b37efc20e ("drm/msm/dp: Implement hpd_notify()") > Signed-off-by: Kuogee Hsieh <quic_khsieh@xxxxxxxxxxx> > Signed-off-by: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx> > --- > drivers/gpu/drm/msm/dp/dp_display.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c > index d80f89581760..dfb10584ff97 100644 > --- a/drivers/gpu/drm/msm/dp/dp_display.c > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > @@ -1665,7 +1665,8 @@ void dp_bridge_hpd_notify(struct drm_bridge *bridge, > return; > > if (!dp_display->link_ready && status == connector_status_connected) > - dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0); > + dp_hpd_plug_handle(dp, 0); > else if (dp_display->link_ready && status == connector_status_disconnected) > - dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0); > + dp_hpd_unplug_handle(dp, 0); > + > } > -- > 2.43.2 > -- With best wishes Dmitry