[Nouveau] [PATCH] therm: debug print the FSRM config on [nvc0, nvf0) cards

Karol Herbst nouveau at karolherbst.de
Mon Dec 21 14:26:58 PST 2015


before we can let nouveau fully reclock the gpu automatically, we should have
a fail safe mechanism to prevent the card from overheating.

Starting with G84 GPUs the so called FSRM does the job and automatically
downclocks the GPU when specific temperatures thresholds are hit. Lucky for us
the needed bits are already configured through a script inside the vbios at
POST time and we only need to verify the set bits.

This Patch implements the verification steps for all [nvc0,nvf0) cards by
printing a debug message and in the case we detect a wrongly configured fsrm
we also print an error.

Sadly on nvf0 and newer cards this looks a bit different and a other patch for
cards older than nvc0 will follow the next days.

Signed-off-by: Karol Herbst <nouveau at karolherbst.de>
---
 drm/nouveau/include/nvkm/subdev/therm.h |  2 ++
 drm/nouveau/nvkm/engine/device/base.c   | 22 ++++++------
 drm/nouveau/nvkm/subdev/therm/Kbuild    |  2 ++
 drm/nouveau/nvkm/subdev/therm/base.c    |  2 ++
 drm/nouveau/nvkm/subdev/therm/gf100.c   | 64 +++++++++++++++++++++++++++++++++
 drm/nouveau/nvkm/subdev/therm/gf119.c   |  9 ++---
 drm/nouveau/nvkm/subdev/therm/gk110.c   | 44 +++++++++++++++++++++++
 drm/nouveau/nvkm/subdev/therm/gt215.c   |  2 +-
 drm/nouveau/nvkm/subdev/therm/priv.h    |  9 +++++
 9 files changed, 140 insertions(+), 16 deletions(-)
 create mode 100644 drm/nouveau/nvkm/subdev/therm/gf100.c
 create mode 100644 drm/nouveau/nvkm/subdev/therm/gk110.c

diff --git a/drm/nouveau/include/nvkm/subdev/therm.h b/drm/nouveau/include/nvkm/subdev/therm.h
index b268b96..c07abd7 100644
--- a/drm/nouveau/include/nvkm/subdev/therm.h
+++ b/drm/nouveau/include/nvkm/subdev/therm.h
@@ -94,6 +94,8 @@ int nv40_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
 int nv50_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
 int g84_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
 int gt215_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
+int gf100_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
 int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
+int gk110_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
 int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
 #endif
diff --git a/drm/nouveau/nvkm/engine/device/base.c b/drm/nouveau/nvkm/engine/device/base.c
index 7476ac2..7ec9167 100644
--- a/drm/nouveau/nvkm/engine/device/base.c
+++ b/drm/nouveau/nvkm/engine/device/base.c
@@ -1354,7 +1354,7 @@ nvc0_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = gf100_pci_new,
 	.pmu = gf100_pmu_new,
-	.therm = gt215_therm_new,
+	.therm = gf100_therm_new,
 	.timer = nv41_timer_new,
 	.volt = nv40_volt_new,
 	.ce[0] = gf100_ce_new,
@@ -1390,7 +1390,7 @@ nvc1_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
 	.pmu = gf100_pmu_new,
-	.therm = gt215_therm_new,
+	.therm = gf100_therm_new,
 	.timer = nv41_timer_new,
 	.volt = nv40_volt_new,
 	.ce[0] = gf100_ce_new,
@@ -1425,7 +1425,7 @@ nvc3_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
 	.pmu = gf100_pmu_new,
-	.therm = gt215_therm_new,
+	.therm = gf100_therm_new,
 	.timer = nv41_timer_new,
 	.volt = nv40_volt_new,
 	.ce[0] = gf100_ce_new,
@@ -1460,7 +1460,7 @@ nvc4_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = gf100_pci_new,
 	.pmu = gf100_pmu_new,
-	.therm = gt215_therm_new,
+	.therm = gf100_therm_new,
 	.timer = nv41_timer_new,
 	.volt = nv40_volt_new,
 	.ce[0] = gf100_ce_new,
@@ -1496,7 +1496,7 @@ nvc8_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = gf100_pci_new,
 	.pmu = gf100_pmu_new,
-	.therm = gt215_therm_new,
+	.therm = gf100_therm_new,
 	.timer = nv41_timer_new,
 	.volt = nv40_volt_new,
 	.ce[0] = gf100_ce_new,
@@ -1532,7 +1532,7 @@ nvce_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = gf100_pci_new,
 	.pmu = gf100_pmu_new,
-	.therm = gt215_therm_new,
+	.therm = gf100_therm_new,
 	.timer = nv41_timer_new,
 	.volt = nv40_volt_new,
 	.ce[0] = gf100_ce_new,
@@ -1568,7 +1568,7 @@ nvcf_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
 	.pmu = gf100_pmu_new,
-	.therm = gt215_therm_new,
+	.therm = gf100_therm_new,
 	.timer = nv41_timer_new,
 	.volt = nv40_volt_new,
 	.ce[0] = gf100_ce_new,
