Commit ca081fff authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/gr/gf100-: generate golden context during first object alloc

Needed for GV100 (and only GV100 for some reason) for WFI_GOLDEN_SAVE.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 11375021
......@@ -26,6 +26,7 @@
#include <subdev/fb.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <engine/fifo.h>
/*******************************************************************************
* PGRAPH context register lists
......@@ -1433,14 +1434,12 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
#define CB_RESERVED 0x80000
int
gf100_grctx_generate(struct gf100_gr *gr)
gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvkm_gpuobj *inst)
{
const struct gf100_grctx_func *grctx = gr->func->grctx;
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_memory *inst = NULL;
struct nvkm_memory *data = NULL;
struct nvkm_vmm *vmm = NULL;
struct nvkm_vma *ctx = NULL;
struct gf100_grctx info;
int ret, i;
......@@ -1472,38 +1471,20 @@ gf100_grctx_generate(struct gf100_gr *gr)
/* Init SCC RAM. */
nvkm_wr32(device, 0x40802c, 0x00000001);
/* Allocate memory to for a "channel", which we'll use to generate
* the default context values.
*/
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
0x1000, 0x1000, true, &inst);
if (ret)
goto done;
ret = nvkm_vmm_new(device, 0, 0, NULL, 0, NULL, "grctx", &vmm);
if (ret)
goto done;
vmm->debug = subdev->debug;
ret = nvkm_vmm_join(vmm, inst);
if (ret)
goto done;
/* Allocate memory to store context, and dummy global context buffers. */
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
CB_RESERVED + gr->size, 0, true, &data);
if (ret)
goto done;
ret = nvkm_vmm_get(vmm, 0, nvkm_memory_size(data), &ctx);
ret = nvkm_vmm_get(chan->vmm, 0, nvkm_memory_size(data), &ctx);
if (ret)
goto done;
ret = nvkm_memory_map(data, 0, vmm, ctx, NULL, 0);
ret = nvkm_memory_map(data, 0, chan->vmm, ctx, NULL, 0);
if (ret)
goto done;
/* Setup context pointer. */
nvkm_kmap(inst);
nvkm_wo32(inst, 0x0210, lower_32_bits(ctx->addr + CB_RESERVED) | 4);
......@@ -1518,11 +1499,11 @@ gf100_grctx_generate(struct gf100_gr *gr)
info.buffer_nr = 0;
/* Make channel current. */
addr = nvkm_memory_addr(inst) >> 12;
addr = inst->addr >> 12;
if (gr->firmware) {
ret = gf100_gr_fecs_bind_pointer(gr, 0x80000000 | addr);
if (ret)
goto done;
goto done_inst;
nvkm_kmap(data);
nvkm_wo32(data, 0x1c, 1);
......@@ -1552,7 +1533,7 @@ gf100_grctx_generate(struct gf100_gr *gr)
break;
) < 0) {
ret = -EBUSY;
goto done;
goto done_inst;
}
gr->data = kmalloc(gr->size, GFP_KERNEL);
......@@ -1566,12 +1547,14 @@ gf100_grctx_generate(struct gf100_gr *gr)
ret = -ENOMEM;
}
done_inst:
nvkm_kmap(inst);
nvkm_wo32(inst, 0x0210, 0);
nvkm_wo32(inst, 0x0214, 0);
nvkm_done(inst);
done:
nvkm_vmm_put(vmm, &ctx);
nvkm_vmm_put(chan->vmm, &ctx);
nvkm_memory_unref(&data);
nvkm_vmm_part(vmm, inst);
nvkm_vmm_unref(&vmm);
nvkm_memory_unref(&inst);
return ret;
}
......
......@@ -81,7 +81,7 @@ struct gf100_grctx_func {
};
extern const struct gf100_grctx_func gf100_grctx;
int gf100_grctx_generate(struct gf100_gr *);
int gf100_grctx_generate(struct gf100_gr *, struct gf100_gr_chan *, struct nvkm_gpuobj *inst);
void gf100_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *);
void gf100_grctx_generate_bundle(struct gf100_grctx *);
void gf100_grctx_generate_pagepool(struct gf100_grctx *);
......
......@@ -394,6 +394,17 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
chan->vmm = nvkm_vmm_ref(fifoch->vmm);
*pobject = &chan->object;
/* Generate golden context image. */
mutex_lock(&gr->fecs.mutex);
if (gr->data == NULL) {
ret = gf100_grctx_generate(gr, chan, fifoch->inst);
if (ret) {
nvkm_error(&base->engine.subdev, "failed to construct context\n");
return ret;
}
}
mutex_unlock(&gr->fecs.mutex);
/* allocate memory for a "mmio list" buffer that's used by the HUB
* fuc to modify some per-context register settings on first load
* of the context.
......@@ -1763,15 +1774,6 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
return ret;
}
/* Generate golden context image. */
if (gr->data == NULL) {
int ret = gf100_grctx_generate(gr);
if (ret) {
nvkm_error(subdev, "failed to construct context\n");
return ret;
}
}
return 0;
}
......@@ -1823,14 +1825,6 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr)
}
gr->size = nvkm_rd32(device, 0x409804);
if (gr->data == NULL) {
int ret = gf100_grctx_generate(gr);
if (ret) {
nvkm_error(subdev, "failed to construct context\n");
return ret;
}
}
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment