Skip to content

Commit

Permalink
drm/nouveau/pmu/gm200-: avoid touching PMU outside of DEVINIT/PREOS/ACR
Browse files Browse the repository at this point in the history
[ Upstream commit 1d2271d ]

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: Diego Viola <diego.viola@gmail.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Link: https://gitlab.freedesktop.org/drm/nouveau/-/merge_requests/10
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Ben Skeggs authored and Greg Kroah-Hartman committed Jan 27, 2022
1 parent 3642493 commit c9ec3d8
Showing 1 changed file with 21 additions and 16 deletions.
37 changes: 21 additions & 16 deletions drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,13 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
return 0;
}

static int
static void
nvkm_pmu_reset(struct nvkm_pmu *pmu)
{
struct nvkm_device *device = pmu->subdev.device;

if (!pmu->func->enabled(pmu))
return 0;

/* Inhibit interrupts, and wait for idle. */
nvkm_wr32(device, 0x10a014, 0x0000ffff);
nvkm_msec(device, 2000,
if (!nvkm_rd32(device, 0x10a04c))
break;
);
return;

/* Reset. */
if (pmu->func->reset)
Expand All @@ -112,25 +105,37 @@ nvkm_pmu_reset(struct nvkm_pmu *pmu)
if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
break;
);

return 0;
}

static int
nvkm_pmu_preinit(struct nvkm_subdev *subdev)
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
return nvkm_pmu_reset(pmu);
nvkm_pmu_reset(pmu);
return 0;
}

static int
nvkm_pmu_init(struct nvkm_subdev *subdev)
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
int ret = nvkm_pmu_reset(pmu);
if (ret == 0 && pmu->func->init)
ret = pmu->func->init(pmu);
return ret;
struct nvkm_device *device = pmu->subdev.device;

if (!pmu->func->init)
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 int
Expand Down

0 comments on commit c9ec3d8

Please sign in to comment.