@@ -1806,7 +1806,7 @@ nvf0_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
 	.pmu = gk110_pmu_new,
-	.therm = gf119_therm_new,
+	.therm = gk110_therm_new,
 	.timer = nv41_timer_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
@@ -1842,7 +1842,7 @@ nvf1_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
 	.pmu = gk110_pmu_new,
-	.therm = gf119_therm_new,
+	.therm = gk110_therm_new,
 	.timer = nv41_timer_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
@@ -1878,7 +1878,7 @@ nv106_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
 	.pmu = gk208_pmu_new,
-	.therm = gf119_therm_new,
+	.therm = gk110_therm_new,
 	.timer = nv41_timer_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
@@ -1914,7 +1914,7 @@ nv108_chipset = {
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
 	.pmu = gk208_pmu_new,
-	.therm = gf119_therm_new,
+	.therm = gk110_therm_new,
 	.timer = nv41_timer_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
diff --git a/drm/nouveau/nvkm/subdev/therm/Kbuild b/drm/nouveau/nvkm/subdev/therm/Kbuild
index 135758b..fc0be52 100644
--- a/drm/nouveau/nvkm/subdev/therm/Kbuild
+++ b/drm/nouveau/nvkm/subdev/therm/Kbuild
@@ -9,5 +9,7 @@ nvkm-y += nvkm/subdev/therm/nv40.o
 nvkm-y += nvkm/subdev/therm/nv50.o
 nvkm-y += nvkm/subdev/therm/g84.o
 nvkm-y += nvkm/subdev/therm/gt215.o
+nvkm-y += nvkm/subdev/therm/gf100.o
 nvkm-y += nvkm/subdev/therm/gf119.o
+nvkm-y += nvkm/subdev/therm/gk110.o
 nvkm-y += nvkm/subdev/therm/gm107.o
diff --git a/drm/nouveau/nvkm/subdev/therm/base.c b/drm/nouveau/nvkm/subdev/therm/base.c
index 949dc61..57b2e5e 100644
--- a/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drm/nouveau/nvkm/subdev/therm/base.c
@@ -337,6 +337,8 @@ nvkm_therm_init(struct nvkm_subdev *subdev)
 
 	nvkm_therm_sensor_init(therm);
 	nvkm_therm_fan_init(therm);
+	if (therm->func->fsrm_verify)
+		therm->func->fsrm_verify(therm);
 	return 0;
 }
 
diff --git a/drm/nouveau/nvkm/subdev/therm/gf100.c b/drm/nouveau/nvkm/subdev/therm/gf100.c
new file mode 100644
index 0000000..85bb933
--- /dev/null
+++ b/drm/nouveau/nvkm/subdev/therm/gf100.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 The Nouveau community
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Karol Herbst
+ */
+#include "priv.h"
+
+void
+gf100_print_fsrm_config(struct nvkm_therm *therm)
+{
+	struct nvkm_device *device = therm->subdev.device;
+	int cfg_5, cfg_low, thr_2, thr_6, thr_8, thr_crit;
+
+	cfg_5    = nvkm_rd32(device, 0x020074);
+	cfg_low  = nvkm_rd32(device, 0x02010c);
+	thr_crit = nvkm_rd32(device, 0x020480);
+	thr_2    = nvkm_rd32(device, 0x0204c0);
+	thr_6    = nvkm_rd32(device, 0x0204d8);
+	thr_8    = nvkm_rd32(device, 0x0204e0);
+
+	nvkm_debug(&therm->subdev, "FSRM config: %i/%i/%i/%i => %x/%x/%x/off\n",
+		thr_8, thr_6, thr_2, thr_crit, (cfg_low & 0x38) >> 3, cfg_low & 0x7, 0x8 + (cfg_5 & 0x70 >> 4));
+	if (thr_crit < 90 || thr_crit > 115)
+		nvkm_error(&therm->subdev, "invalid value for crit threshold: %i\n", thr_crit);
+}
+
+static const struct nvkm_therm_func
+gf100_therm = {
+	.init = gt215_therm_init,
+	.fini = g84_therm_fini,
+	.pwm_ctrl = nv50_fan_pwm_ctrl,
+	.pwm_get = nv50_fan_pwm_get,
+	.pwm_set = nv50_fan_pwm_set,
+	.pwm_clock = nv50_fan_pwm_clock,
+	.temp_get = g84_temp_get,
+	.fan_sense = gt215_therm_fan_sense,
+	.program_alarms = nvkm_therm_program_alarms_polling,
+	.fsrm_verify = gf100_print_fsrm_config,
+};
+
+int
+gf100_therm_new(struct nvkm_device *device, int index,
+	       struct nvkm_therm **ptherm)
+{
+	return nvkm_therm_new_(&gf100_therm, device, index, ptherm);
+}
diff --git a/drm/nouveau/nvkm/subdev/therm/gf119.c b/drm/nouveau/nvkm/subdev/therm/gf119.c
index 06dcfd6..7c4e456 100644
--- a/drm/nouveau/nvkm/subdev/therm/gf119.c
+++ b/drm/nouveau/nvkm/subdev/therm/gf119.c
@@ -49,7 +49,7 @@ pwm_info(struct nvkm_therm *therm, int line)
 	return -ENODEV;
 }
 
