drm/nouveau/fifo/gf100-: provide notification to user if channel is killed
authorBen Skeggs <bskeggs@redhat.com>
Sat, 5 Nov 2016 03:05:14 +0000 (13:05 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 17 Feb 2017 07:38:08 +0000 (17:38 +1000)
There are instances (such as non-recoverable GPU page faults) where
NVKM decides that a channel's context is no longer viable, and will
be removed from the runlist.

This commit notifies the owner of the channel when this happens, so
it has the opportunity to take some kind of recovery action instead
of hanging.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvif/cl906f.h
drivers/gpu/drm/nouveau/include/nvif/cla06f.h
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h

index e9302ec5cbfa609b134476dc94c786a844c7488f..a2d5410a491b8d434e3df8e65d4945f32c57e827 100644 (file)
@@ -11,4 +11,5 @@ struct fermi_channel_gpfifo_v0 {
 };
 
 #define NV906F_V0_NTFY_NON_STALL_INTERRUPT                                 0x00
+#define NV906F_V0_NTFY_KILLED                                              0x01
 #endif
index 567123a8f87437ad765db7872753ef5db4f88ba9..2efa3d048bb9da20a220df3117c68c5babb45b3f 100644 (file)
@@ -26,4 +26,5 @@ struct kepler_channel_gpfifo_a_v0 {
 };
 
 #define NVA06F_V0_NTFY_NON_STALL_INTERRUPT                                 0x00
+#define NVA06F_V0_NTFY_KILLED                                              0x01
 #endif
index ed92fec5292c5b41d7de5b2e4ed01ce0c04e2feb..24efa900d8caaea2e798ee3bbb1ff2673185a817 100644 (file)
@@ -40,6 +40,7 @@ struct nvkm_fifo {
 
        struct nvkm_event uevent; /* async user trigger */
        struct nvkm_event cevent; /* channel creation event */
+       struct nvkm_event kevent; /* channel killed */
 };
 
 void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *);
index 4a01afe917345fe77c224eadcf733c2d03aca167..3567c9920a37008d6649a9d35993272d5b55e71d 100644 (file)
@@ -90,6 +90,31 @@ nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags)
        return NULL;
 }
 
+void
+nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid)
+{
+       nvkm_event_send(&fifo->kevent, 1, chid, NULL, 0);
+}
+
+static int
+nvkm_fifo_kevent_ctor(struct nvkm_object *object, void *data, u32 size,
+                     struct nvkm_notify *notify)
+{
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+       if (size == 0) {
+               notify->size  = 0;
+               notify->types = 1;
+               notify->index = chan->chid;
+               return 0;
+       }
+       return -ENOSYS;
+}
+
+static const struct nvkm_event_func
+nvkm_fifo_kevent_func = {
+       .ctor = nvkm_fifo_kevent_ctor,
+};
+
 static int
 nvkm_fifo_cevent_ctor(struct nvkm_object *object, void *data, u32 size,
                      struct nvkm_notify *notify)
@@ -247,6 +272,7 @@ nvkm_fifo_dtor(struct nvkm_engine *engine)
        void *data = fifo;
        if (fifo->func->dtor)
                data = fifo->func->dtor(fifo);
+       nvkm_event_fini(&fifo->kevent);
        nvkm_event_fini(&fifo->cevent);
        nvkm_event_fini(&fifo->uevent);
        return data;
@@ -289,5 +315,9 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
                        return ret;
        }
 
-       return nvkm_event_init(&nvkm_fifo_cevent_func, 1, 1, &fifo->cevent);
+       ret = nvkm_event_init(&nvkm_fifo_cevent_func, 1, 1, &fifo->cevent);
+       if (ret)
+               return ret;
+
+       return nvkm_event_init(&nvkm_fifo_kevent_func, 1, nr, &fifo->kevent);
 }
