[v3,2/4] gpio: fail if gpu external power is missing

Submitted by Mark Menzynski on July 18, 2019, 8:07 a.m.

Details

Message ID 20190718080741.3147-3-mmenzyns@redhat.com
State New
Headers show
Series "Refuse to load if power cable are not connected" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Mark Menzynski July 18, 2019, 8:07 a.m.
Currently, nouveau doesn't check if GPU is missing power. This
patch makes nouveau fail when this happens on latest GPUs.

It checks GPIO function 121 (External Power Emergency), which
should detect power problems on GPU initialization.

This can be disabled with nouveau.config=NvPowerChecks=1

Tested on TU104, GP106 and GF100.

v3:
*  Add config override for disabling power checks

Signed-off-by: Mark Menzynski <mmenzyns@redhat.com>
---
 drm/nouveau/include/nvkm/subdev/bios/gpio.h |  1 +
 drm/nouveau/nvkm/subdev/gpio/base.c         | 30 +++++++++++++++++++++
 2 files changed, 31 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drm/nouveau/include/nvkm/subdev/bios/gpio.h
index 2f40935f..a70ec9e8 100644
--- a/drm/nouveau/include/nvkm/subdev/bios/gpio.h
+++ b/drm/nouveau/include/nvkm/subdev/bios/gpio.h
@@ -7,6 +7,7 @@  enum dcb_gpio_func_name {
 	DCB_GPIO_TVDAC0 = 0x0c,
 	DCB_GPIO_TVDAC1 = 0x2d,
 	DCB_GPIO_FAN_SENSE = 0x3d,
+	DCB_GPIO_EXT_POWER_LOW = 0x79,
 	DCB_GPIO_LOGO_LED_PWM = 0x84,
 	DCB_GPIO_UNUSED = 0xff,
 	DCB_GPIO_VID0 = 0x04,
diff --git a/drm/nouveau/nvkm/subdev/gpio/base.c b/drm/nouveau/nvkm/subdev/gpio/base.c
index 1399d923..72289e2e 100644
--- a/drm/nouveau/nvkm/subdev/gpio/base.c
+++ b/drm/nouveau/nvkm/subdev/gpio/base.c
@@ -23,6 +23,7 @@ 
  */
 #include "priv.h"
 
+#include <core/option.h>
 #include <core/notify.h>
 
 static int
@@ -182,12 +183,41 @@  static const struct dmi_system_id gpio_reset_ids[] = {
 	{ }
 };
 
+static enum dcb_gpio_func_name power_checks[] = {
+	DCB_GPIO_EXT_POWER_LOW,
+};
+
 static int
 nvkm_gpio_init(struct nvkm_subdev *subdev)
 {
 	struct nvkm_gpio *gpio = nvkm_gpio(subdev);
+	struct dcb_gpio_func func;
+	int ret;
+	int i;
+
 	if (dmi_check_system(gpio_reset_ids))
 		nvkm_gpio_reset(gpio, DCB_GPIO_UNUSED);
+
+	if (nvkm_boolopt(subdev->device->cfgopt, "NvPowerChecks", true))
+	{
+		for (i = 0; i < ARRAY_SIZE(power_checks); ++i)
+		{
+			ret = nvkm_gpio_find(gpio, 0, power_checks[i],
+					     DCB_GPIO_UNUSED, &func);
+			if (ret)
+				continue;
+
+			ret = nvkm_gpio_get(gpio, 0, func.func, func.line);
+			if (!ret)
+				continue;
+
+			nvkm_error(&gpio->subdev,
+				   "GPU is missing power, check its power cables. "
+				   "Boot with nouveau.config=NvPowerChecks=0 to disable.\n");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }