Commit c21b0397 authored by Ben Skeggs's avatar Ben Skeggs Committed by Dave Airlie
Browse files

drm/nouveau/gsp: add hals for fbsr.suspend/resume()



555.42.02 has incompatible changes to FBSR.

At the same time, move the calling of FBSR functions from the instmem
subdev's suspend/resume paths, to GSP's.  This is needed to fix ordering
issues that arise from changes to FBSR in newer RM versions.

Signed-off-by: default avatarBen Skeggs <bskeggs@nvidia.com>
Reviewed-by: default avatarDave Airlie <airlied@redhat.com>
Reviewed-by: default avatarTimur Tabi <ttabi@nvidia.com>
Tested-by: default avatarTimur Tabi <ttabi@nvidia.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 207c445b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ struct nvkm_gsp {
		struct sg_table sgt;
		struct nvkm_gsp_radix3 radix3;
		struct nvkm_gsp_mem meta;
		struct sg_table fbsr;
	} sr;

	struct {
+0 −5
Original line number Diff line number Diff line
@@ -24,11 +24,6 @@ struct nvkm_instmem {
	struct nvkm_ramht  *ramht;
	struct nvkm_memory *ramro;
	struct nvkm_memory *ramfc;

	struct {
		struct sg_table fbsr;
		bool fbsr_valid;
	} rm;
};

u32 nvkm_instmem_rd32(struct nvkm_instmem *, u32 addr);
+14 −15
Original line number Diff line number Diff line
@@ -201,21 +201,18 @@ fbsr_inst(struct fbsr *fbsr, const char *type, struct nvkm_memory *memory)
}

static void
r535_instmem_resume(struct nvkm_instmem *imem)
r535_fbsr_resume(struct nvkm_gsp *gsp)
{
	/* RM has restored VRAM contents already, so just need to free the sysmem buffer. */
	if (imem->rm.fbsr_valid) {
		nvkm_gsp_sg_free(imem->subdev.device, &imem->rm.fbsr);
		imem->rm.fbsr_valid = false;
	}
	nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.fbsr);
}

static int
r535_instmem_suspend(struct nvkm_instmem *imem)
r535_fbsr_suspend(struct nvkm_gsp *gsp)
{
	struct nvkm_subdev *subdev = &imem->subdev;
	struct nvkm_subdev *subdev = &gsp->subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_gsp *gsp = device->gsp;
	struct nvkm_instmem *imem = device->imem;
	struct nvkm_instobj *iobj;
	struct fbsr fbsr = {};
	struct fbsr_item *item, *temp;
@@ -256,7 +253,7 @@ r535_instmem_suspend(struct nvkm_instmem *imem)
	fbsr.size += gsp->fb.bios.vga_workspace.size;
	nvkm_debug(subdev, "fbsr: size: 0x%llx bytes\n", fbsr.size);

	ret = nvkm_gsp_sg(gsp->subdev.device, fbsr.size, &imem->rm.fbsr);
	ret = nvkm_gsp_sg(gsp->subdev.device, fbsr.size, &gsp->sr.fbsr);
	if (ret)
		goto done;

@@ -265,7 +262,7 @@ r535_instmem_suspend(struct nvkm_instmem *imem)
	if (ret)
		goto done_sgt;

	ret = fbsr_init(&fbsr, &imem->rm.fbsr, items_size);
	ret = fbsr_init(&fbsr, &gsp->sr.fbsr, items_size);
	if (WARN_ON(ret))
		goto done_sgt;

@@ -276,12 +273,10 @@ r535_instmem_suspend(struct nvkm_instmem *imem)
			goto done_sgt;
	}

	imem->rm.fbsr_valid = true;

	/* Cleanup everything except the sysmem backup, which will be removed after resume. */
done_sgt:
	if (ret) /* ... unless we failed already. */
		nvkm_gsp_sg_free(device, &imem->rm.fbsr);
		nvkm_gsp_sg_free(device, &gsp->sr.fbsr);
done:
	list_for_each_entry_safe(item, temp, &fbsr.items, head) {
		list_del(&item->head);
@@ -293,6 +288,12 @@ r535_instmem_suspend(struct nvkm_instmem *imem)
	return ret;
}

const struct nvkm_rm_api_fbsr
r535_fbsr = {
	.suspend = r535_fbsr_suspend,
	.resume = r535_fbsr_resume,
};

static void *
r535_instmem_dtor(struct nvkm_instmem *imem)
{
@@ -313,8 +314,6 @@ r535_instmem_new(const struct nvkm_instmem_func *hw,

	rm->dtor = r535_instmem_dtor;
	rm->fini = hw->fini;
	rm->suspend = r535_instmem_suspend;
	rm->resume  = r535_instmem_resume;
	rm->memory_new = hw->memory_new;
	rm->memory_wrap = hw->memory_wrap;
	rm->zero = false;
+11 −0
Original line number Diff line number Diff line
@@ -1730,6 +1730,7 @@ nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
int
r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
{
	struct nvkm_rm *rm = gsp->rm;
	int ret;

	if (suspend) {
@@ -1754,6 +1755,14 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
		sr->revision = GSP_FW_SR_META_REVISION;
		sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
		sr->sizeOfSuspendResumeData = len;

		ret = rm->api->fbsr->suspend(gsp);
		if (ret) {
			nvkm_gsp_mem_dtor(&gsp->sr.meta);
			nvkm_gsp_radix3_dtor(gsp, &gsp->sr.radix3);
			nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt);
			return ret;
		}
	}

	ret = r535_gsp_rpc_unloading_guest_driver(gsp, suspend);
@@ -1787,6 +1796,8 @@ r535_gsp_init(struct nvkm_gsp *gsp)

done:
	if (gsp->sr.meta.data) {
		gsp->rm->api->fbsr->resume(gsp);

		nvkm_gsp_mem_dtor(&gsp->sr.meta);
		nvkm_gsp_radix3_dtor(gsp, &gsp->sr.radix3);
		nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt);
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ r535_api = {
	.alloc = &r535_alloc,
	.client = &r535_client,
	.device = &r535_device,
	.fbsr = &r535_fbsr,
	.disp = &r535_disp,
	.fifo = &r535_fifo,
	.ce = &r535_ce,
Loading