[v4] clk: Restore BYPASS_PLL_CHECK from PLLs

Submitted by Mark Menzynski on Sept. 9, 2019, 8:47 a.m.

Details

Message ID 20190909084728.13349-1-mmenzyns@redhat.com
State New
Headers show
Series "clk: Restore BYPASS_PLL_CHECK from PLLs" ( rev: 2 ) in Nouveau

Not browsing as part of any series.

Commit Message

Mark Menzynski Sept. 9, 2019, 8:47 a.m.
I have looked at problem with Fermi GPUs where changing to higher clock
led to really bad perfomance (with GpuTest 20x worse perfomance) and later also crashes of the nouveau. It seemed
to be affected by Shader Clock in Voltage Entries in the video BIOS. Disabling
BYPASS_PLL_CHECK in CLK0_CTRL seems to completely fix the issue. I have
tried to search this BYPASS_PLL_CHECK in Nvidia traces but seemed it
wasn't used nowhere for CLK settings.

Removing this works fine, but I don't know what it's really for.
Actual bit setting this BYPASS_PLL_CHECK is on 0x10:
	lookup -ac0 0x137000 0x10
	PCLOCK.CLK0_CTRL => { BYPASS_PLL_CHECK | UNK12 = 0 }
Also, disabling this bit on other CLKs doesn't seem to break anything.

v2: add back PLL lock test
v3: add restoring original value after PLL lock test
v4: read the bit with nvkm_mask

Signed-off-by: Mark Menzynski <mmenzyns@redhat.com>
---
 drm/nouveau/nvkm/subdev/clk/gf100.c | 8 +++++---
 drm/nouveau/nvkm/subdev/clk/gk104.c | 6 ++++--
 2 files changed, 9 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/nvkm/subdev/clk/gf100.c b/drm/nouveau/nvkm/subdev/clk/gf100.c
index 7f67f9f5..510ab8ce 100644
--- a/drm/nouveau/nvkm/subdev/clk/gf100.c
+++ b/drm/nouveau/nvkm/subdev/clk/gf100.c
@@ -368,6 +368,7 @@  gf100_clk_prog_2(struct gf100_clk *clk, int idx)
 	struct gf100_clk_info *info = &clk->eng[idx];
 	struct nvkm_device *device = clk->base.subdev.device;
 	const u32 addr = 0x137000 + (idx * 0x20);
+	bool bypass_state = false;
 	if (idx <= 7) {
 		nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000000);
 		nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000000);
@@ -376,12 +377,13 @@  gf100_clk_prog_2(struct gf100_clk *clk, int idx)
 			nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000001);
 
 			/* Test PLL lock */
-			nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000000);
+			bypass_state = nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000000) & 0x00000010;
 			nvkm_msec(device, 2000,
 				if (nvkm_rd32(device, addr + 0x00) & 0x00020000)
 					break;
 			);
-			nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000010);
+			if (bypass_state)
+				nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000010);
 
 			/* Enable sync mode */
 			nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000004);
@@ -476,5 +478,5 @@  gf100_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
 		return -ENOMEM;
 	*pclk = &clk->base;
 
-	return nvkm_clk_ctor(&gf100_clk, device, index, false, &clk->base);
+	return nvkm_clk_ctor(&gf100_clk, device, index, true, &clk->base);
 }
diff --git a/drm/nouveau/nvkm/subdev/clk/gk104.c b/drm/nouveau/nvkm/subdev/clk/gk104.c
index 0b37e3da..de3e00c9 100644
--- a/drm/nouveau/nvkm/subdev/clk/gk104.c
+++ b/drm/nouveau/nvkm/subdev/clk/gk104.c
@@ -388,6 +388,7 @@  gk104_clk_prog_2(struct gk104_clk *clk, int idx)
 	struct gk104_clk_info *info = &clk->eng[idx];
 	struct nvkm_device *device = clk->base.subdev.device;
 	const u32 addr = 0x137000 + (idx * 0x20);
+	bool bypass_state = false;
 	nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000000);
 	nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000000);
 	if (info->coef) {
@@ -395,12 +396,13 @@  gk104_clk_prog_2(struct gk104_clk *clk, int idx)
 		nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000001);
 
 		/* Test PLL lock */
-		nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000000);
+		bypass_state = nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000000) & 0x00000010;
 		nvkm_msec(device, 2000,
 			if (nvkm_rd32(device, addr + 0x00) & 0x00020000)
 				break;
 		);
-		nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000010);
+		if (bypass_state)
+			nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000010);
 
 		/* Enable sync mode */
 		nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000004);