From ff9f29abf0ef4c43e696bef7621884518e6bdbda Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 5 Nov 2016 13:05:14 +1000 Subject: [PATCH] drm/nouveau/fifo/gf100-: provide notification to user if channel is killed 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 --- drivers/gpu/drm/nouveau/include/nvif/cl906f.h | 1 + drivers/gpu/drm/nouveau/include/nvif/cla06f.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 32 +++++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 1 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 19 ++++++++++++- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 1 + 11 files changed, 58 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h index e9302ec..a2d5410 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h @@ -11,4 +11,5 @@ struct fermi_channel_gpfifo_v0 { }; #define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00 +#define NV906F_V0_NTFY_KILLED 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h index 567123a..2efa3d0 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index ed92fec..24efa90 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -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 *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 4a01afe..3567c99 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 55dc415..d8019bd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 66bd1cd..61797c4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -30,7 +30,7 @@ #include -int +static int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, struct nvkm_event **pevent) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 8772a99..cd468ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 73ae4ec..67a6a51 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 12d96426..f9e0377 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -32,6 +32,23 @@ #include #include +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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index a2df4f3..7f53869 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 9bf0251..1fc9d8b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -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 { -- 2.7.4