From: "David R. Hedges" <[email protected]>

nouveau_dp_irq() passes an IRQ_HPD to the HPD worker as
NVIF_CONN_EVENT_V0_IRQ, adding NVIF_CONN_EVENT_V0_PLUG when the sink
count has changed, or NVIF_CONN_EVENT_V0_UNPLUG when servicing an MST
hub fails.  A real plug or unplug can also be pending in the same bits
by the time the worker runs.  nouveau_display_hpd_work() skips
connector detection for anything with the IRQ bit set, though, as long
as nouveau_dp_link_check() reports the link as fine, which it does
whenever there's no trained link to look at, so those plug and unplug
events are dropped.

Only take the link check shortcut for an IRQ_HPD on its own.

Fixes: 016dacb60e6d ("drm/nouveau/kms: pass event mask to hpd handler")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: David R. Hedges <[email protected]>
---
 drivers/gpu/drm/nouveau/nouveau_display.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index d71dcfc6ee66..4398cf0fc541 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -462,7 +462,12 @@ nouveau_display_hpd_work(struct work_struct *work)
                            !!(bits & NVIF_CONN_EVENT_V0_UNPLUG),
                            !!(bits & NVIF_CONN_EVENT_V0_IRQ));
 
-               if (bits & NVIF_CONN_EVENT_V0_IRQ) {
+               /* A plug or unplug event pending alongside the IRQ, such as a
+                * sink count change reported by nouveau_dp_irq(), still needs
+                * connector detection.
+                */
+               if ((bits & NVIF_CONN_EVENT_V0_IRQ) &&
+                   !(bits & (NVIF_CONN_EVENT_V0_PLUG | 
NVIF_CONN_EVENT_V0_UNPLUG))) {
                        if (nouveau_dp_link_check(nv_connector))
                                continue;
                }

-- 
2.55.0


Reply via email to