nouveau_connector_irq() schedules irq_work on the system workqueue.
nouveau_connector_destroy() calls nvif_event_dtor() which unregisters
the interrupt event source so no new callbacks will fire, but it does
not drain the system workqueue.  If a work item was already queued,
nouveau_dp_irq() can run after kfree(connector) and dereference freed
memory.

Add cancel_work_sync() after nvif_event_dtor() so any in-flight or
pending irq_work completes before the connector is freed.

Cc: [email protected]
Signed-off-by: Aldo Ariel Panzardo <[email protected]>
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index XXXXXXX..YYYYYYY 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -395,6 +395,7 @@ nouveau_connector_destroy(struct drm_connector *connector)
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        nvif_event_dtor(&nv_connector->irq);
        nvif_event_dtor(&nv_connector->hpd);
+       cancel_work_sync(&nv_connector->irq_work);
        kfree(nv_connector->edid);
        drm_connector_unregister(connector);
        drm_connector_cleanup(connector);

Reply via email to