drm/nouveau/gpio: fail if gpu external power is missing
authorMark Menzynski <mmenzyns@redhat.com>
Thu, 18 Jul 2019 08:07:39 +0000 (10:07 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 23 Aug 2019 02:55:33 +0000 (12:55 +1000)
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>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c

index 3f74b2726cf2a68361e9db332804d209b46ee36a..d036cdc45201082e27b86431afff8d7544cbf3b4 100644 (file)
@@ -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,
index 1399d923d44623940c000dc0a54be40865e75624..1337a110c0e3aaa3c7ded9dc998f0d9ebf8e6c59 100644 (file)
@@ -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;
 }