Vasily Khoruzhick
2024-Jun-07  22:11 UTC
[PATCH v2] drm/nouveau: don't attempt to schedule hpd_work on headless cards
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 at gmail.com>
---
v2: drop extra checks in nouveau_display_hpd_work() and
nouveau_connector_hpd()
 drivers/gpu/drm/nouveau/dispnv04/disp.c   | 2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 2 +-
 drivers/gpu/drm/nouveau/nouveau_display.c | 6 +++++-
 drivers/gpu/drm/nouveau/nouveau_drv.h     | 1 +
 4 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c
b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 13705c5f1497..4b7497a8755c 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -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)
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 88728a0b2c25..674dc567e179 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -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);
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c
b/drivers/gpu/drm/nouveau/nouveau_display.c
index aed5d5b51b43..d4725a968827 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -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;
 		}
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h
b/drivers/gpu/drm/nouveau/nouveau_drv.h
index e239c6bf4afa..25fca98a20bc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -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;
-- 
2.45.2
Ben Skeggs
2024-Jun-10  08:12 UTC
[PATCH v2] drm/nouveau: don't attempt to schedule hpd_work on headless cards
On 8/6/24 08:09, Vasily Khoruzhick wrote:> 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 at gmail.com>Reviewed-by: Ben Skeggs <bskeggs at nvidia.com>> --- > v2: drop extra checks in nouveau_display_hpd_work() and > nouveau_connector_hpd() > > drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- > drivers/gpu/drm/nouveau/nouveau_display.c | 6 +++++- > drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + > 4 files changed, 8 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c > index 13705c5f1497..4b7497a8755c 100644 > --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c > @@ -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) > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c > index 88728a0b2c25..674dc567e179 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c > @@ -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); > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c > index aed5d5b51b43..d4725a968827 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_display.c > +++ b/drivers/gpu/drm/nouveau/nouveau_display.c > @@ -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; > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h > index e239c6bf4afa..25fca98a20bc 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_drv.h > +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h > @@ -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;
Danilo Krummrich
2024-Jun-11  10:09 UTC
[PATCH v2] drm/nouveau: don't attempt to schedule hpd_work on headless cards
On 6/8/24 00:09, Vasily Khoruzhick wrote:> 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 at gmail.com>Applied to drm-misc-fixes, thanks!> --- > v2: drop extra checks in nouveau_display_hpd_work() and > nouveau_connector_hpd() > > drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- > drivers/gpu/drm/nouveau/nouveau_display.c | 6 +++++- > drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + > 4 files changed, 8 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c > index 13705c5f1497..4b7497a8755c 100644 > --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c > @@ -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) > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c > index 88728a0b2c25..674dc567e179 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c > @@ -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); > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c > index aed5d5b51b43..d4725a968827 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_display.c > +++ b/drivers/gpu/drm/nouveau/nouveau_display.c > @@ -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; > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h > index e239c6bf4afa..25fca98a20bc 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_drv.h > +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h > @@ -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;
Maybe Matching Threads
- [PATCH] drm/nouveau: don't attempt to schedule hpd_work on headless cards
 - [PATCH] drm/nouveau: don't attempt to schedule hpd_work on headless cards
 - [PATCH v2] drm/nouveau: don't attempt to schedule hpd_work on headless cards
 - [RFC v4 00/20] drm/dp, i915, nouveau: Cleanup nouveau HPD and add DP features from i915
 - [RFC v2 00/20] drm/dp, i915, nouveau: Cleanup nouveau HPD and add DP features from i915