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 <[email protected]>
};
#define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00
+#define NV906F_V0_NTFY_KILLED 0x01
#endif
};
#define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00
+#define NVA06F_V0_NTFY_KILLED 0x01
#endif
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 *);
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)
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;
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);
}
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
#include <nvif/cl826e.h>
-int
+static int
g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
struct nvkm_event **pevent)
{
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
fifo->recover.runm |= BIT(chan->runl);
schedule_work(&fifo->recover.work);
+ nvkm_fifo_kevent(&fifo->base, chid);
}
static const struct nvkm_enum
#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)
{
.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,
.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,
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 {