]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
drm/nouveau: don't attempt to schedule hpd_work on headless cards
authorVasily Khoruzhick <anarsoul@gmail.com>
Fri, 7 Jun 2024 22:09:32 +0000 (15:09 -0700)
committerDanilo Krummrich <dakr@redhat.com>
Tue, 11 Jun 2024 10:04:59 +0000 (12:04 +0200)
If the card doesn't have display hardware, hpd_work and hpd_lock are
left uninitialized which causes BUG when attempting to schedule hpd_work
on runtime PM resume.

Fix it by adding headless flag to DRM and skip any hpd if it's set.

Fixes: ae1aadb1eb8d ("nouveau: don't fail driver load if no display hw present.")
Link: https://gitlab.freedesktop.org/drm/nouveau/-/issues/337
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Reviewed-by: Ben Skeggs <bskeggs@nvidia.com>
Signed-off-by: Danilo Krummrich <dakr@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240607221032.25918-1-anarsoul@gmail.com
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drv.h

index 13705c5f1497329a03d754ab9bfaacb6209de4b2..4b7497a8755cdb881586ecf5cc41dd151449f4bf 100644 (file)
@@ -68,7 +68,7 @@ nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend)
        if (nv_two_heads(dev))
                NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0);
 
-       if (!runtime)
+       if (!runtime && !drm->headless)
                cancel_work_sync(&drm->hpd_work);
 
        if (!suspend)
index 88728a0b2c259550ab6fc91c8e9754579d81a524..674dc567e1798a2636a93e57c187dfc89e0cc4c6 100644 (file)
@@ -2680,7 +2680,7 @@ nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend)
                        nv50_mstm_fini(nouveau_encoder(encoder));
        }
 
-       if (!runtime)
+       if (!runtime && !drm->headless)
                cancel_work_sync(&drm->hpd_work);
 }
 
index aed5d5b51b43d623fd90e9f2cde3925e8d58bad9..d4725a968827e9a7f1f1a8d64ea4c34e08f999a6 100644 (file)
@@ -450,6 +450,9 @@ nouveau_display_hpd_resume(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
 
+       if (drm->headless)
+               return;
+
        spin_lock_irq(&drm->hpd_lock);
        drm->hpd_pending = ~0;
        spin_unlock_irq(&drm->hpd_lock);
@@ -635,7 +638,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
        }
        drm_connector_list_iter_end(&conn_iter);
 
-       if (!runtime)
+       if (!runtime && !drm->headless)
                cancel_work_sync(&drm->hpd_work);
 
        drm_kms_helper_poll_disable(dev);
@@ -729,6 +732,7 @@ nouveau_display_create(struct drm_device *dev)
                /* no display hw */
                if (ret == -ENODEV) {
                        ret = 0;
+                       drm->headless = true;
                        goto disp_create_err;
                }
 
index e239c6bf4afa4f75d4ca30c63583af82f2ab9621..25fca98a20bcd9522a4ef091da3d5c5adfc682eb 100644 (file)
@@ -276,6 +276,7 @@ struct nouveau_drm {
        /* modesetting */
        struct nvbios vbios;
        struct nouveau_display *display;
+       bool headless;
        struct work_struct hpd_work;
        spinlock_t hpd_lock;
        u32 hpd_pending;