drm/nouveau/fifo/gk104-: directly use new recovery code for mmu faults

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2017-01-18 16:01:11 +10:00
parent eaa5ed65ee
commit 3534821df5
3 changed files with 40 additions and 11 deletions

View File

@ -65,19 +65,29 @@ nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags,
}
}
struct nvkm_fifo_chan *
nvkm_fifo_chan_inst_locked(struct nvkm_fifo *fifo, u64 inst)
{
struct nvkm_fifo_chan *chan;
list_for_each_entry(chan, &fifo->chan, head) {
if (chan->inst->addr == inst) {
list_del(&chan->head);
list_add(&chan->head, &fifo->chan);
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);
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;
}
if ((chan = nvkm_fifo_chan_inst_locked(fifo, inst))) {
*rflags = flags;
return chan;
}
spin_unlock_irqrestore(&fifo->lock, flags);
return NULL;

View 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[] = {

View 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 *);