drm/nouveau/gr/gf100-: call FECS WFI_GOLDEN_SAVE method
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:48:08 +0000 (20:48 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 9 Nov 2022 00:45:11 +0000 (10:45 +1000)
This won't work on Ampere, and, it's questionable whether we should have
been using our FW's method of storing the golden context image with NV's
firmware to begin with.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h

index 332590f861fb50312e632442fd8bc7bc181588cb..eef9b3f065fd969e46f07dbef33b11514ea1c133 100644 (file)
@@ -1496,17 +1496,25 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk
 
        grctx->main(chan);
 
-       /* Trigger a context unload by unsetting the "next channel valid" bit
-        * and faking a context switch interrupt.
-        */
-       nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000);
-       nvkm_wr32(device, 0x409000, 0x00000100);
-       if (nvkm_msec(device, 2000,
-               if (!(nvkm_rd32(device, 0x409b00) & 0x80000000))
-                       break;
-       ) < 0) {
-               ret = -EBUSY;
-               goto done_inst;
+       if (!gr->firmware) {
+               /* Trigger a context unload by unsetting the "next channel valid" bit
+                * and faking a context switch interrupt.
+                */
+               nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000);
+               nvkm_wr32(device, 0x409000, 0x00000100);
+               if (nvkm_msec(device, 2000,
+                       if (!(nvkm_rd32(device, 0x409b00) & 0x80000000))
+                               break;
+               ) < 0) {
+                       ret = -EBUSY;
+                       goto done_inst;
+               }
+       } else {
+               ret = gf100_gr_fecs_wfi_golden_save(gr, 0x80000000 | addr);
+               if (ret)
+                       goto done_inst;
+
+               nvkm_mask(device, 0x409b00, 0x80000000, 0x00000000);
        }
 
        gr->data = kmalloc(gr->size, GFP_KERNEL);
index 30dce77ffa11d1593d3e0e4d9caf4c5a34cb8675..22f360df1b3a247c2151f739f59e0c88e9dd3a76 100644 (file)
@@ -796,6 +796,25 @@ gf100_gr_fecs_stop_ctxsw(struct nvkm_gr *base)
        return ret;
 }
 
+int
+gf100_gr_fecs_wfi_golden_save(struct gf100_gr *gr, u32 inst)
+{
+       struct nvkm_device *device = gr->base.engine.subdev.device;
+
+       nvkm_mask(device, 0x409800, 0x00000003, 0x00000000);
+       nvkm_wr32(device, 0x409500, inst);
+       nvkm_wr32(device, 0x409504, 0x00000009);
+       nvkm_msec(device, 2000,
+               u32 stat = nvkm_rd32(device, 0x409800);
+               if (stat & 0x00000002)
+                       return -EIO;
+               if (stat & 0x00000001)
+                       return 0;
+       );
+
+       return -ETIMEDOUT;
+}
+
 int
 gf100_gr_fecs_bind_pointer(struct gf100_gr *gr, u32 inst)
 {
index 7f467f6d0462c13088577c07e4039861d97fa0e5..66aefc972a183441e4e788c5cbe2923f28fd358b 100644 (file)
@@ -129,6 +129,7 @@ struct gf100_gr {
 };
 
 int gf100_gr_fecs_bind_pointer(struct gf100_gr *, u32 inst);
+int gf100_gr_fecs_wfi_golden_save(struct gf100_gr *, u32 inst);
 
 struct gf100_gr_func_zbc {
        void (*clear_color)(struct gf100_gr *, int zbc);