Commit 1d2271d2 authored by Ben Skeggs's avatar Ben Skeggs Committed by Karol Herbst

drm/nouveau/pmu/gm200-: avoid touching PMU outside of DEVINIT/PREOS/ACR

There have been reports of the WFI timing out on some boards, and a
patch was proposed to just remove it.  This stuff is rather fragile,
and I believe the WFI might be needed with our FW prior to GM200.

However, we probably should not be touching PMU during init on GPUs
where we depend on NVIDIA FW, outside of limited circumstances, so
this should be a somewhat safer change that achieves the desired
result.
Reported-by: default avatarDiego Viola <diego.viola@gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarKarol Herbst <kherbst@redhat.com>
Signed-off-by: default avatarKarol Herbst <kherbst@redhat.com>
Link: https://gitlab.freedesktop.org/drm/nouveau/-/merge_requests/10
parent 6040308f
...@@ -94,20 +94,13 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) ...@@ -94,20 +94,13 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
return 0; return 0;
} }
static int static void
nvkm_pmu_reset(struct nvkm_pmu *pmu) nvkm_pmu_reset(struct nvkm_pmu *pmu)
{ {
struct nvkm_device *device = pmu->subdev.device; struct nvkm_device *device = pmu->subdev.device;
if (!pmu->func->enabled(pmu)) if (!pmu->func->enabled(pmu))
return 0; return;
/* Inhibit interrupts, and wait for idle. */
nvkm_wr32(device, 0x10a014, 0x0000ffff);
nvkm_msec(device, 2000,
if (!nvkm_rd32(device, 0x10a04c))
break;
);
/* Reset. */ /* Reset. */
if (pmu->func->reset) if (pmu->func->reset)
...@@ -118,25 +111,37 @@ nvkm_pmu_reset(struct nvkm_pmu *pmu) ...@@ -118,25 +111,37 @@ nvkm_pmu_reset(struct nvkm_pmu *pmu)
if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006)) if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
break; break;
); );
return 0;
} }
static int static int
nvkm_pmu_preinit(struct nvkm_subdev *subdev) nvkm_pmu_preinit(struct nvkm_subdev *subdev)
{ {
struct nvkm_pmu *pmu = nvkm_pmu(subdev); struct nvkm_pmu *pmu = nvkm_pmu(subdev);
return nvkm_pmu_reset(pmu); nvkm_pmu_reset(pmu);
return 0;
} }
static int static int
nvkm_pmu_init(struct nvkm_subdev *subdev) nvkm_pmu_init(struct nvkm_subdev *subdev)
{ {
struct nvkm_pmu *pmu = nvkm_pmu(subdev); struct nvkm_pmu *pmu = nvkm_pmu(subdev);
int ret = nvkm_pmu_reset(pmu); struct nvkm_device *device = pmu->subdev.device;
if (ret == 0 && pmu->func->init)
ret = pmu->func->init(pmu); if (!pmu->func->init)
return ret; return 0;
if (pmu->func->enabled(pmu)) {
/* Inhibit interrupts, and wait for idle. */
nvkm_wr32(device, 0x10a014, 0x0000ffff);
nvkm_msec(device, 2000,
if (!nvkm_rd32(device, 0x10a04c))
break;
);
nvkm_pmu_reset(pmu);
}
return pmu->func->init(pmu);
} }
static void * static void *
......
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