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);
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)
{
};
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);