From e43c872c03a9ad56f5cbc52149b4454601aa6904 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:29 +1000 Subject: [PATCH] drm/nouveau/fifo: merge mmu fault handlers together After updating GF100 implementation from the GK104/TU102 ones, and using the new runlist/engine topology info, all three handlers become (almost) identical. - there's a temporary kludge to call through to the HW-specific recovery - engine fault mapping info determined at load time, not on every fault Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 112 +++++++++----- .../gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 137 +++--------------- .../gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 14 -- .../gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 5 - .../gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 5 - .../gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 5 - .../gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 32 ++-- .../gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 5 - .../gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 40 ++--- .../gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 22 +-- .../gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 18 ++- .../gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 23 ++- .../gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 2 + .../gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 100 +------------ 14 files changed, 184 insertions(+), 336 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 177ae02e78ee..7fc4c37b407f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -295,7 +295,7 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, } static const struct nvkm_enum -gf100_fifo_fault_engine[] = { +gf100_fifo_mmu_fault_engine[] = { { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, { 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, @@ -312,7 +312,7 @@ gf100_fifo_fault_engine[] = { }; static const struct nvkm_enum -gf100_fifo_fault_reason[] = { +gf100_fifo_mmu_fault_reason[] = { { 0x00, "PT_NOT_PRESENT" }, { 0x01, "PT_TOO_SHORT" }, { 0x02, "PAGE_NOT_PRESENT" }, @@ -326,7 +326,7 @@ gf100_fifo_fault_reason[] = { }; static const struct nvkm_enum -gf100_fifo_fault_hubclient[] = { +gf100_fifo_mmu_fault_hubclient[] = { { 0x01, "PCOPY0" }, { 0x02, "PCOPY1" }, { 0x04, "DISPATCH" }, @@ -345,7 +345,7 @@ gf100_fifo_fault_hubclient[] = { }; static const struct nvkm_enum -gf100_fifo_fault_gpcclient[] = { +gf100_fifo_mmu_fault_gpcclient[] = { { 0x01, "TEX" }, { 0x0c, "ESETUP" }, { 0x0e, "CTXCTL" }, @@ -353,29 +353,48 @@ gf100_fifo_fault_gpcclient[] = { {} }; -static void -gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) +const struct nvkm_enum +gf100_fifo_mmu_fault_access[] = { + { 0x00, "READ" }, + { 0x01, "WRITE" }, + {} +}; + +void +gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *info) { - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; - const struct nvkm_enum *er, *eu, *ec; + const struct nvkm_enum *er, *ee, *ec, *ea; struct nvkm_engine *engine = NULL; struct nvkm_fifo_chan *chan; + struct nvkm_runl *runl; + struct nvkm_engn *engn; unsigned long flags; - char gpcid[8] = ""; + char ct[8] = "HUB/"; - er = nvkm_enum_find(gf100_fifo_fault_reason, info->reason); - eu = nvkm_enum_find(gf100_fifo_fault_engine, info->engine); - if (info->hub) { - ec = nvkm_enum_find(gf100_fifo_fault_hubclient, info->client); - } else { - ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, info->client); - snprintf(gpcid, sizeof(gpcid), "GPC%d/", info->gpc); + /* Lookup engine by MMU fault ID. */ + nvkm_runl_foreach(runl, fifo) { + engn = nvkm_runl_find_engn(engn, runl, engn->fault == info->engine); + if (engn) { + engine = engn->engine; + break; + } } - if (eu && eu->data2) { - switch (eu->data2) { + er = nvkm_enum_find(fifo->func->mmu_fault->reason, info->reason); + ee = nvkm_enum_find(fifo->func->mmu_fault->engine, info->engine); + if (info->hub) { + ec = nvkm_enum_find(fifo->func->mmu_fault->hubclient, info->client); + } else { + ec = nvkm_enum_find(fifo->func->mmu_fault->gpcclient, info->client); + snprintf(ct, sizeof(ct), "GPC%d/", info->gpc); + } + ea = nvkm_enum_find(fifo->func->mmu_fault->access, info->access); + + /* Handle BAR faults. */ + if (ee && ee->data2) { + switch (ee->data2) { case NVKM_SUBDEV_BAR: nvkm_bar_bar1_reset(device); break; @@ -386,30 +405,39 @@ gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); break; default: - engine = nvkm_device_engine(device, eu->data2, eu->inst); break; } } - chan = nvkm_fifo_chan_inst(&fifo->base, info->inst, &flags); + chan = nvkm_fifo_chan_inst(fifo, info->inst, &flags); nvkm_error(subdev, - "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " - "reason %02x [%s] on channel %d [%010llx %s]\n", - info->access ? "write" : "read", info->addr, - info->engine, eu ? eu->name : "", - info->client, gpcid, ec ? ec->name : "", - info->reason, er ? er->name : "", chan ? chan->chid : -1, - info->inst, chan ? chan->object.client->name : "unknown"); + "fault %02x [%s] at %016llx engine %02x [%s] client %02x " + "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n", + info->access, ea ? ea->name : "", info->addr, + info->engine, ee ? ee->name : engine ? engine->subdev.name : "", + info->client, ct, ec ? ec->name : "", + info->reason, er ? er->name : "", + chan ? chan->id : -1, info->inst, chan ? chan->name : "unknown"); + /* Handle host/engine faults. */ + if (fifo->func->recover_chan && chan) + fifo->func->recover_chan(fifo, chan->id); + else if (engine && chan) - gf100_fifo_recover(fifo, engine, (void *)chan); - nvkm_fifo_chan_put(&fifo->base, flags, &chan); + gf100_fifo_recover(gf100_fifo(fifo), engine, (void *)chan); + + nvkm_fifo_chan_put(fifo, flags, &chan); } static const struct nvkm_fifo_func_mmu_fault gf100_fifo_mmu_fault = { - .recover = gf100_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gf100_fifo_mmu_fault_engine, + .reason = gf100_fifo_mmu_fault_reason, + .hubclient = gf100_fifo_mmu_fault_hubclient, + .gpcclient = gf100_fifo_mmu_fault_gpcclient, }; static const struct nvkm_enum @@ -498,6 +526,19 @@ gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) nvkm_fifo_fault(fifo, &info); } +void +gf100_fifo_intr_mmu_fault(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + unsigned long mask = nvkm_rd32(device, 0x00259c); + int unit; + + for_each_set_bit(unit, &mask, 32) { + fifo->func->intr_mmu_fault_unit(fifo, unit); + nvkm_wr32(device, 0x00259c, BIT(unit)); + } +} + bool gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo) { @@ -609,13 +650,7 @@ gf100_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x10000000) { - u32 mask = nvkm_rd32(device, 0x00259c); - while (mask) { - u32 unit = __ffs(mask); - gf100_fifo_intr_mmu_fault_unit(fifo, unit); - nvkm_wr32(device, 0x00259c, (1 << unit)); - mask &= ~(1 << unit); - } + gf100_fifo_intr_mmu_fault(fifo); stat &= ~0x10000000; } @@ -783,6 +818,7 @@ gf100_fifo = { .init_pbdmas = gf100_fifo_init_pbdmas, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, + .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gf100_fifo_mmu_fault, .engine_id = gf100_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 6295389bfbea..de8e3a17d79e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -30,10 +30,8 @@ #include "cgrp.h" #include "changk104.h" -#include #include #include -#include #include #include #include @@ -474,7 +472,7 @@ gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) if (!status.faulted && engine) { mmui = nvkm_top_fault_id(device, engine->subdev.type, engine->subdev.inst); if (mmui < 0) { - const struct nvkm_enum *en = fifo->func->fault.engine; + const struct nvkm_enum *en = fifo->func->mmu_fault->engine; for (; en && en->name; en++) { if (en->data2 == engine->subdev.type && en->inst == engine->subdev.inst) { @@ -512,15 +510,8 @@ gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) schedule_work(&fifo->recover.work); } -const struct nvkm_enum -gk104_fifo_fault_access[] = { - { 0x0, "READ" }, - { 0x1, "WRITE" }, - {} -}; - -const struct nvkm_enum -gk104_fifo_fault_engine[] = { +static const struct nvkm_enum +gk104_fifo_mmu_fault_engine[] = { { 0x00, "GR", NULL, NVKM_ENGINE_GR }, { 0x01, "DISPLAY" }, { 0x02, "CAPTURE" }, @@ -528,14 +519,14 @@ gk104_fifo_fault_engine[] = { { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, { 0x06, "SCHED" }, - { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, - { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, - { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, - { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, - { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, - { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, - { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, - { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, + { 0x07, "HOST0" }, + { 0x08, "HOST1" }, + { 0x09, "HOST2" }, + { 0x0a, "HOST3" }, + { 0x0b, "HOST4" }, + { 0x0c, "HOST5" }, + { 0x0d, "HOST6" }, + { 0x0e, "HOST7" }, { 0x0f, "HOSTSR" }, { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD }, { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP }, @@ -551,7 +542,7 @@ gk104_fifo_fault_engine[] = { }; const struct nvkm_enum -gk104_fifo_fault_reason[] = { +gk104_fifo_mmu_fault_reason[] = { { 0x00, "PDE" }, { 0x01, "PDE_SIZE" }, { 0x02, "PTE" }, @@ -572,7 +563,7 @@ gk104_fifo_fault_reason[] = { }; const struct nvkm_enum -gk104_fifo_fault_hubclient[] = { +gk104_fifo_mmu_fault_hubclient[] = { { 0x00, "VIP" }, { 0x01, "CE0" }, { 0x02, "CE1" }, @@ -609,7 +600,7 @@ gk104_fifo_fault_hubclient[] = { }; const struct nvkm_enum -gk104_fifo_fault_gpcclient[] = { +gk104_fifo_mmu_fault_gpcclient[] = { { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" }, { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" }, { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" }, @@ -634,89 +625,14 @@ gk104_fifo_fault_gpcclient[] = { {} }; -void -gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const struct nvkm_enum *er, *ee, *ec, *ea; - struct nvkm_engine *engine = NULL; - struct nvkm_fifo_chan *chan; - unsigned long flags; - const char *en = ""; - char ct[8] = "HUB/"; - - er = nvkm_enum_find(fifo->func->fault.reason, info->reason); - ee = nvkm_enum_find(fifo->func->fault.engine, info->engine); - if (info->hub) { - ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client); - } else { - ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client); - snprintf(ct, sizeof(ct), "GPC%d/", info->gpc); - } - ea = nvkm_enum_find(fifo->func->fault.access, info->access); - - if (ee && ee->data2) { - switch (ee->data2) { - case NVKM_SUBDEV_BAR: - nvkm_bar_bar1_reset(device); - break; - case NVKM_SUBDEV_INSTMEM: - nvkm_bar_bar2_reset(device); - break; - case NVKM_ENGINE_IFB: - nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); - break; - default: - engine = nvkm_device_engine(device, ee->data2, 0); - break; - } - } - - if (ee == NULL) { - struct nvkm_subdev *subdev = nvkm_top_fault(device, info->engine); - if (subdev) { - if (subdev->func == &nvkm_engine) - engine = container_of(subdev, typeof(*engine), subdev); - en = engine->subdev.name; - } - } else { - en = ee->name; - } - - spin_lock_irqsave(&fifo->base.lock, flags); - chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst); - - nvkm_error(subdev, - "fault %02x [%s] at %016llx engine %02x [%s] client %02x " - "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n", - info->access, ea ? ea->name : "", info->addr, - info->engine, ee ? ee->name : en, - info->client, ct, ec ? ec->name : "", - info->reason, er ? er->name : "", chan ? chan->chid : -1, - info->inst, chan ? chan->object.client->name : "unknown"); - - /* 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... - */ - if (engine) { - int engn = fifo->base.func->engine_id(&fifo->base, engine); - if (engn >= 0 && engn != GK104_FIFO_ENGN_SW) - gk104_fifo_recover_engn(fifo, engn); - } - - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gk104_fifo_mmu_fault_engine, + .reason = gk104_fifo_mmu_fault_reason, + .hubclient = gk104_fifo_mmu_fault_hubclient, + .gpcclient = gk104_fifo_mmu_fault_gpcclient, }; static const struct nvkm_enum @@ -884,13 +800,7 @@ gk104_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x10000000) { - u32 mask = nvkm_rd32(device, 0x00259c); - while (mask) { - u32 unit = __ffs(mask); - fifo->func->intr_mmu_fault_unit(fifo, unit); - nvkm_wr32(device, 0x00259c, (1 << unit)); - mask &= ~(1 << unit); - } + gf100_fifo_intr_mmu_fault(fifo); stat &= ~0x10000000; } @@ -1105,11 +1015,6 @@ gk104_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index f7e6c26a2a45..13f1efcc9e24 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -69,11 +69,6 @@ int gk104_fifo_oneinit(struct nvkm_fifo *); void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); -extern const struct nvkm_enum gk104_fifo_fault_access[]; -extern const struct nvkm_enum gk104_fifo_fault_engine[]; -extern const struct nvkm_enum gk104_fifo_fault_reason[]; -extern const struct nvkm_enum gk104_fifo_fault_hubclient[]; -extern const struct nvkm_enum gk104_fifo_fault_gpcclient[]; extern const struct gk104_fifo_runlist_func gk104_fifo_runlist; void gk104_fifo_runlist_chan(struct gk104_fifo_chan *, struct nvkm_memory *, u32); @@ -84,17 +79,8 @@ extern const struct gk104_fifo_runlist_func gk110_fifo_runlist; void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, struct nvkm_memory *, u32); -void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *); - -extern const struct nvkm_enum gm107_fifo_fault_engine[]; extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; -extern const struct nvkm_enum gp100_fifo_fault_engine[]; - -extern const struct nvkm_enum gv100_fifo_fault_access[]; -extern const struct nvkm_enum gv100_fifo_fault_reason[]; -extern const struct nvkm_enum gv100_fifo_fault_hubclient[]; -extern const struct nvkm_enum gv100_fifo_fault_gpcclient[]; void gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, struct nvkm_memory *, u32); void gv100_fifo_runlist_chan(struct gk104_fifo_chan *, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 4143a07e3808..5271f5504854 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -88,11 +88,6 @@ gk110_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 87601c35581c..ab813aa6d1a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -62,11 +62,6 @@ gk208_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 3d3db802b824..0d633b805331 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -38,11 +38,6 @@ gk20a_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index a85f30768b74..ecf4e6d94866 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -56,22 +56,22 @@ const struct nvkm_runl_func gm107_runl = { }; -const struct nvkm_enum -gm107_fifo_fault_engine[] = { +static const struct nvkm_enum +gm107_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x02, "CAPTURE" }, { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, { 0x06, "SCHED" }, - { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, - { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, - { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, - { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, - { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, - { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, - { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, - { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, + { 0x07, "HOST0" }, + { 0x08, "HOST1" }, + { 0x09, "HOST2" }, + { 0x0a, "HOST3" }, + { 0x0b, "HOST4" }, + { 0x0c, "HOST5" }, + { 0x0d, "HOST6" }, + { 0x0e, "HOST7" }, { 0x0f, "HOSTSR" }, { 0x13, "PERF" }, { 0x17, "PMU" }, @@ -81,7 +81,12 @@ gm107_fifo_fault_engine[] = { const struct nvkm_fifo_func_mmu_fault gm107_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gm107_fifo_mmu_fault_engine, + .reason = gk104_fifo_mmu_fault_reason, + .hubclient = gk104_fifo_mmu_fault_hubclient, + .gpcclient = gk104_fifo_mmu_fault_gpcclient, }; void @@ -128,11 +133,6 @@ gm107_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, .mmu_fault = &gm107_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gm107_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 131e4ae61590..6fa96a4c3e23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -52,11 +52,6 @@ gm200_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, .mmu_fault = &gm107_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gm107_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index b05ede6dd392..0ca14b08ca3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -33,23 +33,23 @@ static const struct nvkm_runl_func gp100_runl = { }; -const struct nvkm_enum -gp100_fifo_fault_engine[] = { +static const struct nvkm_enum +gp100_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, - { 0x06, "HOST0", NULL, NVKM_ENGINE_FIFO }, - { 0x07, "HOST1", NULL, NVKM_ENGINE_FIFO }, - { 0x08, "HOST2", NULL, NVKM_ENGINE_FIFO }, - { 0x09, "HOST3", NULL, NVKM_ENGINE_FIFO }, - { 0x0a, "HOST4", NULL, NVKM_ENGINE_FIFO }, - { 0x0b, "HOST5", NULL, NVKM_ENGINE_FIFO }, - { 0x0c, "HOST6", NULL, NVKM_ENGINE_FIFO }, - { 0x0d, "HOST7", NULL, NVKM_ENGINE_FIFO }, - { 0x0e, "HOST8", NULL, NVKM_ENGINE_FIFO }, - { 0x0f, "HOST9", NULL, NVKM_ENGINE_FIFO }, - { 0x10, "HOST10", NULL, NVKM_ENGINE_FIFO }, + { 0x06, "HOST0" }, + { 0x07, "HOST1" }, + { 0x08, "HOST2" }, + { 0x09, "HOST3" }, + { 0x0a, "HOST4" }, + { 0x0b, "HOST5" }, + { 0x0c, "HOST6" }, + { 0x0d, "HOST7" }, + { 0x0e, "HOST8" }, + { 0x0f, "HOST9" }, + { 0x10, "HOST10" }, { 0x13, "PERF" }, { 0x17, "PMU" }, { 0x18, "PTP" }, @@ -59,10 +59,15 @@ gp100_fifo_fault_engine[] = { static const struct nvkm_fifo_func_mmu_fault gp100_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gp100_fifo_mmu_fault_engine, + .reason = gk104_fifo_mmu_fault_reason, + .hubclient = gk104_fifo_mmu_fault_hubclient, + .gpcclient = gk104_fifo_mmu_fault_gpcclient, }; -void +static void gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) { struct nvkm_device *device = fifo->engine.subdev.device; @@ -100,11 +105,6 @@ gp100_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gp100_fifo_intr_mmu_fault_unit, .mmu_fault = &gp100_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gp100_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index dc1586e2ab72..49d7c9e7fb8a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -87,7 +87,7 @@ gv100_runl = { }; const struct nvkm_enum -gv100_fifo_fault_gpcclient[] = { +gv100_fifo_mmu_fault_gpcclient[] = { { 0x00, "T1_0" }, { 0x01, "T1_1" }, { 0x02, "T1_2" }, @@ -189,7 +189,7 @@ gv100_fifo_fault_gpcclient[] = { }; const struct nvkm_enum -gv100_fifo_fault_hubclient[] = { +gv100_fifo_mmu_fault_hubclient[] = { { 0x00, "VIP" }, { 0x01, "CE0" }, { 0x02, "CE1" }, @@ -251,7 +251,7 @@ gv100_fifo_fault_hubclient[] = { }; const struct nvkm_enum -gv100_fifo_fault_reason[] = { +gv100_fifo_mmu_fault_reason[] = { { 0x00, "PDE" }, { 0x01, "PDE_SIZE" }, { 0x02, "PTE" }, @@ -272,7 +272,7 @@ gv100_fifo_fault_reason[] = { }; static const struct nvkm_enum -gv100_fifo_fault_engine[] = { +gv100_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x03, "PTP" }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, @@ -299,7 +299,7 @@ gv100_fifo_fault_engine[] = { }; const struct nvkm_enum -gv100_fifo_fault_access[] = { +gv100_fifo_mmu_fault_access[] = { { 0x0, "VIRT_READ" }, { 0x1, "VIRT_WRITE" }, { 0x2, "VIRT_ATOMIC" }, @@ -314,7 +314,12 @@ gv100_fifo_fault_access[] = { static const struct nvkm_fifo_func_mmu_fault gv100_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gv100_fifo_mmu_fault_access, + .engine = gv100_fifo_mmu_fault_engine, + .reason = gv100_fifo_mmu_fault_reason, + .hubclient = gv100_fifo_mmu_fault_hubclient, + .gpcclient = gv100_fifo_mmu_fault_gpcclient, }; static const struct nvkm_fifo_func @@ -330,11 +335,6 @@ gv100_fifo = { .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .mmu_fault = &gv100_fifo_mmu_fault, - .fault.access = gv100_fifo_fault_access, - .fault.engine = gv100_fifo_fault_engine, - .fault.reason = gv100_fifo_fault_reason, - .fault.hubclient = gv100_fifo_fault_hubclient, - .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 00f23c39978e..19c6e706f33e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -37,15 +37,12 @@ struct nvkm_fifo_func { const struct nvkm_fifo_func_mmu_fault { void (*recover)(struct nvkm_fifo *, struct nvkm_fault_data *); - } *mmu_fault; - - struct { const struct nvkm_enum *access; const struct nvkm_enum *engine; const struct nvkm_enum *reason; const struct nvkm_enum *hubclient; const struct nvkm_enum *gpcclient; - } fault; + } *mmu_fault; int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *); void (*pause)(struct nvkm_fifo *, unsigned long *); @@ -116,7 +113,10 @@ extern const struct nvkm_chan_func g84_chan; int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); int gf100_fifo_runq_nr(struct nvkm_fifo *); bool gf100_fifo_intr_pbdma(struct nvkm_fifo *); +void gf100_fifo_intr_mmu_fault(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); +void gf100_fifo_mmu_fault_recover(struct nvkm_fifo *, struct nvkm_fault_data *); +extern const struct nvkm_enum gf100_fifo_mmu_fault_access[]; extern const struct nvkm_event_func gf100_fifo_nonstall; void gf100_runq_init(struct nvkm_runq *); bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *); @@ -129,7 +129,9 @@ irqreturn_t gk104_fifo_intr(struct nvkm_inth *); void gk104_fifo_intr_chsw(struct nvkm_fifo *); void gk104_fifo_intr_bind(struct nvkm_fifo *); extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; -void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); +extern const struct nvkm_enum gk104_fifo_mmu_fault_reason[]; +extern const struct nvkm_enum gk104_fifo_mmu_fault_hubclient[]; +extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[]; void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); extern const struct nvkm_runq_func gk104_runq; @@ -155,8 +157,10 @@ extern const struct nvkm_chan_func gm107_chan; int gm200_fifo_chid_nr(struct nvkm_fifo *); int gm200_fifo_runq_nr(struct nvkm_fifo *); -void gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); - +extern const struct nvkm_enum gv100_fifo_mmu_fault_access[]; +extern const struct nvkm_enum gv100_fifo_mmu_fault_reason[]; +extern const struct nvkm_enum gv100_fifo_mmu_fault_hubclient[]; +extern const struct nvkm_enum gv100_fifo_mmu_fault_gpcclient[]; extern const struct nvkm_runq_func gv100_runq; extern const struct nvkm_engn_func gv100_engn; extern const struct nvkm_engn_func gv100_engn_ce; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 1a15b0a9ab7c..0b75565bfbc1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -24,6 +24,8 @@ #include "chid.h" #include "priv.h" +#include + void nvkm_runl_del(struct nvkm_runl *runl) { @@ -46,7 +48,8 @@ struct nvkm_engn * nvkm_runl_add(struct nvkm_runl *runl, int engi, const struct nvkm_engn_func *func, enum nvkm_subdev_type type, int inst) { - struct nvkm_device *device = runl->fifo->engine.subdev.device; + struct nvkm_fifo *fifo = runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_engine *engine; struct nvkm_engn *engn; @@ -63,7 +66,25 @@ nvkm_runl_add(struct nvkm_runl *runl, int engi, const struct nvkm_engn_func *fun engn->runl = runl; engn->id = engi; engn->engine = engine; + engn->fault = -1; list_add_tail(&engn->head, &runl->engns); + + /* Lookup MMU engine ID for fault handling. */ + if (device->top) + engn->fault = nvkm_top_fault_id(device, engine->subdev.type, engine->subdev.inst); + + if (engn->fault < 0 && fifo->func->mmu_fault) { + const struct nvkm_enum *map = fifo->func->mmu_fault->engine; + + while (map->name) { + if (map->data2 == engine->subdev.type && map->inst == engine->subdev.inst) { + engn->fault = map->value; + break; + } + map++; + } + } + return engn; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index cb0de870a118..b223da2d4399 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -13,6 +13,8 @@ struct nvkm_engn { struct nvkm_engine *engine; + int fault; + struct list_head head; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 2d14795b9842..47de0b97534a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -26,12 +26,8 @@ #include "cgrp.h" #include "changk104.h" -#include #include -#include -#include #include -#include #include @@ -67,7 +63,7 @@ tu102_runl = { }; static const struct nvkm_enum -tu102_fifo_fault_engine[] = { +tu102_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x03, "PTP" }, { 0x06, "PWR_PMU" }, @@ -247,91 +243,14 @@ tu102_fifo_recover_engn(struct gk104_fifo *fifo, int engn) schedule_work(&fifo->recover.work); } -static void -tu102_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const struct nvkm_enum *er, *ee, *ec, *ea; - struct nvkm_engine *engine = NULL; - struct nvkm_fifo_chan *chan; - unsigned long flags; - const char *en = ""; - char ct[8] = "HUB/"; - int engn; - - er = nvkm_enum_find(fifo->func->fault.reason, info->reason); - ee = nvkm_enum_find(fifo->func->fault.engine, info->engine); - if (info->hub) { - ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client); - } else { - ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client); - snprintf(ct, sizeof(ct), "GPC%d/", info->gpc); - } - ea = nvkm_enum_find(fifo->func->fault.access, info->access); - - if (ee && ee->data2) { - switch (ee->data2) { - case NVKM_SUBDEV_BAR: - nvkm_bar_bar1_reset(device); - break; - case NVKM_SUBDEV_INSTMEM: - nvkm_bar_bar2_reset(device); - break; - case NVKM_ENGINE_IFB: - nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); - break; - default: - engine = nvkm_device_engine(device, ee->data2, 0); - break; - } - } - - if (ee == NULL) { - struct nvkm_subdev *subdev = nvkm_top_fault(device, info->engine); - if (subdev) { - if (subdev->func == &nvkm_engine) - engine = container_of(subdev, typeof(*engine), subdev); - en = engine->subdev.name; - } - } else { - en = ee->name; - } - - spin_lock_irqsave(&fifo->base.lock, flags); - chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst); - - nvkm_error(subdev, - "fault %02x [%s] at %016llx engine %02x [%s] client %02x " - "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n", - info->access, ea ? ea->name : "", info->addr, - info->engine, ee ? ee->name : en, - info->client, ct, ec ? ec->name : "", - info->reason, er ? er->name : "", chan ? chan->chid : -1, - info->inst, chan ? chan->object.client->name : "unknown"); - - /* Kill the channel that caused the fault. */ - if (chan) - tu102_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) { - tu102_fifo_recover_engn(fifo, engn); - break; - } - } - - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault = { - .recover = tu102_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gv100_fifo_mmu_fault_access, + .engine = tu102_fifo_mmu_fault_engine, + .reason = gv100_fifo_mmu_fault_reason, + .hubclient = gv100_fifo_mmu_fault_hubclient, + .gpcclient = gv100_fifo_mmu_fault_gpcclient, }; static void @@ -441,11 +360,6 @@ tu102_fifo = { .fini = gk104_fifo_fini, .intr = tu102_fifo_intr, .mmu_fault = &tu102_fifo_mmu_fault, - .fault.access = gv100_fifo_fault_access, - .fault.engine = tu102_fifo_fault_engine, - .fault.reason = gv100_fifo_fault_reason, - .fault.hubclient = gv100_fifo_fault_hubclient, - .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist,