drm/nouveau/ce/gk104: attempt at better handling of LAUNCHERR
authorBen Skeggs <bskeggs@redhat.com>
Wed, 11 Nov 2015 03:06:10 +0000 (13:06 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 11 Jan 2016 01:17:40 +0000 (11:17 +1000)
Very rough, no idea how correct it is at this point, but it prevents
getteximage-depth from piglit from hanging the GPU.

v2: updated with NV_PCE_FE_LAUNCHERR_REPORT values provided by NVIDIA

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c

index c541a1c..e2b944d 100644 (file)
  * Authors: Ben Skeggs
  */
 #include "priv.h"
+#include <core/enum.h>
 
 #include <nvif/class.h>
 
+static const struct nvkm_enum
+gk104_ce_launcherr_report[] = {
+       { 0x0, "NO_ERR" },
+       { 0x1, "2D_LAYER_EXCEEDS_DEPTH" },
+       { 0x2, "INVALID_ARGUMENT" },
+       { 0x3, "MEM2MEM_RECT_OUT_OF_BOUNDS" },
+       { 0x4, "SRC_LINE_EXCEEDS_PITCH" },
+       { 0x5, "SRC_LINE_EXCEEDS_NEG_PITCH" },
+       { 0x6, "DST_LINE_EXCEEDS_PITCH" },
+       { 0x7, "DST_LINE_EXCEEDS_NEG_PITCH" },
+       { 0x8, "BAD_SRC_PIXEL_COMP_REF" },
+       { 0x9, "INVALID_VALUE" },
+       { 0xa, "UNUSED_FIELD" },
+       { 0xb, "INVALID_OPERATION" },
+       {}
+};
+
+static void
+gk104_ce_intr_launcherr(struct nvkm_engine *ce, const u32 base)
+{
+       struct nvkm_subdev *subdev = &ce->subdev;
+       struct nvkm_device *device = subdev->device;
+       u32 stat = nvkm_rd32(device, 0x104f14 + base);
+       const struct nvkm_enum *en =
+               nvkm_enum_find(gk104_ce_launcherr_report, stat & 0x0000000f);
+       nvkm_warn(subdev, "LAUNCHERR %08x [%s]\n", stat, en ? en->name : "");
+       nvkm_wr32(device, 0x104f14 + base, 0x00000000);
+}
+
 void
 gk104_ce_intr(struct nvkm_engine *ce)
 {
        const u32 base = (ce->subdev.index - NVKM_ENGINE_CE0) * 0x1000;
        struct nvkm_subdev *subdev = &ce->subdev;
        struct nvkm_device *device = subdev->device;
-       u32 stat = nvkm_rd32(device, 0x104908 + base);
-       if (stat) {
-               nvkm_warn(subdev, "intr %08x\n", stat);
-               nvkm_wr32(device, 0x104908 + base, stat);
+       u32 mask = nvkm_rd32(device, 0x104904 + base);
+       u32 intr = nvkm_rd32(device, 0x104908 + base) & mask;
+       if (intr & 0x00000001) {
+               nvkm_warn(subdev, "BLOCKPIPE\n");
+               nvkm_wr32(device, 0x104908 + base, 0x00000001);
+               intr &= ~0x00000001;
+       }
+       if (intr & 0x00000002) {
+               nvkm_warn(subdev, "NONBLOCKPIPE\n");
+               nvkm_wr32(device, 0x104908 + base, 0x00000002);
+               intr &= ~0x00000002;
+       }
+       if (intr & 0x00000004) {
+               gk104_ce_intr_launcherr(ce, base);
+               nvkm_wr32(device, 0x104908 + base, 0x00000004);
+               intr &= ~0x00000004;
+       }
+       if (intr) {
+               nvkm_warn(subdev, "intr %08x\n", intr);
+               nvkm_wr32(device, 0x104908 + base, intr);
        }
 }