DP IRQ_HPD does not necessarily indicate a display connection change. It can also signal link status changes or pending MST messages, which need bridge-side handling but do not necessarily require userspace to reprobe the connector.
Currently, the HPD handler sends a hotplug event for every notification, without distinguishing ordinary HPD from IRQ_HPD. This causes IRQ_HPD notifications with no connection change to trigger unnecessary connector reprobes. However, filtering out all IRQ_HPD notifications would also discard hotplug events for downstream display connection changes on a DP branch, where upstream HPD can remain asserted. The decision therefore needs to use the actual connector status after handling the notification, rather than the raw HPD status reported by the event. Pass the event to the bridge chain first, then call the bridge .detect() callback to update connector->status. Fall back to the reported status when no .detect() callback is available. For IRQ_HPD, send a hotplug event only when the connector status changes, suppressing IRQ-only notifications while preserving notifications for downstream connection changes. Keep hotplug events unconditional for ordinary HPD notifications. An earlier detect may already have updated the connection status before subsequent plug handling reads the EDID, so a reprobe is still needed. Signed-off-by: Yongxing Mou <[email protected]> --- drivers/gpu/drm/display/drm_bridge_connector.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 083d70017f02..d27ce59ca32b 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -159,15 +159,28 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri enum drm_connector_dp_event event) { struct drm_connector *connector = &drm_bridge_connector->base; + struct drm_bridge *detect = drm_bridge_connector->bridge_detect; struct drm_device *dev = connector->dev; + enum drm_connector_status old_status, new_status; + bool level_hpd; + bool changed; + + level_hpd = event == DRM_CONNECTOR_NO_EXTRA_STATUS; mutex_lock(&dev->mode_config.mutex); - connector->status = status; + old_status = connector->status; mutex_unlock(&dev->mode_config.mutex); drm_bridge_connector_hpd_notify(connector, status, event); - drm_kms_helper_connector_hotplug_event(connector); + mutex_lock(&dev->mode_config.mutex); + new_status = detect ? detect->funcs->detect(detect, connector) : status; + connector->status = new_status; + changed = new_status != old_status; + mutex_unlock(&dev->mode_config.mutex); + + if (changed || level_hpd) + drm_kms_helper_connector_hotplug_event(connector); } static void drm_bridge_connector_hpd_cb(void *cb_data, -- 2.43.0
