inno_hdmi_irq() passes hdmi->bridge.dev to drm_helper_hpd_irq_event(),
which dereferences it in its first statement:

        if (!dev->mode_config.poll_enabled)

bridge.dev is assigned only by drm_bridge_attach(), but inno_hdmi_bind()
unmutes the hotplug interrupt in inno_hdmi_init_hw() and installs the
handler well before it attaches the bridge:

        inno_hdmi_init_hw(hdmi);                /* unmutes hotplug */
        devm_request_threaded_irq(...);         /* handler goes live */
        ...
        hdmi->bridge.ddc = inno_hdmi_i2c_adapter(hdmi);
        devm_drm_bridge_add(dev, &hdmi->bridge);
        drm_bridge_attach(...);                 /* bridge.dev set here */

The bridge is allocated by devm_drm_bridge_alloc(), which kzalloc()s it,
so bridge.dev is NULL for all of that window, and a hotplug event
arriving in it enters drm_helper_hpd_irq_event(NULL).

Before the conversion to a bridge the ordering was safe:
inno_hdmi_register() called drmm_connector_hdmi_init(), which set
connector.dev, before the interrupt was requested.

Drop hotplug events that arrive before the bridge is attached.

Fixes: 969325a2597e ("drm/rockchip: inno-hdmi: Convert to drm bridge")
Signed-off-by: Michal Wilczynski <[email protected]>
---
 drivers/gpu/drm/bridge/inno-hdmi.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c 
b/drivers/gpu/drm/bridge/inno-hdmi.c
index 
d7c33b92e2ddf4ced84d17304463f44be52270b8..d29832249b942dec84fb9d07a0b21ee751fc0486
 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -929,7 +929,13 @@ static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
 {
        struct inno_hdmi *hdmi = dev_id;
 
-       drm_helper_hpd_irq_event(hdmi->bridge.dev);
+       /*
+        * The interrupt is requested before the bridge is attached, and
+        * bridge.dev is only set by drm_bridge_attach(). Drop hotplug events
+        * that arrive before then rather than dereference a NULL drm_device.
+        */
+       if (hdmi->bridge.dev)
+               drm_helper_hpd_irq_event(hdmi->bridge.dev);
 
        return IRQ_HANDLED;
 }

-- 
2.34.1

Reply via email to