[PATCH v2] drm/nouveau: don't attempt to schedule hpd_work on headless cards
Ben Skeggs
bskeggs at nvidia.com
Mon Jun 10 08:12:07 UTC 2024
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;
More information about the Nouveau
mailing list