drm/nouveau/fb/gp102-: unlock VPR right after devinit
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:47:52 +0000 (20:47 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 9 Nov 2022 00:44:58 +0000 (10:44 +1000)
Under memory load, instmem allocations could end up in the regions of
VRAM that are inaccessible right after boot, and be corrupted after a
suspend/resume cycle as a result of being restored before booting the
mem unlock firmware.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c

index f2bd9b11c84a2073f06d8eca0ec432837e9ddd51..40768373cdd90de752d157568135061ff4790310 100644 (file)
@@ -58,6 +58,8 @@ struct nvkm_fb {
        struct nvkm_memory *mmu_wr;
 };
 
+int nvkm_fb_mem_unlock(struct nvkm_fb *);
+
 void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size,
                       u32 pitch, u32 flags, struct nvkm_fb_tile *);
 void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *);
index 852c18aec4cdbb7c18cdd1fa9be558e07a70531d..c94de7b4555677e48cc12b14bad814848389bbf9 100644 (file)
@@ -2808,6 +2808,10 @@ nvkm_device_preinit(struct nvkm_device *device)
        if (ret)
                goto fail;
 
+       ret = nvkm_fb_mem_unlock(device->fb);
+       if (ret)
+               goto fail;
+
        time = ktime_to_us(ktime_get()) - time;
        nvdev_trace(device, "preinit completed in %lldus\n", time);
        return 0;
index 2ebdec44236d8d1bb4c14fd2a8eeb557576b83f5..bac7dcc4c2c1308fc36c3ea2b5ef5ef3351ce4d4 100644 (file)
@@ -134,12 +134,20 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev)
        return nvkm_mm_init(&fb->tags.mm, 0, 0, tags, 1);
 }
 
-static int
-nvkm_fb_init_scrub_vpr(struct nvkm_fb *fb)
+int
+nvkm_fb_mem_unlock(struct nvkm_fb *fb)
 {
        struct nvkm_subdev *subdev = &fb->subdev;
        int ret;
 
+       if (!fb->func->vpr.scrub_required)
+               return 0;
+
+       if (!fb->func->vpr.scrub_required(fb)) {
+               nvkm_debug(subdev, "VPR not locked\n");
+               return 0;
+       }
+
        nvkm_debug(subdev, "VPR locked, running scrubber binary\n");
 
        if (!fb->vpr_scrubber.size) {
@@ -194,13 +202,6 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
        if (fb->func->init_unkn)
                fb->func->init_unkn(fb);
 
-       if (fb->func->vpr.scrub_required &&
-           fb->func->vpr.scrub_required(fb)) {
-               ret = nvkm_fb_init_scrub_vpr(fb);
-               if (ret)
-                       return ret;
-       }
-
        return 0;
 }