Commit ff9f29ab authored by Ben Skeggs's avatar Ben Skeggs

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent 40cea739
......@@ -11,4 +11,5 @@ struct fermi_channel_gpfifo_v0 {
};
#define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00
#define NV906F_V0_NTFY_KILLED 0x01
#endif
......@@ -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
......@@ -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 *);
......
......@@ -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);
}
......@@ -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
......@@ -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)
{
......
......@@ -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
......
......@@ -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
......
......@@ -32,6 +32,23 @@
#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,
......
......@@ -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,
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment