Commit ca081fff authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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
Loading
Loading
Loading
Loading
+14 −31
Original line number Diff line number Diff line
@@ -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;
}

+1 −1
Original line number Diff line number Diff line
@@ -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 *);
+11 −17
Original line number Diff line number Diff line
@@ -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;
}