summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2016-03-11 13:09:28 +1000
committerBen Skeggs <bskeggs@redhat.com>2016-03-11 13:09:28 +1000
commit1548b696817ad032015182d425346bb0cf95cd0e (patch)
tree499a5e78be17ce823358f9e87d58850131047398
parent8171370a33774aeebf20d561740c91e057cfbb4e (diff)
downloadnouveau-1548b696817ad032015182d425346bb0cf95cd0e.tar.gz
fifo/gk104: make use of topology info during fault recovery
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drm/nouveau/nvkm/engine/fifo/gk104.c38
-rw-r--r--drm/nouveau/nvkm/engine/fifo/gk104.h22
2 files changed, 26 insertions, 34 deletions
diff --git a/drm/nouveau/nvkm/engine/fifo/gk104.c b/drm/nouveau/nvkm/engine/fifo/gk104.c
index cc9bb77e1..c7b570748 100644
--- a/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -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);
}
diff --git a/drm/nouveau/nvkm/engine/fifo/gk104.h b/drm/nouveau/nvkm/engine/fifo/gk104.h
index cfd0f8ef9..9e5d00ba3 100644
--- a/drm/nouveau/nvkm/engine/fifo/gk104.h
+++ b/drm/nouveau/nvkm/engine/fifo/gk104.h
@@ -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