Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6007dc4 authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Ben Skeggs
Browse files

drm/nouveau/devinit/gf100: make devinit on resume safer



In case of successful suspend, devinit will have to be run and this is
the behavior currently hardcoded. However, as FD bug 94725 suggests,
there might be cases where runtime suspend leaves the GPU powered, and
in such cases devinit should not be run on resume.

On GF100+ we have a reliable way to know whether we need to run devinit.
Use it instead of blindly trusting the flag set by nvkm_devinit_fini().

The code around the NvForcePost also needs to be slightly reworked in
order to keep working.

Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Suggested-by: default avatarDave Airlie <airlied@redhat.com>
Suggested-by: default avatarKarol Herbst <nouveau@karolherbst.de>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 4dc28134
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -7,6 +7,7 @@ struct nvkm_devinit {
	const struct nvkm_devinit_func *func;
	const struct nvkm_devinit_func *func;
	struct nvkm_subdev subdev;
	struct nvkm_subdev subdev;
	bool post;
	bool post;
	bool force_post;
};
};


u32 nvkm_devinit_mmio(struct nvkm_devinit *, u32 addr);
u32 nvkm_devinit_mmio(struct nvkm_devinit *, u32 addr);
+7 −1
Original line number Original line Diff line number Diff line
@@ -83,6 +83,12 @@ nvkm_devinit_preinit(struct nvkm_subdev *subdev)
	if (init->func->preinit)
	if (init->func->preinit)
		init->func->preinit(init);
		init->func->preinit(init);


	/* Override the post flag during the first call if NvForcePost is set */
	if (init->force_post) {
		init->post = init->force_post;
		init->force_post = false;
	}

	/* unlock the extended vga crtc regs */
	/* unlock the extended vga crtc regs */
	nvkm_lockvgac(subdev->device, false);
	nvkm_lockvgac(subdev->device, false);
	return 0;
	return 0;
@@ -126,5 +132,5 @@ nvkm_devinit_ctor(const struct nvkm_devinit_func *func,
{
{
	nvkm_subdev_ctor(&nvkm_devinit, device, index, 0, &init->subdev);
	nvkm_subdev_ctor(&nvkm_devinit, device, index, 0, &init->subdev);
	init->func = func;
	init->func = func;
	init->post = nvkm_boolopt(device->cfgopt, "NvForcePost", false);
	init->force_post = nvkm_boolopt(device->cfgopt, "NvForcePost", false);
}
}
+5 −3
Original line number Original line Diff line number Diff line
@@ -97,8 +97,10 @@ gf100_devinit_preinit(struct nvkm_devinit *base)
	struct nvkm_subdev *subdev = &init->base.subdev;
	struct nvkm_subdev *subdev = &init->base.subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_device *device = subdev->device;


	/* This bit is set by devinit, and flips back to 0 on suspend */
	/*
	if (!base->post)
	 * This bit is set by devinit, and flips back to 0 on suspend. We
	 * can use it as a reliable way to know whether we should run devinit.
	 */
	base->post = ((nvkm_rd32(device, 0x2240c) & BIT(1)) == 0);
	base->post = ((nvkm_rd32(device, 0x2240c) & BIT(1)) == 0);
}
}