-static int
+int
 gf119_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
 {
 	struct nvkm_device *device = therm->subdev.device;
@@ -63,7 +63,7 @@ gf119_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
 	return 0;
 }
 
-static int
+int
 gf119_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
 {
 	struct nvkm_device *device = therm->subdev.device;
@@ -85,7 +85,7 @@ gf119_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
 	return -EINVAL;
 }
 
-static int
+int
 gf119_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
 {
 	struct nvkm_device *device = therm->subdev.device;
@@ -102,7 +102,7 @@ gf119_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
 	return 0;
 }
 
-static int
+int
 gf119_fan_pwm_clock(struct nvkm_therm *therm, int line)
 {
 	struct nvkm_device *device = therm->subdev.device;
@@ -143,6 +143,7 @@ gf119_therm = {
 	.temp_get = g84_temp_get,
 	.fan_sense = gt215_therm_fan_sense,
 	.program_alarms = nvkm_therm_program_alarms_polling,
+	.fsrm_verify = gf100_print_fsrm_config,
 };
 
 int
diff --git a/drm/nouveau/nvkm/subdev/therm/gk110.c b/drm/nouveau/nvkm/subdev/therm/gk110.c
new file mode 100644
index 0000000..b799003
--- /dev/null
+++ b/drm/nouveau/nvkm/subdev/therm/gk110.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 The Nouveau community
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Karol Herbst
+ */
+#include "priv.h"
+
+static const struct nvkm_therm_func
+gk110_therm = {
+	.init = gf119_therm_init,
+	.fini = g84_therm_fini,
+	.pwm_ctrl = gf119_fan_pwm_ctrl,
+	.pwm_get = gf119_fan_pwm_get,
+	.pwm_set = gf119_fan_pwm_set,
+	.pwm_clock = gf119_fan_pwm_clock,
+	.temp_get = g84_temp_get,
+	.fan_sense = gt215_therm_fan_sense,
+	.program_alarms = nvkm_therm_program_alarms_polling,
+};
+
+int
+gk110_therm_new(struct nvkm_device *device, int index,
+	       struct nvkm_therm **ptherm)
+{
+	return nvkm_therm_new_(&gk110_therm, device, index, ptherm);
+}
diff --git a/drm/nouveau/nvkm/subdev/therm/gt215.c b/drm/nouveau/nvkm/subdev/therm/gt215.c
index c08097f..4caf401 100644
--- a/drm/nouveau/nvkm/subdev/therm/gt215.c
+++ b/drm/nouveau/nvkm/subdev/therm/gt215.c
@@ -36,7 +36,7 @@ gt215_therm_fan_sense(struct nvkm_therm *therm)
 	return -ENODEV;
 }
 
-static void
+void
 gt215_therm_init(struct nvkm_therm *therm)
 {
 	struct nvkm_device *device = therm->subdev.device;
diff --git a/drm/nouveau/nvkm/subdev/therm/priv.h b/drm/nouveau/nvkm/subdev/therm/priv.h
index 235a5d8..8564bb0 100644
--- a/drm/nouveau/nvkm/subdev/therm/priv.h
+++ b/drm/nouveau/nvkm/subdev/therm/priv.h
@@ -96,6 +96,8 @@ struct nvkm_therm_func {
 	int (*fan_sense)(struct nvkm_therm *);
 
 	void (*program_alarms)(struct nvkm_therm *);
+
+	void (*fsrm_verify)(struct nvkm_therm *);
 };
 
 void nv40_therm_intr(struct nvkm_therm *);
@@ -109,9 +111,16 @@ int  g84_temp_get(struct nvkm_therm *);
 void g84_sensor_setup(struct nvkm_therm *);
 void g84_therm_fini(struct nvkm_therm *);
 
+void gt215_therm_init(struct nvkm_therm *);
 int gt215_therm_fan_sense(struct nvkm_therm *);
 
+void gf100_print_fsrm_config(struct nvkm_therm *);
+
 void gf119_therm_init(struct nvkm_therm *);
+int gf119_fan_pwm_ctrl(struct nvkm_therm *, int line, bool enable);
+int gf119_fan_pwm_get(struct nvkm_therm *, int line, u32 *divs, u32 *duty);
+int gf119_fan_pwm_set(struct nvkm_therm *, int line, u32 divs, u32 duty);
+int gf119_fan_pwm_clock(struct nvkm_therm *, int line);
 
 int nvkm_fanpwm_create(struct nvkm_therm *, struct dcb_gpio_func *);
 int nvkm_fantog_create(struct nvkm_therm *, struct dcb_gpio_func *);
-- 
2.6.4



More information about the Nouveau mailing list