Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+58 -5
+1
drivers/gpu/drm/nouveau/include/nvif/cl906f.h
··· 11 11 }; 12 12 13 13 #define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00 14 + #define NV906F_V0_NTFY_KILLED 0x01 14 15 #endif
+1
drivers/gpu/drm/nouveau/include/nvif/cla06f.h
··· 26 26 }; 27 27 28 28 #define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00 29 + #define NVA06F_V0_NTFY_KILLED 0x01 29 30 #endif
+1
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
··· 40 40 41 41 struct nvkm_event uevent; /* async user trigger */ 42 42 struct nvkm_event cevent; /* channel creation event */ 43 + struct nvkm_event kevent; /* channel killed */ 43 44 }; 44 45 45 46 void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *);
+31 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
··· 90 90 return NULL; 91 91 } 92 92 93 + void 94 + nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid) 95 + { 96 + nvkm_event_send(&fifo->kevent, 1, chid, NULL, 0); 97 + } 98 + 99 + static int 100 + nvkm_fifo_kevent_ctor(struct nvkm_object *object, void *data, u32 size, 101 + struct nvkm_notify *notify) 102 + { 103 + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); 104 + if (size == 0) { 105 + notify->size = 0; 106 + notify->types = 1; 107 + notify->index = chan->chid; 108 + return 0; 109 + } 110 + return -ENOSYS; 111 + } 112 + 113 + static const struct nvkm_event_func 114 + nvkm_fifo_kevent_func = { 115 + .ctor = nvkm_fifo_kevent_ctor, 116 + }; 117 + 93 118 static int 94 119 nvkm_fifo_cevent_ctor(struct nvkm_object *object, void *data, u32 size, 95 120 struct nvkm_notify *notify) ··· 272 247 void *data = fifo; 273 248 if (fifo->func->dtor) 274 249 data = fifo->func->dtor(fifo); 250 + nvkm_event_fini(&fifo->kevent); 275 251 nvkm_event_fini(&fifo->cevent); 276 252 nvkm_event_fini(&fifo->uevent); 277 253 return data; ··· 315 289 return ret; 316 290 } 317 291 318 - return nvkm_event_init(&nvkm_fifo_cevent_func, 1, 1, &fifo->cevent); 292 + ret = nvkm_event_init(&nvkm_fifo_cevent_func, 1, 1, &fifo->cevent); 293 + if (ret) 294 + return ret; 295 + 296 + return nvkm_event_init(&nvkm_fifo_kevent_func, 1, nr, &fifo->kevent); 319 297 }
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
··· 29 29 struct nvkm_sclass base; 30 30 }; 31 31 32 - int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **); 32 + int gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **); 33 33 #endif
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
··· 30 30 31 31 #include <nvif/cl826e.h> 32 32 33 - int 33 + static int 34 34 g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, 35 35 struct nvkm_event **pevent) 36 36 {
+1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
··· 190 190 if (engine != &fifo->base.engine) 191 191 fifo->recover.mask |= 1ULL << engine->subdev.index; 192 192 schedule_work(&fifo->recover.work); 193 + nvkm_fifo_kevent(&fifo->base, chid); 193 194 } 194 195 195 196 static const struct nvkm_enum
+1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
··· 178 178 179 179 fifo->recover.runm |= BIT(chan->runl); 180 180 schedule_work(&fifo->recover.work); 181 + nvkm_fifo_kevent(&fifo->base, chid); 181 182 } 182 183 183 184 static const struct nvkm_enum
+18 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
··· 32 32 #include <nvif/cl906f.h> 33 33 #include <nvif/unpack.h> 34 34 35 + int 36 + gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, 37 + struct nvkm_event **pevent) 38 + { 39 + switch (type) { 40 + case NV906F_V0_NTFY_NON_STALL_INTERRUPT: 41 + *pevent = &chan->fifo->uevent; 42 + return 0; 43 + case NV906F_V0_NTFY_KILLED: 44 + *pevent = &chan->fifo->kevent; 45 + return 0; 46 + default: 47 + break; 48 + } 49 + return -EINVAL; 50 + } 51 + 35 52 static u32 36 53 gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) 37 54 { ··· 201 184 .dtor = gf100_fifo_gpfifo_dtor, 202 185 .init = gf100_fifo_gpfifo_init, 203 186 .fini = gf100_fifo_gpfifo_fini, 204 - .ntfy = g84_fifo_chan_ntfy, 187 + .ntfy = gf100_fifo_chan_ntfy, 205 188 .engine_ctor = gf100_fifo_gpfifo_engine_ctor, 206 189 .engine_dtor = gf100_fifo_gpfifo_engine_dtor, 207 190 .engine_init = gf100_fifo_gpfifo_engine_init,
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
··· 213 213 .dtor = gk104_fifo_gpfifo_dtor, 214 214 .init = gk104_fifo_gpfifo_init, 215 215 .fini = gk104_fifo_gpfifo_fini, 216 - .ntfy = g84_fifo_chan_ntfy, 216 + .ntfy = gf100_fifo_chan_ntfy, 217 217 .engine_ctor = gk104_fifo_gpfifo_engine_ctor, 218 218 .engine_dtor = gk104_fifo_gpfifo_engine_dtor, 219 219 .engine_init = gk104_fifo_gpfifo_engine_init,
+1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
··· 7 7 int index, int nr, struct nvkm_fifo *); 8 8 void nvkm_fifo_uevent(struct nvkm_fifo *); 9 9 void nvkm_fifo_cevent(struct nvkm_fifo *); 10 + void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); 10 11 11 12 struct nvkm_fifo_chan_oclass; 12 13 struct nvkm_fifo_func {