diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/fifo')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 75 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 266 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 7 |
9 files changed, 333 insertions, 61 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 1c9682ae3a6b..660ca7aa95ea 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -32,6 +32,17 @@ #include <nvif/unpack.h> void +nvkm_fifo_recover_chan(struct nvkm_fifo *fifo, int chid) +{ + unsigned long flags; + if (WARN_ON(!fifo->func->recover_chan)) + return; + spin_lock_irqsave(&fifo->lock, flags); + fifo->func->recover_chan(fifo, chid); + spin_unlock_irqrestore(&fifo->lock, flags); +} + +void nvkm_fifo_pause(struct nvkm_fifo *fifo, unsigned long *flags) { return fifo->func->pause(fifo, flags); @@ -55,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; } @@ -90,9 +111,34 @@ nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags) return NULL; } +void +nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid) +{ + nvkm_event_send(&fifo->kevent, 1, chid, NULL, 0); +} + static int -nvkm_fifo_event_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) +nvkm_fifo_kevent_ctor(struct nvkm_object *object, void *data, u32 size, + struct nvkm_notify *notify) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + if (size == 0) { + notify->size = 0; + notify->types = 1; + notify->index = chan->chid; + return 0; + } + return -ENOSYS; +} + +static const struct nvkm_event_func +nvkm_fifo_kevent_func = { + .ctor = nvkm_fifo_kevent_ctor, +}; + +static int +nvkm_fifo_cevent_ctor(struct nvkm_object *object, void *data, u32 size, + struct nvkm_notify *notify) { if (size == 0) { notify->size = 0; @@ -104,10 +150,16 @@ nvkm_fifo_event_ctor(struct nvkm_object *object, void *data, u32 size, } static const struct nvkm_event_func -nvkm_fifo_event_func = { - .ctor = nvkm_fifo_event_ctor, +nvkm_fifo_cevent_func = { + .ctor = nvkm_fifo_cevent_ctor, }; +void +nvkm_fifo_cevent(struct nvkm_fifo *fifo) +{ + nvkm_event_send(&fifo->cevent, 1, 0, NULL, 0); +} + static void nvkm_fifo_uevent_fini(struct nvkm_event *event, int type, int index) { @@ -241,6 +293,7 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) void *data = fifo; if (fifo->func->dtor) data = fifo->func->dtor(fifo); + nvkm_event_fini(&fifo->kevent); nvkm_event_fini(&fifo->cevent); nvkm_event_fini(&fifo->uevent); return data; @@ -283,5 +336,9 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, return ret; } - return nvkm_event_init(&nvkm_fifo_event_func, 1, 1, &fifo->cevent); + ret = nvkm_event_init(&nvkm_fifo_cevent_func, 1, 1, &fifo->cevent); + if (ret) + return ret; + + return nvkm_event_init(&nvkm_fifo_kevent_func, 1, nr, &fifo->kevent); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index dc6d4678f228..fab760ae922f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -371,9 +371,9 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, /* allocate push buffer ctxdma instance */ if (push) { - dmaobj = nvkm_dma_search(device->dma, oclass->client, push); - if (!dmaobj) - return -ENOENT; + dmaobj = nvkm_dmaobj_search(client, push); + if (IS_ERR(dmaobj)) + return PTR_ERR(dmaobj); ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, &chan->push); @@ -410,6 +410,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, base + user * chan->chid; chan->size = user; - nvkm_event_send(&fifo->cevent, 1, 0, NULL, 0); + nvkm_fifo_cevent(fifo); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 55dc415c5c08..d8019bdacd61 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -29,5 +29,5 @@ struct nvkm_fifo_chan_oclass { struct nvkm_sclass base; }; -int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **); +int gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 15a992b3580a..61797c4dd07a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -30,12 +30,12 @@ #include <nvif/cl826e.h> -int +static int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, struct nvkm_event **pevent) { switch (type) { - case G82_CHANNEL_DMA_V0_NTFY_UEVENT: + case NV826E_V0_NTFY_NON_STALL_INTERRUPT: *pevent = &chan->fifo->uevent; return 0; default: diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index ec68ea9747d5..cd468ab1db12 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -68,7 +68,14 @@ gf100_fifo_runlist_commit(struct gf100_fifo *fifo) } nvkm_done(cur); - target = (nvkm_memory_target(cur) == NVKM_MEM_TARGET_HOST) ? 0x3 : 0x0; + switch (nvkm_memory_target(cur)) { + case NVKM_MEM_TARGET_VRAM: target = 0; break; + case NVKM_MEM_TARGET_NCOH: target = 3; break; + default: + mutex_unlock(&subdev->mutex); + WARN_ON(1); + return; + } nvkm_wr32(device, 0x002270, (nvkm_memory_addr(cur) >> 12) | (target << 28)); @@ -183,6 +190,7 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, if (engine != &fifo->base.engine) fifo->recover.mask |= 1ULL << engine->subdev.index; schedule_work(&fifo->recover.work); + nvkm_fifo_kevent(&fifo->base, chid); } static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 38c0910722c0..3a24788c3185 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -27,11 +27,71 @@ #include <core/client.h> #include <core/gpuobj.h> #include <subdev/bar.h> +#include <subdev/timer.h> #include <subdev/top.h> #include <engine/sw.h> #include <nvif/class.h> +struct gk104_fifo_engine_status { + bool busy; + bool faulted; + bool chsw; + bool save; + bool load; + struct { + bool tsg; + u32 id; + } prev, next, *chan; +}; + +static void +gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, + struct gk104_fifo_engine_status *status) +{ + struct nvkm_engine *engine = fifo->engine[engn].engine; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x08)); + + status->busy = !!(stat & 0x80000000); + status->faulted = !!(stat & 0x40000000); + status->next.tsg = !!(stat & 0x10000000); + status->next.id = (stat & 0x0fff0000) >> 16; + status->chsw = !!(stat & 0x00008000); + status->save = !!(stat & 0x00004000); + status->load = !!(stat & 0x00002000); + status->prev.tsg = !!(stat & 0x00001000); + status->prev.id = (stat & 0x00000fff); + status->chan = NULL; + + if (status->busy && status->chsw) { + if (status->load && status->save) { + if (engine && nvkm_engine_chsw_load(engine)) + status->chan = &status->next; + else + status->chan = &status->prev; + } else + if (status->load) { + status->chan = &status->next; + } else { + status->chan = &status->prev; + } + } else + if (status->load) { + status->chan = &status->prev; + } + + nvkm_debug(subdev, "engine %02d: busy %d faulted %d chsw %d " + "save %d load %d %sid %d%s-> %sid %d%s\n", + engn, status->busy, status->faulted, + status->chsw, status->save, status->load, + status->prev.tsg ? "tsg" : "ch", status->prev.id, + status->chan == &status->prev ? "*" : " ", + status->next.tsg ? "tsg" : "ch", status->next.id, + status->chan == &status->next ? "*" : " "); +} + static int gk104_fifo_class_get(struct nvkm_fifo *base, int index, const struct nvkm_fifo_chan_oclass **psclass) @@ -83,10 +143,13 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) } nvkm_done(mem); - if (nvkm_memory_target(mem) == NVKM_MEM_TARGET_VRAM) - target = 0; - else - target = 3; + switch (nvkm_memory_target(mem)) { + case NVKM_MEM_TARGET_VRAM: target = 0; break; + case NVKM_MEM_TARGET_NCOH: target = 3; break; + default: + WARN_ON(1); + return; + } nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) | (target << 28)); @@ -149,31 +212,137 @@ gk104_fifo_recover_work(struct work_struct *w) nvkm_mask(device, 0x002630, runm, 0x00000000); } +static void gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn); + static void -gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine, - struct gk104_fifo_chan *chan) +gk104_fifo_recover_runl(struct gk104_fifo *fifo, int runl) { struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; - u32 chid = chan->base.chid; - int engn; + const u32 runm = BIT(runl); - nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n", - nvkm_subdev_name[engine->subdev.index], chid); assert_spin_locked(&fifo->base.lock); + if (fifo->recover.runm & runm) + return; + fifo->recover.runm |= runm; - nvkm_mask(device, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800); - list_del_init(&chan->head); - chan->killed = true; + /* Block runlist to prevent channel assignment(s) from changing. */ + nvkm_mask(device, 0x002630, runm, runm); - for (engn = 0; engn < fifo->engine_nr; engn++) { - if (fifo->engine[engn].engine == engine) { - fifo->recover.engm |= BIT(engn); + /* Schedule recovery. */ + nvkm_warn(subdev, "runlist %d: scheduled for recovery\n", runl); + schedule_work(&fifo->recover.work); +} + +static void +gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid) +{ + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 stat = nvkm_rd32(device, 0x800004 + (chid * 0x08)); + const u32 runl = (stat & 0x000f0000) >> 16; + const bool used = (stat & 0x00000001); + unsigned long engn, engm = fifo->runlist[runl].engm; + struct gk104_fifo_chan *chan; + + assert_spin_locked(&fifo->base.lock); + if (!used) + return; + + /* Lookup SW state for channel, and mark it as dead. */ + list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { + if (chan->base.chid == chid) { + list_del_init(&chan->head); + chan->killed = true; + nvkm_fifo_kevent(&fifo->base, chid); break; } } - fifo->recover.runm |= BIT(chan->runl); + /* Disable channel. */ + nvkm_wr32(device, 0x800004 + (chid * 0x08), stat | 0x00000800); + nvkm_warn(subdev, "channel %d: killed\n", chid); + + /* Block channel assignments from changing during recovery. */ + gk104_fifo_recover_runl(fifo, runl); + + /* Schedule recovery for any engines the channel is on. */ + for_each_set_bit(engn, &engm, fifo->engine_nr) { + struct gk104_fifo_engine_status status; + gk104_fifo_engine_status(fifo, engn, &status); + if (!status.chan || status.chan->id != chid) + continue; + gk104_fifo_recover_engn(fifo, engn); + } +} + +static void +gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) +{ + struct nvkm_engine *engine = fifo->engine[engn].engine; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 runl = fifo->engine[engn].runl; + const u32 engm = BIT(engn); + struct gk104_fifo_engine_status status; + int mmui = -1; + + assert_spin_locked(&fifo->base.lock); + if (fifo->recover.engm & engm) + return; + fifo->recover.engm |= engm; + + /* Block channel assignments from changing during recovery. */ + gk104_fifo_recover_runl(fifo, runl); + + /* Determine which channel (if any) is currently on the engine. */ + gk104_fifo_engine_status(fifo, engn, &status); + if (status.chan) { + /* The channel is not longer viable, kill it. */ + gk104_fifo_recover_chan(&fifo->base, status.chan->id); + } + + /* Determine MMU fault ID for the engine, if we're not being + * called from the fault handler already. + */ + if (!status.faulted && engine) { + mmui = nvkm_top_fault_id(device, engine->subdev.index); + if (mmui < 0) { + const struct nvkm_enum *en = fifo->func->fault.engine; + for (; en && en->name; en++) { + if (en->data2 == engine->subdev.index) { + mmui = en->value; + break; + } + } + } + WARN_ON(mmui < 0); + } + + /* Trigger a MMU fault for the engine. + * + * No good idea why this is needed, but nvgpu does something similar, + * and it makes recovery from CTXSW_TIMEOUT a lot more reliable. + */ + if (mmui >= 0) { + nvkm_wr32(device, 0x002a30 + (engn * 0x04), 0x00000100 | mmui); + + /* Wait for fault to trigger. */ + nvkm_msec(device, 2000, + gk104_fifo_engine_status(fifo, engn, &status); + if (status.faulted) + break; + ); + + /* Release MMU fault trigger, and ACK the fault. */ + nvkm_wr32(device, 0x002a30 + (engn * 0x04), 0x00000000); + nvkm_wr32(device, 0x00259c, BIT(mmui)); + nvkm_wr32(device, 0x002100, 0x10000000); + } + + /* Schedule recovery. */ + nvkm_warn(subdev, "engine %d: scheduled for recovery\n", engn); schedule_work(&fifo->recover.work); } @@ -211,34 +380,30 @@ static void gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo) { struct nvkm_device *device = fifo->base.engine.subdev.device; - struct gk104_fifo_chan *chan; - unsigned long flags; + unsigned long flags, engm = 0; u32 engn; + /* We need to ACK the SCHED_ERROR here, and prevent it reasserting, + * as MMU_FAULT cannot be triggered while it's pending. + */ spin_lock_irqsave(&fifo->base.lock, flags); + nvkm_mask(device, 0x002140, 0x00000100, 0x00000000); + nvkm_wr32(device, 0x002100, 0x00000100); + for (engn = 0; engn < fifo->engine_nr; engn++) { - struct nvkm_engine *engine = fifo->engine[engn].engine; - int runl = fifo->engine[engn].runl; - u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x08)); - u32 busy = (stat & 0x80000000); - u32 next = (stat & 0x0fff0000) >> 16; - u32 chsw = (stat & 0x00008000); - u32 save = (stat & 0x00004000); - u32 load = (stat & 0x00002000); - u32 prev = (stat & 0x00000fff); - u32 chid = load ? next : prev; - (void)save; - - if (!busy || !chsw) + struct gk104_fifo_engine_status status; + + gk104_fifo_engine_status(fifo, engn, &status); + if (!status.busy || !status.chsw) continue; - list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { - if (chan->base.chid == chid && engine) { - gk104_fifo_recover(fifo, engine, chan); - break; - } - } + engm |= BIT(engn); } + + for_each_set_bit(engn, &engm, fifo->engine_nr) + gk104_fifo_recover_engn(fifo, engn); + + nvkm_mask(device, 0x002140, 0x00000100, 0x00000100); spin_unlock_irqrestore(&fifo->base.lock, flags); } @@ -301,6 +466,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); @@ -342,7 +508,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] " @@ -353,9 +520,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[] = { @@ -716,6 +897,7 @@ gk104_fifo_ = { .intr = gk104_fifo_intr, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .class_get = gk104_fifo_class_get, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 12d964260a29..f9e0377d3d24 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -32,6 +32,23 @@ #include <nvif/cl906f.h> #include <nvif/unpack.h> +int +gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, + struct nvkm_event **pevent) +{ + switch (type) { + case NV906F_V0_NTFY_NON_STALL_INTERRUPT: + *pevent = &chan->fifo->uevent; + return 0; + case NV906F_V0_NTFY_KILLED: + *pevent = &chan->fifo->kevent; + return 0; + default: + break; + } + return -EINVAL; +} + static u32 gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) { @@ -184,7 +201,7 @@ gf100_fifo_gpfifo_func = { .dtor = gf100_fifo_gpfifo_dtor, .init = gf100_fifo_gpfifo_init, .fini = gf100_fifo_gpfifo_fini, - .ntfy = g84_fifo_chan_ntfy, + .ntfy = gf100_fifo_chan_ntfy, .engine_ctor = gf100_fifo_gpfifo_engine_ctor, .engine_dtor = gf100_fifo_gpfifo_engine_dtor, .engine_init = gf100_fifo_gpfifo_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index a2df4f3e7763..8abf6f8ef445 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -50,6 +50,7 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan) ) < 0) { nvkm_error(subdev, "channel %d [%s] kick timeout\n", chan->base.chid, client->name); + nvkm_fifo_recover_chan(&fifo->base, chan->base.chid); ret = -ETIMEDOUT; } mutex_unlock(&subdev->mutex); @@ -213,7 +214,7 @@ gk104_fifo_gpfifo_func = { .dtor = gk104_fifo_gpfifo_dtor, .init = gk104_fifo_gpfifo_init, .fini = gk104_fifo_gpfifo_fini, - .ntfy = g84_fifo_chan_ntfy, + .ntfy = gf100_fifo_chan_ntfy, .engine_ctor = gk104_fifo_gpfifo_engine_ctor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gk104_fifo_gpfifo_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index f6dfb37d9429..f889b13b5e41 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -6,6 +6,12 @@ int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, int index, int nr, struct nvkm_fifo *); void nvkm_fifo_uevent(struct nvkm_fifo *); +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 { @@ -18,6 +24,7 @@ struct nvkm_fifo_func { void (*start)(struct nvkm_fifo *, unsigned long *); void (*uevent_init)(struct nvkm_fifo *); void (*uevent_fini)(struct nvkm_fifo *); + void (*recover_chan)(struct nvkm_fifo *, int chid); int (*class_get)(struct nvkm_fifo *, int index, const struct nvkm_fifo_chan_oclass **); const struct nvkm_fifo_chan_oclass *chan[]; |