Commit 19f89279 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo/gk104: make use of topology info during fault recovery

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent af83a677
......@@ -108,37 +108,40 @@ gk104_fifo_recover_work(struct work_struct *w)
struct nvkm_device *device = fifo->base.engine.subdev.device;
struct nvkm_engine *engine;
unsigned long flags;
u32 engn, engm = 0;
u64 mask, todo;
u32 engm, runm, todo;
int engn, runl;
spin_lock_irqsave(&fifo->base.lock, flags);
mask = fifo->recover.mask;
fifo->recover.mask = 0ULL;
runm = fifo->recover.runm;
engm = fifo->recover.engm;
fifo->recover.engm = 0;
fifo->recover.runm = 0;
spin_unlock_irqrestore(&fifo->base.lock, flags);
for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
engm |= 1 << gk104_fifo_subdev_engine(engn);
nvkm_mask(device, 0x002630, engm, engm);
nvkm_mask(device, 0x002630, runm, runm);
for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
if ((engine = nvkm_device_engine(device, engn))) {
for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT(engn)) {
if ((engine = fifo->engine[engn].engine)) {
nvkm_subdev_fini(&engine->subdev, false);
WARN_ON(nvkm_subdev_init(&engine->subdev));
}
gk104_fifo_runlist_commit(fifo, gk104_fifo_subdev_engine(engn));
}
nvkm_wr32(device, 0x00262c, engm);
nvkm_mask(device, 0x002630, engm, 0x00000000);
for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl))
gk104_fifo_runlist_commit(fifo, runl);
nvkm_wr32(device, 0x00262c, runm);
nvkm_mask(device, 0x002630, runm, 0x00000000);
}
static void
gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine,
struct gk104_fifo_chan *chan)
struct gk104_fifo_chan *chan)
{
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
u32 chid = chan->base.chid;
int engn;
nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n",
nvkm_subdev_name[engine->subdev.index], chid);
......@@ -148,7 +151,14 @@ gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine,
list_del_init(&chan->head);
chan->killed = true;
fifo->recover.mask |= 1ULL << engine->subdev.index;
for (engn = 0; engn < fifo->engine_nr; engn++) {
if (fifo->engine[engn].engine == engine) {
fifo->recover.engm |= BIT(engn);
break;
}
}
fifo->recover.runm |= BIT(chan->runl);
schedule_work(&fifo->recover.work);
}
......
......@@ -11,7 +11,8 @@ struct gk104_fifo {
struct {
struct work_struct work;
u64 mask;
u32 engm;
u32 runm;
} recover;
int pbdma_nr;
......@@ -69,23 +70,4 @@ gk104_fifo_engine_subdev(int engine)
return 0;
}
}
static inline int
gk104_fifo_subdev_engine(int subdev)
{
switch (subdev) {
case NVKM_ENGINE_GR:
case NVKM_ENGINE_SW:
case NVKM_ENGINE_CE2 : return 0;
case NVKM_ENGINE_MSPDEC: return 1;
case NVKM_ENGINE_MSPPP : return 2;
case NVKM_ENGINE_MSVLD : return 3;
case NVKM_ENGINE_CE0 : return 4;
case NVKM_ENGINE_CE1 : return 5;
case NVKM_ENGINE_MSENC : return 6;
default:
WARN_ON(1);
return 0;
}
}
#endif
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