From 4e1bfac95054eb3944424243b46967e56c6a683c Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 1 Apr 2016 15:26:23 +0900 Subject: [PATCH] devinit/gf100: make devinit on resume safer X-NVConfidentiality: public 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: Alexandre Courbot Suggested-by: Dave Airlie Suggested-by: Karol Herbst --- drm/nouveau/include/nvkm/subdev/devinit.h | 1 + drm/nouveau/nvkm/subdev/devinit/base.c | 8 +++++++- drm/nouveau/nvkm/subdev/devinit/gf100.c | 8 +++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/devinit.h b/drm/nouveau/include/nvkm/subdev/devinit.h index 193626c69517..709d786f1808 100644 --- a/drm/nouveau/include/nvkm/subdev/devinit.h +++ b/drm/nouveau/include/nvkm/subdev/devinit.h @@ -7,6 +7,7 @@ struct nvkm_devinit { const struct nvkm_devinit_func *func; struct nvkm_subdev subdev; bool post; + bool force_post; }; u32 nvkm_devinit_mmio(struct nvkm_devinit *, u32 addr); diff --git a/drm/nouveau/nvkm/subdev/devinit/base.c b/drm/nouveau/nvkm/subdev/devinit/base.c index 5f25402f6b09..9edd53773a19 100644 --- a/drm/nouveau/nvkm/subdev/devinit/base.c +++ b/drm/nouveau/nvkm/subdev/devinit/base.c @@ -83,6 +83,12 @@ nvkm_devinit_preinit(struct nvkm_subdev *subdev) if (init->func->preinit) 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 */ nvkm_lockvgac(subdev->device, false); 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); init->func = func; - init->post = nvkm_boolopt(device->cfgopt, "NvForcePost", false); + init->force_post = nvkm_boolopt(device->cfgopt, "NvForcePost", false); } diff --git a/drm/nouveau/nvkm/subdev/devinit/gf100.c b/drm/nouveau/nvkm/subdev/devinit/gf100.c index 2923598b5fe9..8b1b34c3ad26 100644 --- a/drm/nouveau/nvkm/subdev/devinit/gf100.c +++ b/drm/nouveau/nvkm/subdev/devinit/gf100.c @@ -97,9 +97,11 @@ gf100_devinit_preinit(struct nvkm_devinit *base) struct nvkm_subdev *subdev = &init->base.subdev; struct nvkm_device *device = subdev->device; - /* This bit is set by devinit, and flips back to 0 on suspend */ - if (!base->post) - base->post = ((nvkm_rd32(device, 0x2240c) & BIT(1)) == 0); + /* + * 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); } static const struct nvkm_devinit_func -- 2.7.3