drm/nouveau/fifo/gk104-: directly use new recovery code for mmu faults
authorBen Skeggs <bskeggs@redhat.com>
Wed, 18 Jan 2017 06:01:11 +0000 (16:01 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 17 Feb 2017 07:38:14 +0000 (17:38 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h

index 23f50f1ed7a25ae22515be766b507c5d0deb34e2..660ca7aa95ea397fc7b8770ed584c76a7c7d71d5 100644 (file)
@@ -66,19 +66,29 @@ nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags,
 }
 
 struct nvkm_fifo_chan *
-nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags)
+nvkm_fifo_chan_inst_locked(struct nvkm_fifo *fifo, u64 inst)
 {
        struct nvkm_fifo_chan *chan;
-       unsigned long flags;
-       spin_lock_irqsave(&fifo->lock, flags);
        list_for_each_entry(chan, &fifo->chan, head) {
                if (chan->inst->addr == inst) {
                        list_del(&chan->head);
                        list_add(&chan->head, &fifo->chan);
-                       *rflags = flags;
                        return chan;
                }
        }
+       return NULL;
+}
+
+struct nvkm_fifo_chan *
+nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags)
+{
+       struct nvkm_fifo_chan *chan;
+       unsigned long flags;
+       spin_lock_irqsave(&fifo->lock, flags);
+       if ((chan = nvkm_fifo_chan_inst_locked(fifo, inst))) {
+               *rflags = flags;
+               return chan;
+       }
        spin_unlock_irqrestore(&fifo->lock, flags);
        return NULL;
 }
index 4f174470c02b13b51b3cf054f1010987af4b0c29..4422891d3a8654ce63ea1d63045e692363355472 100644 (file)
@@ -435,6 +435,7 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
        struct nvkm_fifo_chan *chan;
        unsigned long flags;
        char gpcid[8] = "", en[16] = "";
+       int engn;
 
        er = nvkm_enum_find(fifo->func->fault.reason, reason);
        eu = nvkm_enum_find(fifo->func->fault.engine, unit);
@@ -476,7 +477,8 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
                snprintf(en, sizeof(en), "%s", eu->name);
        }
 
-       chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags);
+       spin_lock_irqsave(&fifo->base.lock, flags);
+       chan = nvkm_fifo_chan_inst_locked(&fifo->base, (u64)inst << 12);
 
        nvkm_error(subdev,
                   "%s fault at %010llx engine %02x [%s] client %02x [%s%s] "
@@ -487,9 +489,23 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
                   (u64)inst << 12,
                   chan ? chan->object.client->name : "unknown");
 
-       if (engine && chan)
-               gk104_fifo_recover(fifo, engine, (void *)chan);
-       nvkm_fifo_chan_put(&fifo->base, flags, &chan);
+
+       /* Kill the channel that caused the fault. */
+       if (chan)
+               gk104_fifo_recover_chan(&fifo->base, chan->chid);
+
+       /* Channel recovery will probably have already done this for the
+        * correct engine(s), but just in case we can't find the channel
+        * information...
+        */
+       for (engn = 0; engn < fifo->engine_nr && engine; engn++) {
+               if (fifo->engine[engn].engine == engine) {
+                       gk104_fifo_recover_engn(fifo, engn);
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&fifo->base.lock, flags);
 }
 
 static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
index 78136d947cbeffdc317f7743bee620958855823a..f889b13b5e4178ce9c4a964676d75ab37307bc37 100644 (file)
@@ -10,6 +10,9 @@ void nvkm_fifo_cevent(struct nvkm_fifo *);
 void nvkm_fifo_kevent(struct nvkm_fifo *, int chid);
 void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid);
 
+struct nvkm_fifo_chan *
+nvkm_fifo_chan_inst_locked(struct nvkm_fifo *, u64 inst);
+
 struct nvkm_fifo_chan_oclass;
 struct nvkm_fifo_func {
        void *(*dtor)(struct nvkm_fifo *);