index 55dc415c5c08b2373ab566b8caec1b218a2476bf..d8019bdacd61726a8f973886fd06f2133fb0628f 100644 (file)
@@ -29,5 +29,5 @@ struct nvkm_fifo_chan_oclass {
        struct nvkm_sclass base;
 };
 
-int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **);
+int gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **);
 #endif
index 66bd1cda56028370112e5719741f4b7ea0af4430..61797c4dd07a753f6c46a4c1b18df3a7cba920af 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <nvif/cl826e.h>
 
-int
+static int
 g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
                   struct nvkm_event **pevent)
 {
index 8772a995329a60f5e05be264b32dc4c39af5d11c..cd468ab1db125e213de377eac9458d6879190009 100644 (file)
@@ -190,6 +190,7 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
        if (engine != &fifo->base.engine)
                fifo->recover.mask |= 1ULL << engine->subdev.index;
        schedule_work(&fifo->recover.work);
+       nvkm_fifo_kevent(&fifo->base, chid);
 }
 
 static const struct nvkm_enum
index 73ae4ecc2e9a887c9298cf6aa818436df71010dc..67a6a514b5fa696689641fd9f56db304be84f150 100644 (file)
@@ -178,6 +178,7 @@ gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine,
 
        fifo->recover.runm |= BIT(chan->runl);
        schedule_work(&fifo->recover.work);
+       nvkm_fifo_kevent(&fifo->base, chid);
 }
 
 static const struct nvkm_enum
index 12d964260a29921ed71cb25b2a299824ac4442f2..f9e0377d3d24bbb9c3bdc3e09753fe7304b37367 100644 (file)
 #include <nvif/cl906f.h>
 #include <nvif/unpack.h>
 
+int
+gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
+                    struct nvkm_event **pevent)
+{
+       switch (type) {
+       case NV906F_V0_NTFY_NON_STALL_INTERRUPT:
+               *pevent = &chan->fifo->uevent;
+               return 0;
+       case NV906F_V0_NTFY_KILLED:
+               *pevent = &chan->fifo->kevent;
+               return 0;
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
 static u32
 gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
 {
@@ -184,7 +201,7 @@ gf100_fifo_gpfifo_func = {
        .dtor = gf100_fifo_gpfifo_dtor,
        .init = gf100_fifo_gpfifo_init,
        .fini = gf100_fifo_gpfifo_fini,
-       .ntfy = g84_fifo_chan_ntfy,
+       .ntfy = gf100_fifo_chan_ntfy,
        .engine_ctor = gf100_fifo_gpfifo_engine_ctor,
        .engine_dtor = gf100_fifo_gpfifo_engine_dtor,
        .engine_init = gf100_fifo_gpfifo_engine_init,
index a2df4f3e7763494acf93acc5a46c2f15720b19d3..7f53869101620a02d991bd862853edcffcdc41fe 100644 (file)
@@ -213,7 +213,7 @@ gk104_fifo_gpfifo_func = {
        .dtor = gk104_fifo_gpfifo_dtor,
        .init = gk104_fifo_gpfifo_init,
        .fini = gk104_fifo_gpfifo_fini,
-       .ntfy = g84_fifo_chan_ntfy,
+       .ntfy = gf100_fifo_chan_ntfy,
        .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
        .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
        .engine_init = gk104_fifo_gpfifo_engine_init,
index 9bf0251c05d023d2917991cc59c8ca885f0eccae..1fc9d8bf12f2c18362b8fe80ad108439718b7afe 100644 (file)
@@ -7,6 +7,7 @@ int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *,
                   int index, int nr, struct nvkm_fifo *);
 void nvkm_fifo_uevent(struct nvkm_fifo *);
 void nvkm_fifo_cevent(struct nvkm_fifo *);
+void nvkm_fifo_kevent(struct nvkm_fifo *, int chid);
 
 struct nvkm_fifo_chan_oclass;
 struct nvkm_fifo_func {