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 <bskeggs@redhat.com>
This commit is contained in:
parent
40cea73984
commit
ff9f29abf0
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue