From 742db30c4ee6cd28142e83e154b5271f95a2c67a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Jan 2020 15:17:21 +0100 Subject: drm/nouveau: Add HD-audio component notifier support This patch adds the support for the notification of HD-audio hotplug via the already existing drm_audio_component framework. This allows us more reliable hotplug notification and ELD transfer without accessing HD-audio bus; it's more efficient, and more importantly, it works without waking up the runtime PM. The implementation is rather simplistic: nouveau driver provides the get_eld ops for HD-audio, and it notifies the audio hotplug via pin_eld_notify callback upon each nv50_audio_enable() and _disable() call. As the HD-audio pin assignment seems corresponding to the CRTC, the crtc->index number is passed directly as the zero-based port number. The bind and unbind callbacks handle the device-link so that it assures the PM call order. Link: https://lore.kernel.org/r/20190722143815.7339-3-tiwai@suse.de Reviewed-by: Lyude Paul Cc: Jaroslav Kysela Signed-off-by: Takashi Iwai Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Kconfig | 1 + drivers/gpu/drm/nouveau/dispnv50/disp.c | 111 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 7 ++ 3 files changed, 119 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index ce03693698ef..d6e4ae1ef705 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -17,6 +17,7 @@ config DRM_NOUVEAU select INPUT if ACPI && X86 select THERMAL if ACPI && X86 select ACPI_VIDEO if ACPI && X86 + select SND_HDA_COMPONENT if SND_HDA_CORE help Choose this option for open-source NVIDIA support. diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index a82b354e5a8c..2f123082c85d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -476,12 +477,113 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) return 0; } +/* + * audio component binding for ELD notification + */ +static void +nv50_audio_component_eld_notify(struct drm_audio_component *acomp, int port) +{ + if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) + acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + port, -1); +} + +static int +nv50_audio_component_get_eld(struct device *kdev, int port, int pipe, + bool *enabled, unsigned char *buf, int max_bytes) +{ + struct drm_device *drm_dev = dev_get_drvdata(kdev); + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct drm_encoder *encoder; + struct nouveau_encoder *nv_encoder; + struct nouveau_connector *nv_connector; + struct nouveau_crtc *nv_crtc; + int ret = 0; + + *enabled = false; + drm_for_each_encoder(encoder, drm->dev) { + nv_encoder = nouveau_encoder(encoder); + nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_crtc = nouveau_crtc(encoder->crtc); + if (!nv_connector || !nv_crtc || nv_crtc->index != port) + continue; + *enabled = drm_detect_monitor_audio(nv_connector->edid); + if (*enabled) { + ret = drm_eld_size(nv_connector->base.eld); + memcpy(buf, nv_connector->base.eld, + min(max_bytes, ret)); + } + break; + } + return ret; +} + +static const struct drm_audio_component_ops nv50_audio_component_ops = { + .get_eld = nv50_audio_component_get_eld, +}; + +static int +nv50_audio_component_bind(struct device *kdev, struct device *hda_kdev, + void *data) +{ + struct drm_device *drm_dev = dev_get_drvdata(kdev); + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct drm_audio_component *acomp = data; + + if (WARN_ON(!device_link_add(hda_kdev, kdev, DL_FLAG_STATELESS))) + return -ENOMEM; + + drm_modeset_lock_all(drm_dev); + acomp->ops = &nv50_audio_component_ops; + acomp->dev = kdev; + drm->audio.component = acomp; + drm_modeset_unlock_all(drm_dev); + return 0; +} + +static void +nv50_audio_component_unbind(struct device *kdev, struct device *hda_kdev, + void *data) +{ + struct drm_device *drm_dev = dev_get_drvdata(kdev); + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct drm_audio_component *acomp = data; + + drm_modeset_lock_all(drm_dev); + drm->audio.component = NULL; + acomp->ops = NULL; + acomp->dev = NULL; + drm_modeset_unlock_all(drm_dev); +} + +static const struct component_ops nv50_audio_component_bind_ops = { + .bind = nv50_audio_component_bind, + .unbind = nv50_audio_component_unbind, +}; + +static void +nv50_audio_component_init(struct nouveau_drm *drm) +{ + if (!component_add(drm->dev->dev, &nv50_audio_component_bind_ops)) + drm->audio.component_registered = true; +} + +static void +nv50_audio_component_fini(struct nouveau_drm *drm) +{ + if (drm->audio.component_registered) { + component_del(drm->dev->dev, &nv50_audio_component_bind_ops); + drm->audio.component_registered = false; + } +} + /****************************************************************************** * Audio *****************************************************************************/ static void nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) { + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nv50_disp *disp = nv50_disp(encoder->dev); struct { @@ -496,11 +598,14 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) }; nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); + + nv50_audio_component_eld_notify(drm->audio.component, nv_crtc->index); } static void nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) { + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; @@ -527,6 +632,8 @@ nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) nvif_mthd(&disp->disp->object, 0, &args, sizeof(args.base) + drm_eld_size(args.data)); + + nv50_audio_component_eld_notify(drm->audio.component, nv_crtc->index); } /****************************************************************************** @@ -2296,6 +2403,8 @@ nv50_display_destroy(struct drm_device *dev) { struct nv50_disp *disp = nv50_disp(dev); + nv50_audio_component_fini(nouveau_drm(dev)); + nv50_core_del(&disp->core); nouveau_bo_unmap(disp->sync); @@ -2444,6 +2553,8 @@ nv50_display_create(struct drm_device *dev) /* Disable vblank irqs aggressively for power-saving, safe on nv50+ */ dev->vblank_disable_immediate = true; + nv50_audio_component_init(drm); + out: if (ret) nv50_display_destroy(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index da8c46e09943..c2c332fbde97 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -58,6 +58,8 @@ #include #include +#include + #include "uapi/drm/nouveau_drm.h" struct nouveau_channel; @@ -211,6 +213,11 @@ struct nouveau_drm { struct nouveau_svm *svm; struct nouveau_dmem *dmem; + + struct { + struct drm_audio_component *component; + bool component_registered; + } audio; }; static inline struct nouveau_drm * -- cgit v1.2.3 From 4c9ee1bfca820b93f107957f5322845c862ea368 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 13:55:19 +1000 Subject: drm/nouveau: zero vma pointer even if we only unreference it rather than free I'm not sure this affects anything, but best be safe. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_vmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.c b/drivers/gpu/drm/nouveau/nouveau_vmm.c index 77061182a1cf..b28c7dc13ad6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vmm.c @@ -69,8 +69,8 @@ nouveau_vma_del(struct nouveau_vma **pvma) } list_del(&vma->head); kfree(*pvma); - *pvma = NULL; } + *pvma = NULL; } int -- cgit v1.2.3 From 0181f4bfbdcdfdf8474946bf14fd644727fb8363 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 13:47:12 +1000 Subject: drm/nouveau: reject attempts to submit to dead channels Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 05ec8edd6a8b..8f97534e996c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -702,6 +702,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (!chan) return nouveau_abi16_put(abi16, -ENOENT); + if (unlikely(atomic_read(&chan->killed))) + return nouveau_abi16_put(abi16, -ENODEV); req->vram_available = drm->gem.vram_available; req->gart_available = drm->gem.gart_available; -- cgit v1.2.3 From ea13e5abf807ea912ce84eef6a1946b9a38c6508 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 15:39:27 +1000 Subject: drm/nouveau: signal pending fences when channel has been killed Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_chan.c | 2 ++ drivers/gpu/drm/nouveau/nouveau_fence.c | 10 +++++++++- drivers/gpu/drm/nouveau/nouveau_fence.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 282fd90b65e1..d9381a053169 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -55,6 +55,8 @@ nouveau_channel_killed(struct nvif_notify *ntfy) struct nouveau_cli *cli = (void *)chan->user.client; NV_PRINTK(warn, cli, "channel %d killed!\n", chan->chid); atomic_set(&chan->killed, 1); + if (chan->fence) + nouveau_fence_context_kill(chan->fence, -ENODEV); return NVIF_NOTIFY_DROP; } diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 70bb6bb97af8..666f2090d92b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -87,7 +87,7 @@ nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) } void -nouveau_fence_context_del(struct nouveau_fence_chan *fctx) +nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) { struct nouveau_fence *fence; @@ -95,11 +95,19 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx) while (!list_empty(&fctx->pending)) { fence = list_entry(fctx->pending.next, typeof(*fence), head); + if (error) + dma_fence_set_error(&fence->base, error); + if (nouveau_fence_signal(fence)) nvif_notify_put(&fctx->notify); } spin_unlock_irq(&fctx->lock); +} +void +nouveau_fence_context_del(struct nouveau_fence_chan *fctx) +{ + nouveau_fence_context_kill(fctx, 0); nvif_notify_fini(&fctx->notify); fctx->dead = 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index c9e24baaaa4f..4887caa69c65 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -63,6 +63,7 @@ struct nouveau_fence_priv { void nouveau_fence_context_new(struct nouveau_channel *, struct nouveau_fence_chan *); void nouveau_fence_context_del(struct nouveau_fence_chan *); void nouveau_fence_context_free(struct nouveau_fence_chan *); +void nouveau_fence_context_kill(struct nouveau_fence_chan *, int error); int nv04_fence_create(struct nouveau_drm *); int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32); -- cgit v1.2.3 From 0352029ed83ff4d3f99e6bcf31bed5a97b07e3cf Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 15:52:12 +1000 Subject: drm/nouveau: support synchronous pushbuf submission This is useful for debugging GPU hangs. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 11 ++++++++++- include/uapi/drm/nouveau_drm.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 8f97534e996c..f5ece1f94973 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -688,7 +688,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, struct validate_op op; struct nouveau_fence *fence = NULL; int i, j, ret = 0; - bool do_reloc = false; + bool do_reloc = false, sync = false; if (unlikely(!abi16)) return -ENOMEM; @@ -705,6 +705,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (unlikely(atomic_read(&chan->killed))) return nouveau_abi16_put(abi16, -ENODEV); + sync = req->vram_available & NOUVEAU_GEM_PUSHBUF_SYNC; + req->vram_available = drm->gem.vram_available; req->gart_available = drm->gem.gart_available; if (unlikely(req->nr_push == 0)) @@ -852,6 +854,13 @@ revalidate: goto out; } + if (sync) { + if (!(ret = nouveau_fence_wait(fence, false, false))) { + if ((ret = dma_fence_get_status(&fence->base)) == 1) + ret = 0; + } + } + out: validate_fini(&op, chan, fence, bo); nouveau_fence_unref(&fence); diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h index 9459a6e3bc1f..853a327433d3 100644 --- a/include/uapi/drm/nouveau_drm.h +++ b/include/uapi/drm/nouveau_drm.h @@ -110,6 +110,7 @@ struct drm_nouveau_gem_pushbuf { __u64 push; __u32 suffix0; __u32 suffix1; +#define NOUVEAU_GEM_PUSHBUF_SYNC (1ULL << 0) __u64 vram_available; __u64 gart_available; }; -- cgit v1.2.3 From 0e6176c6d286316e9431b4f695940cfac4ffe6c2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 28 Jan 2020 14:39:26 +1000 Subject: drm/nouveau/disp/nv50-: prevent oops when no channel method map provided The implementations for most channel types contains a map of methods to priv registers in order to provide debugging info when a disp exception has been raised. This info is missing from the implementation of PIO channels as they're rather simplistic already, however, if an exception is raised by one of them, we'd end up triggering a NULL-pointer deref. Not ideal... Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=206299 Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c index bcf32d92ee5a..50e3539f33d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c @@ -74,6 +74,8 @@ nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) if (debug > subdev->debug) return; + if (!mthd) + return; for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { u32 base = chan->head * mthd->addr; -- cgit v1.2.3 From 86e18ebd87072ed1ba6ecd86271e7a712115d579 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 28 Jan 2020 15:03:25 +1000 Subject: drm/nouveau/disp/gv100-: not all channel types support reporting error codes Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index 892be6c9b76c..3aa2cc3af1e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -101,15 +101,26 @@ gv100_disp_exception(struct nv50_disp *disp, int chid) u32 stat = nvkm_rd32(device, 0x611020 + (chid * 12)); u32 type = (stat & 0x00007000) >> 12; u32 mthd = (stat & 0x00000fff) << 2; - u32 data = nvkm_rd32(device, 0x611024 + (chid * 12)); - u32 code = nvkm_rd32(device, 0x611028 + (chid * 12)); const struct nvkm_enum *reason = nvkm_enum_find(nv50_disp_intr_error_type, type); - nvkm_error(subdev, "chid %d stat %08x reason %d [%s] mthd %04x " - "data %08x code %08x\n", - chid, stat, type, reason ? reason->name : "", - mthd, data, code); + /*TODO: Suspect 33->41 are for WRBK channel exceptions, but we + * don't support those currently. + * + * CORE+WIN CHIDs map directly to the FE_EXCEPT() slots. + */ + if (chid <= 32) { + u32 data = nvkm_rd32(device, 0x611024 + (chid * 12)); + u32 code = nvkm_rd32(device, 0x611028 + (chid * 12)); + nvkm_error(subdev, "chid %d stat %08x reason %d [%s] " + "mthd %04x data %08x code %08x\n", + chid, stat, type, reason ? reason->name : "", + mthd, data, code); + } else { + nvkm_error(subdev, "chid %d stat %08x reason %d [%s] " + "mthd %04x\n", + chid, stat, type, reason ? reason->name : "", mthd); + } if (chid < ARRAY_SIZE(disp->chan) && disp->chan[chid]) { switch (mthd) { -- cgit v1.2.3 From 1c338ed5e52b62737a9d45f37f085bdbb367821b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 29 Jan 2020 11:20:34 +1000 Subject: drm/nouveau/acr: return error when registering LSF if ACR not supported This fixes an oops on TU11x GPUs where SEC2 attempts to register its falcon, and triggers a NULL-pointer deref because ACR isn't yet supported. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c index 9896462960ea..07d1830126ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c @@ -58,8 +58,12 @@ struct nvkm_acr_lsfw * nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *func, struct nvkm_acr *acr, struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id) { - struct nvkm_acr_lsfw *lsfw = nvkm_acr_lsfw_get(acr, id); + struct nvkm_acr_lsfw *lsfw; + + if (!acr) + return ERR_PTR(-ENOSYS); + lsfw = nvkm_acr_lsfw_get(acr, id); if (lsfw && lsfw->func) { nvkm_error(&acr->subdev, "LSFW %d redefined\n", id); return ERR_PTR(-EEXIST); -- cgit v1.2.3 From c3463aed05abf06bd5ebaac12f2c015db298b98f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 29 Jan 2020 11:29:05 +1000 Subject: drm/nouveau/fb/gp102-: allow module to load even when scrubber binary is missing Without relaxing this requirement, TU10x boards will fail to load without an updated linux-firmware, and TU11x will completely fail to load because FW isn't available yet. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 39 +++++++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | 5 ++-- 2 files changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index d09db7c6b7ee..5940e0dea2f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -125,6 +125,34 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev) return nvkm_mm_init(&fb->tags, 0, 0, tags, 1); } +static int +nvkm_fb_init_scrub_vpr(struct nvkm_fb *fb) +{ + struct nvkm_subdev *subdev = &fb->subdev; + int ret; + + nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); + + if (!fb->vpr_scrubber.size) { + nvkm_warn(subdev, "VPR locked, but no scrubber binary!\n"); + return 0; + } + + ret = fb->func->vpr.scrub(fb); + if (ret) { + nvkm_error(subdev, "VPR scrubber binary failed\n"); + return ret; + } + + if (fb->func->vpr.scrub_required(fb)) { + nvkm_error(subdev, "VPR still locked after scrub!\n"); + return -EIO; + } + + nvkm_debug(subdev, "VPR scrubber binary successful\n"); + return 0; +} + static int nvkm_fb_init(struct nvkm_subdev *subdev) { @@ -157,18 +185,9 @@ nvkm_fb_init(struct nvkm_subdev *subdev) if (fb->func->vpr.scrub_required && fb->func->vpr.scrub_required(fb)) { - nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); - - ret = fb->func->vpr.scrub(fb); + ret = nvkm_fb_init_scrub_vpr(fb); if (ret) return ret; - - if (fb->func->vpr.scrub_required(fb)) { - nvkm_error(subdev, "VPR still locked after scrub!\n"); - return -EIO; - } - - nvkm_debug(subdev, "VPR scrubber binary successful\n"); } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index 9be7316c6642..fc8c93aa3da5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -120,8 +120,9 @@ gp102_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, if (ret) return ret; - return nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, - &(*pfb)->vpr_scrubber); + nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, + &(*pfb)->vpr_scrubber); + return 0; } int -- cgit v1.2.3