diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm')
57 files changed, 674 insertions, 219 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/intr.c b/drivers/gpu/drm/nouveau/nvkm/core/intr.c index e20b7ca218c3..36a747f0039e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/intr.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/intr.c @@ -212,8 +212,8 @@ nvkm_intr(int irq, void *arg) list_for_each_entry(intr, &device->intr.intr, head) { for (leaf = 0; leaf < intr->leaves; leaf++) { if (intr->stat[leaf]) { - nvkm_warn(intr->subdev, "intr%d: %08x\n", - leaf, intr->stat[leaf]); + nvkm_debug(intr->subdev, "intr%d: %08x\n", + leaf, intr->stat[leaf]); nvkm_intr_block_locked(intr, leaf, intr->stat[leaf]); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c index 301a5e5b5f7f..7c554c14e884 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -185,7 +185,7 @@ nvkm_object_fini(struct nvkm_object *object, bool suspend) nvif_debug(object, "%s children...\n", action); time = ktime_to_us(ktime_get()); - list_for_each_entry(child, &object->tree, head) { + list_for_each_entry_reverse(child, &object->tree, head) { ret = nvkm_object_fini(child, suspend); if (ret && suspend) goto fail_child; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c index 6648ed62daa6..315a69f7fdd1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c @@ -36,6 +36,15 @@ ga100_ce_intr(struct nvkm_inth *inth) } int +ga100_ce_nonstall(struct nvkm_engine *engine) +{ + struct nvkm_subdev *subdev = &engine->subdev; + struct nvkm_device *device = subdev->device; + + return nvkm_rd32(device, 0x104424 + (subdev->inst * 0x80)) & 0x00000fff; +} + +int ga100_ce_fini(struct nvkm_engine *engine, bool suspend) { nvkm_inth_block(&engine->subdev.inth); @@ -67,6 +76,7 @@ ga100_ce = { .oneinit = ga100_ce_oneinit, .init = ga100_ce_init, .fini = ga100_ce_fini, + .nonstall = ga100_ce_nonstall, .cclass = &gv100_ce_cclass, .sclass = { { -1, -1, AMPERE_DMA_COPY_A }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c index 9f3448ad625f..461b73c7e2e0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c @@ -28,6 +28,7 @@ ga102_ce = { .oneinit = ga100_ce_oneinit, .init = ga100_ce_init, .fini = ga100_ce_fini, + .nonstall = ga100_ce_nonstall, .cclass = &gv100_ce_cclass, .sclass = { { -1, -1, AMPERE_DMA_COPY_A }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h index c4c046916fa6..0be72c463b21 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h @@ -3,7 +3,7 @@ #define __NVKM_CE_PRIV_H__ #include <engine/ce.h> -void gt215_ce_intr(struct nvkm_falcon *, struct nvkm_fifo_chan *); +void gt215_ce_intr(struct nvkm_falcon *, struct nvkm_chan *); void gk104_ce_intr(struct nvkm_engine *); void gp100_ce_intr(struct nvkm_engine *); @@ -12,4 +12,5 @@ extern const struct nvkm_object_func gv100_ce_cclass; int ga100_ce_oneinit(struct nvkm_engine *); int ga100_ce_init(struct nvkm_engine *); int ga100_ce_fini(struct nvkm_engine *, bool); +int ga100_ce_nonstall(struct nvkm_engine *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 5ea9a2ff0663..5db37247dc29 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -283,11 +283,21 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) } /* Initialise non-stall intr handling. */ - if (fifo->func->nonstall_ctor) { - ret = fifo->func->nonstall_ctor(fifo); - if (ret) { - nvkm_error(subdev, "nonstall %d\n", ret); + if (fifo->func->nonstall) { + if (fifo->func->nonstall_ctor) { + ret = fifo->func->nonstall_ctor(fifo); + if (ret < 0) { + nvkm_error(subdev, "nonstall %d\n", ret); + return ret; + } + } else { + ret = 1; } + + ret = nvkm_event_init(fifo->func->nonstall, &fifo->engine.subdev, 1, ret, + &fifo->nonstall.event); + if (ret) + return ret; } /* Allocate USERD + BAR1 polling area. */ @@ -358,7 +368,6 @@ nvkm_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { struct nvkm_fifo *fifo; - int ret; if (!(fifo = *pfifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) return -ENOMEM; @@ -374,16 +383,5 @@ nvkm_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, spin_lock_init(&fifo->lock); mutex_init(&fifo->mutex); - ret = nvkm_engine_ctor(&nvkm_fifo, device, type, inst, true, &fifo->engine); - if (ret) - return ret; - - if (func->nonstall) { - ret = nvkm_event_init(func->nonstall, &fifo->engine.subdev, 1, 1, - &fifo->nonstall.event); - if (ret) - return ret; - } - - return 0; + return nvkm_engine_ctor(&nvkm_fifo, device, type, inst, true, &fifo->engine); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c index 12a5d99d5e77..c56d2a839efb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c @@ -32,9 +32,6 @@ #include <nvif/class.h> -/*TODO: allocate? */ -#define GA100_FIFO_NONSTALL_VECTOR 0 - static u32 ga100_chan_doorbell_handle(struct nvkm_chan *chan) { @@ -83,7 +80,7 @@ ga100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, nvkm_wo32(chan->inst, 0x0e4, priv ? 0x00000020 : 0x00000000); nvkm_wo32(chan->inst, 0x0e8, chan->id); nvkm_wo32(chan->inst, 0x0f4, 0x00001000 | (priv ? 0x00000100 : 0x00000000)); - nvkm_wo32(chan->inst, 0x0f8, 0x80000000 | GA100_FIFO_NONSTALL_VECTOR); + nvkm_wo32(chan->inst, 0x0f8, 0x80000000 | chan->cgrp->runl->nonstall.vector); nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000); nvkm_done(chan->inst); return 0; @@ -148,8 +145,20 @@ ga100_engn_cxid(struct nvkm_engn *engn, bool *cgid) return -ENODEV; } +static int +ga100_engn_nonstall(struct nvkm_engn *engn) +{ + struct nvkm_engine *engine = engn->engine; + + if (WARN_ON(!engine->func->nonstall)) + return -EINVAL; + + return engine->func->nonstall(engine); +} + const struct nvkm_engn_func ga100_engn = { + .nonstall = ga100_engn_nonstall, .cxid = ga100_engn_cxid, .ctor = gk104_ectx_ctor, .bind = gv100_ectx_bind, @@ -157,6 +166,7 @@ ga100_engn = { const struct nvkm_engn_func ga100_engn_ce = { + .nonstall = ga100_engn_nonstall, .cxid = ga100_engn_cxid, .ctor = gv100_ectx_ce_ctor, .bind = gv100_ectx_ce_bind, @@ -429,7 +439,9 @@ static int ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prunl) { struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_top_device *tdev; struct nvkm_runl *runl; + struct nvkm_engn *engn; u32 chcfg = nvkm_rd32(device, addr + 0x004); u32 chnum = 1 << (chcfg & 0x0000000f); u32 chaddr = (chcfg & 0xfffffff0); @@ -437,26 +449,55 @@ ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prun u32 vector = nvkm_rd32(device, addr + 0x160); int i, ret; - runl = *prunl = nvkm_runl_new(fifo, id, addr, chnum); + runl = nvkm_runl_new(fifo, id, addr, chnum); if (IS_ERR(runl)) return PTR_ERR(runl); + *prunl = runl; + for (i = 0; i < 2; i++) { u32 pbcfg = nvkm_rd32(device, addr + 0x010 + (i * 0x04)); if (pbcfg & 0x80000000) { runl->runq[runl->runq_nr] = nvkm_runq_new(fifo, ((pbcfg & 0x03fffc00) - 0x040000) / 0x800); - if (!runl->runq[runl->runq_nr]) + if (!runl->runq[runl->runq_nr]) { + RUNL_ERROR(runl, "runq %d", runl->runq_nr); return -ENOMEM; + } runl->runq_nr++; } } + nvkm_list_foreach(tdev, &device->top->device, head, tdev->runlist == runl->addr) { + if (tdev->engine < 0) { + RUNL_DEBUG(runl, "engn !top"); + return -EINVAL; + } + + engn = nvkm_runl_add(runl, tdev->engine, (tdev->type == NVKM_ENGINE_CE) ? + fifo->func->engn_ce : fifo->func->engn, + tdev->type, tdev->inst); + if (!engn) + return -EINVAL; + + if (!engn->engine->func->nonstall) { + RUNL_DEBUG(runl, "engn %s !nonstall", engn->engine->subdev.name); + return -EINVAL; + } + } + + if (list_empty(&runl->engns)) { + RUNL_DEBUG(runl, "!engns"); + return -EINVAL; + } + ret = nvkm_inth_add(&device->vfn->intr, vector & 0x00000fff, NVKM_INTR_PRIO_NORMAL, &fifo->engine.subdev, ga100_runl_intr, &runl->inth); - if (ret) + if (ret) { + RUNL_ERROR(runl, "inth %d", ret); return ret; + } runl->chan = chaddr; runl->doorbell = dbcfg >> 16; @@ -466,9 +507,9 @@ ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prun static irqreturn_t ga100_fifo_nonstall_intr(struct nvkm_inth *inth) { - struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), nonstall.intr); + struct nvkm_runl *runl = container_of(inth, typeof(*runl), nonstall.inth); - nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT); + nvkm_event_ntfy(&runl->fifo->nonstall.event, runl->id, NVKM_FIFO_NONSTALL_EVENT); return IRQ_HANDLED; } @@ -476,16 +517,18 @@ static void ga100_fifo_nonstall_block(struct nvkm_event *event, int type, int index) { struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + struct nvkm_runl *runl = nvkm_runl_get(fifo, index, 0); - nvkm_inth_block(&fifo->nonstall.intr); + nvkm_inth_block(&runl->nonstall.inth); } static void ga100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index) { struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + struct nvkm_runl *runl = nvkm_runl_get(fifo, index, 0); - nvkm_inth_allow(&fifo->nonstall.intr); + nvkm_inth_allow(&runl->nonstall.inth); } const struct nvkm_event_func @@ -497,9 +540,29 @@ ga100_fifo_nonstall = { int ga100_fifo_nonstall_ctor(struct nvkm_fifo *fifo) { - return nvkm_inth_add(&fifo->engine.subdev.device->vfn->intr, GA100_FIFO_NONSTALL_VECTOR, - NVKM_INTR_PRIO_NORMAL, &fifo->engine.subdev, ga100_fifo_nonstall_intr, - &fifo->nonstall.intr); + struct nvkm_subdev *subdev = &fifo->engine.subdev; + struct nvkm_vfn *vfn = subdev->device->vfn; + struct nvkm_runl *runl; + int ret, nr = 0; + + nvkm_runl_foreach(runl, fifo) { + struct nvkm_engn *engn = list_first_entry(&runl->engns, typeof(*engn), head); + + runl->nonstall.vector = engn->func->nonstall(engn); + if (runl->nonstall.vector < 0) { + RUNL_ERROR(runl, "nonstall %d", runl->nonstall.vector); + return runl->nonstall.vector; + } + + ret = nvkm_inth_add(&vfn->intr, runl->nonstall.vector, NVKM_INTR_PRIO_NORMAL, + subdev, ga100_fifo_nonstall_intr, &runl->nonstall.inth); + if (ret) + return ret; + + nr = max(nr, runl->id + 1); + } + + return nr; } int @@ -514,15 +577,13 @@ ga100_fifo_runl_ctor(struct nvkm_fifo *fifo) runl = nvkm_runl_get(fifo, -1, tdev->runlist); if (!runl) { ret = ga100_runl_new(fifo, id++, tdev->runlist, &runl); - if (ret) - return ret; - } - - if (tdev->engine < 0) - continue; + if (ret) { + if (runl) + nvkm_runl_del(runl); - nvkm_runl_add(runl, tdev->engine, (tdev->type == NVKM_ENGINE_CE) ? - fifo->func->engn_ce : fifo->func->engn, tdev->type, tdev->inst); + continue; + } + } } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 93d628d7d508..454a481a0aef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -399,7 +399,7 @@ nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr) int ret; if (!(runl = kzalloc(sizeof(*runl), GFP_KERNEL))) - return NULL; + return ERR_PTR(-ENOMEM); runl->func = fifo->func->runl; runl->fifo = fifo; @@ -419,7 +419,7 @@ nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr) (ret = nvkm_chid_new(&nvkm_chan_event, subdev, id_nr, 0, id_nr, &runl->chid))) { RUNL_ERROR(runl, "cgid/chid: %d", ret); nvkm_runl_del(runl); - return NULL; + return ERR_PTR(ret); } } else { runl->cgid = nvkm_chid_ref(fifo->cgid); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index c93d21bb7bd5..5421321f8e85 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -11,6 +11,7 @@ enum nvkm_subdev_type; struct nvkm_engn { const struct nvkm_engn_func { + int (*nonstall)(struct nvkm_engn *); bool (*chsw)(struct nvkm_engn *); int (*cxid)(struct nvkm_engn *, bool *cgid); void (*mmu_fault_trigger)(struct nvkm_engn *); @@ -69,6 +70,11 @@ struct nvkm_runl { struct nvkm_inth inth; + struct { + int vector; + struct nvkm_inth inth; + } nonstall; + struct list_head cgrps; int cgrp_nr; int chan_nr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 1dac95ae7b43..04140e0110be 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -52,7 +52,7 @@ nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ switch (args->v0.type) { case NVIF_CHAN_EVENT_V0_NON_STALL_INTR: - return nvkm_uevent_add(uevent, &runl->fifo->nonstall.event, 0, + return nvkm_uevent_add(uevent, &runl->fifo->nonstall.event, runl->id, NVKM_FIFO_NONSTALL_EVENT, NULL); case NVIF_CHAN_EVENT_V0_KILLED: return nvkm_uevent_add(uevent, &runl->chid->event, chan->id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c index 71b824e6da9d..0096ad401b15 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c @@ -109,8 +109,7 @@ nvkm_gr_oclass_get(struct nvkm_oclass *oclass, int index) } static int -nvkm_gr_cclass_new(struct nvkm_fifo_chan *chan, - const struct nvkm_oclass *oclass, +nvkm_gr_cclass_new(struct nvkm_chan *chan, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nvkm_gr *gr = nvkm_gr(oclass->engine); @@ -127,6 +126,17 @@ nvkm_gr_intr(struct nvkm_engine *engine) } static int +nvkm_gr_nonstall(struct nvkm_engine *engine) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + + if (gr->func->nonstall) + return gr->func->nonstall(gr); + + return -EINVAL; +} + +static int nvkm_gr_oneinit(struct nvkm_engine *engine) { struct nvkm_gr *gr = nvkm_gr(engine); @@ -178,6 +188,7 @@ nvkm_gr = { .init = nvkm_gr_init, .fini = nvkm_gr_fini, .reset = nvkm_gr_reset, + .nonstall = nvkm_gr_nonstall, .intr = nvkm_gr_intr, .tile = nvkm_gr_tile, .chsw_load = nvkm_gr_chsw_load, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c index a5b5ac2755a2..00cd70abad67 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c @@ -137,8 +137,15 @@ ga102_gr_oneinit_intr(struct gf100_gr *gr, enum nvkm_intr_type *pvector) return &device->vfn->intr; } +static int +ga102_gr_nonstall(struct gf100_gr *gr) +{ + return nvkm_rd32(gr->base.engine.subdev.device, 0x400160) & 0x00000fff; +} + static const struct gf100_gr_func ga102_gr = { + .nonstall = ga102_gr_nonstall, .oneinit_intr = ga102_gr_oneinit_intr, .oneinit_tiles = gm200_gr_oneinit_tiles, .oneinit_sm_id = gv100_gr_oneinit_sm_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 5f20079c3660..3648868bb9fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -374,7 +374,7 @@ gf100_gr_chan = { }; static int -gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { @@ -2494,12 +2494,24 @@ gf100_gr_gpccs_ucode = { .data.size = sizeof(gf100_grgpc_data), }; +static int +gf100_gr_nonstall(struct nvkm_gr *base) +{ + struct gf100_gr *gr = gf100_gr(base); + + if (gr->func->nonstall) + return gr->func->nonstall(gr); + + return -EINVAL; +} + static const struct nvkm_gr_func gf100_gr_ = { .dtor = gf100_gr_dtor, .oneinit = gf100_gr_oneinit, .init = gf100_gr_init_, .fini = gf100_gr_fini, + .nonstall = gf100_gr_nonstall, .reset = gf100_gr_reset, .units = gf100_gr_units, .chan_new = gf100_gr_chan_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 94ca7ac16acf..54f686ba39ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -147,6 +147,7 @@ struct gf100_gr_func_zbc { }; struct gf100_gr_func { + int (*nonstall)(struct gf100_gr *); struct nvkm_intr *(*oneinit_intr)(struct gf100_gr *, enum nvkm_intr_type *); void (*oneinit_tiles)(struct gf100_gr *); int (*oneinit_sm_id)(struct gf100_gr *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c index 81bd682c2102..ca822f07b63e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c @@ -1181,7 +1181,7 @@ nv04_gr_chan = { }; static int -nv04_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv04_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv04_gr *gr = nv04_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c index 7fe6e58f6bab..92ef7c9b2910 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c @@ -999,7 +999,7 @@ nv10_gr_chan = { } while (0) int -nv10_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv10_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv10_gr *gr = nv10_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h index 5cfe927c9123..b86090c08060 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h @@ -9,6 +9,6 @@ int nv10_gr_init(struct nvkm_gr *); void nv10_gr_intr(struct nvkm_gr *); void nv10_gr_tile(struct nvkm_gr *, int, struct nvkm_fb_tile *); -int nv10_gr_chan_new(struct nvkm_gr *, struct nvkm_fifo_chan *, +int nv10_gr_chan_new(struct nvkm_gr *, struct nvkm_chan *, const struct nvkm_oclass *, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c index 75434f5de7ad..02a8c62a0a32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c @@ -72,7 +72,7 @@ nv20_gr_chan = { }; static int -nv20_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv20_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv20_gr *gr = nv20_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c index 94685e4d4f87..d6bc6904dcc8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c @@ -18,7 +18,7 @@ nv25_gr_chan = { }; static int -nv25_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv25_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv20_gr *gr = nv20_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c index 2d6273675291..e5a351b51eb9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c @@ -18,7 +18,7 @@ nv2a_gr_chan = { }; static int -nv2a_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv2a_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv20_gr *gr = nv20_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c index 647bd6fede04..80370323755e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c @@ -19,7 +19,7 @@ nv30_gr_chan = { }; static int -nv30_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv30_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv20_gr *gr = nv20_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c index 2eae3fe4ef4e..cdf043bbdd59 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c @@ -18,7 +18,7 @@ nv34_gr_chan = { }; static int -nv34_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv34_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv20_gr *gr = nv20_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c index 657d7cdba369..fa5a6ccb871d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c @@ -18,7 +18,7 @@ nv35_gr_chan = { }; static int -nv35_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv35_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv20_gr *gr = nv20_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c index d2df097a6cf6..a5e1f02791b4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c @@ -145,7 +145,7 @@ nv40_gr_chan = { }; int -nv40_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv40_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv40_gr *gr = nv40_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h index f3d3d3a5ae5b..84fbc99139e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h @@ -22,12 +22,12 @@ u64 nv40_gr_units(struct nvkm_gr *); struct nv40_gr_chan { struct nvkm_object object; struct nv40_gr *gr; - struct nvkm_fifo_chan *fifo; + struct nvkm_chan *fifo; u32 inst; struct list_head head; }; -int nv40_gr_chan_new(struct nvkm_gr *, struct nvkm_fifo_chan *, +int nv40_gr_chan_new(struct nvkm_gr *, struct nvkm_chan *, const struct nvkm_oclass *, struct nvkm_object **); extern const struct nvkm_object_func nv40_gr_object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c index 1ba18a8e380f..c8a0288c092d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c @@ -86,7 +86,7 @@ nv50_gr_chan = { }; int -nv50_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, +nv50_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv50_gr *gr = nv50_gr(base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h index 84388c42e5c6..97ead0042357 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h @@ -27,7 +27,7 @@ struct nv50_gr_chan { struct nv50_gr *gr; }; -int nv50_gr_chan_new(struct nvkm_gr *, struct nvkm_fifo_chan *, +int nv50_gr_chan_new(struct nvkm_gr *, struct nvkm_chan *, const struct nvkm_oclass *, struct nvkm_object **); extern const struct nvkm_object_func nv50_gr_object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h index 08d5c96e6458..0884abc73a9d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h @@ -5,7 +5,7 @@ #include <engine/gr.h> #include <core/enum.h> struct nvkm_fb_tile; -struct nvkm_fifo_chan; +struct nvkm_chan; int nvkm_gr_ctor(const struct nvkm_gr_func *, struct nvkm_device *, enum nvkm_subdev_type, int, bool enable, struct nvkm_gr *); @@ -18,10 +18,11 @@ struct nvkm_gr_func { int (*init)(struct nvkm_gr *); int (*fini)(struct nvkm_gr *, bool); int (*reset)(struct nvkm_gr *); + int (*nonstall)(struct nvkm_gr *); void (*intr)(struct nvkm_gr *); void (*tile)(struct nvkm_gr *, int region, struct nvkm_fb_tile *); int (*tlb_flush)(struct nvkm_gr *); - int (*chan_new)(struct nvkm_gr *, struct nvkm_fifo_chan *, + int (*chan_new)(struct nvkm_gr *, struct nvkm_chan *, const struct nvkm_oclass *, struct nvkm_object **); int (*object_get)(struct nvkm_gr *, int, struct nvkm_sclass *); /* Returns chipset-specific counts of units packed into an u64. diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c index cb0c3991b2ad..db9fc1ecae0d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c @@ -81,8 +81,7 @@ nv31_mpeg_chan = { }; int -nv31_mpeg_chan_new(struct nvkm_fifo_chan *fifoch, - const struct nvkm_oclass *oclass, +nv31_mpeg_chan_new(struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv31_mpeg *mpeg = nv31_mpeg(oclass->engine); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h index 9f30aaaf809e..251d659565de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h @@ -24,9 +24,9 @@ struct nv31_mpeg_func { struct nv31_mpeg_chan { struct nvkm_object object; struct nv31_mpeg *mpeg; - struct nvkm_fifo_chan *fifo; + struct nvkm_chan *fifo; }; -int nv31_mpeg_chan_new(struct nvkm_fifo_chan *, const struct nvkm_oclass *, +int nv31_mpeg_chan_new(struct nvkm_chan *, const struct nvkm_oclass *, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c index 0890a279458e..4b1374adbda3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c @@ -43,7 +43,7 @@ struct nv44_mpeg { struct nv44_mpeg_chan { struct nvkm_object object; struct nv44_mpeg *mpeg; - struct nvkm_fifo_chan *fifo; + struct nvkm_chan *fifo; struct list_head head; u32 inst; }; @@ -100,8 +100,7 @@ nv44_mpeg_chan = { }; static int -nv44_mpeg_chan_new(struct nvkm_fifo_chan *fifoch, - const struct nvkm_oclass *oclass, +nv44_mpeg_chan_new(struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv44_mpeg *mpeg = nv44_mpeg(oclass->engine); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h index 667a2d05dd89..044ff4133874 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h @@ -2,7 +2,7 @@ #ifndef __NVKM_MPEG_PRIV_H__ #define __NVKM_MPEG_PRIV_H__ #include <engine/mpeg.h> -struct nvkm_fifo_chan; +struct nvkm_chan; int nv31_mpeg_init(struct nvkm_engine *); void nv31_mpeg_tile(struct nvkm_engine *, int, struct nvkm_fb_tile *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c index a9d464db6974..20220d6d4a13 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c @@ -74,8 +74,7 @@ nvkm_sw_oclass_get(struct nvkm_oclass *oclass, int index) } static int -nvkm_sw_cclass_get(struct nvkm_fifo_chan *fifoch, - const struct nvkm_oclass *oclass, +nvkm_sw_cclass_get(struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nvkm_sw *sw = nvkm_sw(oclass->engine); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c index 834b8cbed51d..2bf45141de60 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c @@ -74,7 +74,7 @@ nvkm_sw_chan = { int nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *func, struct nvkm_sw *sw, - struct nvkm_fifo_chan *fifo, const struct nvkm_oclass *oclass, + struct nvkm_chan *fifo, const struct nvkm_oclass *oclass, struct nvkm_sw_chan *chan) { unsigned long flags; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h index 67b2e5ea93d9..c313aea16a17 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h @@ -11,7 +11,7 @@ struct nvkm_sw_chan { const struct nvkm_sw_chan_func *func; struct nvkm_object object; struct nvkm_sw *sw; - struct nvkm_fifo_chan *fifo; + struct nvkm_chan *fifo; struct list_head head; #define NVKM_SW_CHAN_EVENT_PAGE_FLIP BIT(0) @@ -24,7 +24,7 @@ struct nvkm_sw_chan_func { }; int nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *, struct nvkm_sw *, - struct nvkm_fifo_chan *, const struct nvkm_oclass *, + struct nvkm_chan *, const struct nvkm_oclass *, struct nvkm_sw_chan *); bool nvkm_sw_chan_mthd(struct nvkm_sw_chan *, int subc, u32 mthd, u32 data); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c index c3cf6f2ff86c..a0273baf4c67 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c @@ -102,7 +102,7 @@ gf100_sw_chan = { }; static int -gf100_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch, +gf100_sw_chan_new(struct nvkm_sw *sw, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c index 4aa57573869c..8a1d112da894 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c @@ -106,7 +106,7 @@ nv04_sw_chan = { }; static int -nv04_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifo, +nv04_sw_chan_new(struct nvkm_sw *sw, struct nvkm_chan *fifo, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv04_sw_chan *chan; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c index e79e640ae535..742c75859569 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c @@ -36,7 +36,7 @@ nv10_sw_chan = { }; static int -nv10_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifo, +nv10_sw_chan_new(struct nvkm_sw *sw, struct nvkm_chan *fifo, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nvkm_sw_chan *chan; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c index 9d7a9b7d5be3..99476d32c5af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c @@ -99,7 +99,7 @@ nv50_sw_chan = { }; static int -nv50_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch, +nv50_sw_chan_new(struct nvkm_sw *sw, struct nvkm_chan *fifoch, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nvkm_disp *disp = sw->engine.subdev.device->disp; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h index d9d83b1b8849..8015afaba947 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h @@ -15,7 +15,7 @@ struct nvkm_sw_chan_sclass { }; struct nvkm_sw_func { - int (*chan_new)(struct nvkm_sw *, struct nvkm_fifo_chan *, + int (*chan_new)(struct nvkm_sw *, struct nvkm_chan *, const struct nvkm_oclass *, struct nvkm_object **); const struct nvkm_sw_chan_sclass sclass[]; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild index 6ba5120a2ebe..394c305e759a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild @@ -55,7 +55,7 @@ nvkm-y += nvkm/subdev/fb/ramgk104.o nvkm-y += nvkm/subdev/fb/ramgm107.o nvkm-y += nvkm/subdev/fb/ramgm200.o nvkm-y += nvkm/subdev/fb/ramgp100.o -nvkm-y += nvkm/subdev/fb/ramga102.o +nvkm-y += nvkm/subdev/fb/ramgp102.o nvkm-y += nvkm/subdev/fb/sddr2.o nvkm-y += nvkm/subdev/fb/sddr3.o nvkm-y += nvkm/subdev/fb/gddr3.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index 0955340cc421..8a286a9349ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -174,6 +174,18 @@ nvkm_fb_mem_unlock(struct nvkm_fb *fb) return 0; } +u64 +nvkm_fb_vidmem_size(struct nvkm_device *device) +{ + struct nvkm_fb *fb = device->fb; + + if (fb && fb->func->vidmem.size) + return fb->func->vidmem.size(fb); + + WARN_ON(1); + return 0; +} + static int nvkm_fb_init(struct nvkm_subdev *subdev) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c index a7456e786463..12037fd4fdf2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c @@ -30,7 +30,8 @@ ga100_fb = { .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, - .ram_new = gp100_ram_new, + .vidmem.size = gp102_fb_vidmem_size, + .ram_new = gp102_ram_new, .default_bigpage = 16, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c index dd476e079fe1..76f6877b54c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c @@ -24,6 +24,12 @@ #include <engine/nvdec.h> +static u64 +ga102_fb_vidmem_size(struct nvkm_fb *fb) +{ + return (u64)nvkm_rd32(fb->subdev.device, 0x1183a4) << 20; +} + static int ga102_fb_oneinit(struct nvkm_fb *fb) { @@ -43,7 +49,8 @@ ga102_fb = { .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, - .ram_new = ga102_ram_new, + .vidmem.size = ga102_fb_vidmem_size, + .ram_new = gp102_ram_new, .default_bigpage = 16, .vpr.scrub_required = tu102_fb_vpr_scrub_required, .vpr.scrub = gp102_fb_vpr_scrub, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index 14d942e8b857..534553c64805 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -40,6 +40,20 @@ gp102_fb_vpr_scrub_required(struct nvkm_fb *fb) return (nvkm_rd32(device, 0x100cd0) & 0x00000010) != 0; } +u64 +gp102_fb_vidmem_size(struct nvkm_fb *fb) +{ + const u32 data = nvkm_rd32(fb->subdev.device, 0x100ce0); + const u32 lmag = (data & 0x000003f0) >> 4; + const u32 lsca = (data & 0x0000000f); + const u64 size = (u64)lmag << (lsca + 20); + + if (data & 0x40000000) + return size / 16 * 15; + + return size; +} + int gp102_fb_oneinit(struct nvkm_fb *fb) { @@ -59,9 +73,10 @@ gp102_fb = { .init_remapper = gp100_fb_init_remapper, .init_page = gm200_fb_init_page, .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, + .vidmem.size = gp102_fb_vidmem_size, .vpr.scrub_required = gp102_fb_vpr_scrub_required, .vpr.scrub = gp102_fb_vpr_scrub, - .ram_new = gp100_ram_new, + .ram_new = gp102_ram_new, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c index 4d8a286a7a34..f422564bee5b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c @@ -36,9 +36,10 @@ gv100_fb = { .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, + .vidmem.size = gp102_fb_vidmem_size, .vpr.scrub_required = gp102_fb_vpr_scrub_required, .vpr.scrub = gp102_fb_vpr_scrub, - .ram_new = gp100_ram_new, + .ram_new = gp102_ram_new, .default_bigpage = 16, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index 726c30c8bf95..77d6a8c10829 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -20,6 +20,10 @@ struct nvkm_fb_func { void (*flush_page_init)(struct nvkm_fb *); } sysmem; + struct nvkm_fb_func_vidmem { + u64 (*size)(struct nvkm_fb *); + } vidmem; + struct { bool (*scrub_required)(struct nvkm_fb *); int (*scrub)(struct nvkm_fb *); @@ -84,6 +88,7 @@ void gp100_fb_init_remapper(struct nvkm_fb *); void gp100_fb_init_unkn(struct nvkm_fb *); int gp102_fb_oneinit(struct nvkm_fb *); +u64 gp102_fb_vidmem_size(struct nvkm_fb *); bool gp102_fb_vpr_scrub_required(struct nvkm_fb *); int gp102_fb_vpr_scrub(struct nvkm_fb *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h index ea7d66f3dd82..50f0c1914f58 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h @@ -70,5 +70,5 @@ int gk104_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gm107_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gm200_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gp100_ram_new(struct nvkm_fb *, struct nvkm_ram **); -int ga102_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int gp102_ram_new(struct nvkm_fb *, struct nvkm_ram **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramga102.c deleted file mode 100644 index 298c136cefe0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramga102.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ram.h" - -#include <subdev/bios.h> -#include <subdev/bios/init.h> -#include <subdev/bios/rammap.h> - -static const struct nvkm_ram_func -ga102_ram = { -}; - -int -ga102_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) -{ - struct nvkm_device *device = fb->subdev.device; - enum nvkm_ram_type type = nvkm_fb_bios_memtype(device->bios); - u32 size = nvkm_rd32(device, 0x1183a4); - - return nvkm_ram_new_(&ga102_ram, fb, type, (u64)size << 20, pram); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.c new file mode 100644 index 000000000000..8550f5e47347 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +#include "ram.h" + +#include <subdev/bios.h> + +static const struct nvkm_ram_func +gp102_ram = { +}; + +int +gp102_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + enum nvkm_ram_type type = nvkm_fb_bios_memtype(fb->subdev.device->bios); + const u32 rsvd_head = ( 256 * 1024); /* vga memory */ + const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ + u64 size = fb->func->vidmem.size(fb); + int ret; + + ret = nvkm_ram_new_(&gp102_ram, fb, type, size, pram); + if (ret) + return ret; + + nvkm_mm_fini(&(*pram)->vram); + + return nvkm_mm_init(&(*pram)->vram, NVKM_RAM_MM_NORMAL, + rsvd_head >> NVKM_RAM_MM_SHIFT, + (size - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, + 1); + +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c index b8803c124c3b..bcc23d4c8115 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c @@ -36,9 +36,10 @@ tu102_fb = { .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, + .vidmem.size = gp102_fb_vidmem_size, .vpr.scrub_required = tu102_fb_vpr_scrub_required, .vpr.scrub = gp102_fb_vpr_scrub, - .ram_new = gp100_ram_new, + .ram_new = gp102_ram_new, .default_bigpage = 16, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c index 524cd3c0e3fe..8e459d88ff8f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c @@ -58,10 +58,13 @@ nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; + if (nvkm_vmm_in_managed_range(vmm, addr, size) && vmm->managed.raw) + return -EINVAL; + if (size) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_pfn_unmap(vmm, addr, size); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } return ret; @@ -88,10 +91,13 @@ nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; + if (nvkm_vmm_in_managed_range(vmm, addr, size) && vmm->managed.raw) + return -EINVAL; + if (size) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_pfn_map(vmm, page, addr, size, phys); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } return ret; @@ -113,7 +119,10 @@ nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; - mutex_lock(&vmm->mutex); + if (nvkm_vmm_in_managed_range(vmm, addr, 0) && vmm->managed.raw) + return -EINVAL; + + mutex_lock(&vmm->mutex.vmm); vma = nvkm_vmm_node_search(vmm, addr); if (ret = -ENOENT, !vma || vma->addr != addr) { VMM_DEBUG(vmm, "lookup %016llx: %016llx", @@ -134,7 +143,7 @@ nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) nvkm_vmm_unmap_locked(vmm, vma, false); ret = 0; done: - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); return ret; } @@ -159,13 +168,16 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; + if (nvkm_vmm_in_managed_range(vmm, addr, size) && vmm->managed.raw) + return -EINVAL; + memory = nvkm_umem_search(client, handle); if (IS_ERR(memory)) { VMM_DEBUG(vmm, "memory %016llx %ld\n", handle, PTR_ERR(memory)); return PTR_ERR(memory); } - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); if (ret = -ENOENT, !(vma = nvkm_vmm_node_search(vmm, addr))) { VMM_DEBUG(vmm, "lookup %016llx", addr); goto fail; @@ -198,7 +210,7 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } } vma->busy = true; - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); ret = nvkm_memory_map(memory, offset, vmm, vma, argv, argc); if (ret == 0) { @@ -207,11 +219,11 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) return 0; } - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); vma->busy = false; nvkm_vmm_unmap_region(vmm, vma); fail: - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); nvkm_memory_unref(&memory); return ret; } @@ -232,7 +244,7 @@ nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); vma = nvkm_vmm_node_search(vmm, args->v0.addr); if (ret = -ENOENT, !vma || vma->addr != addr || vma->part) { VMM_DEBUG(vmm, "lookup %016llx: %016llx %d", addr, @@ -248,7 +260,7 @@ nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc) nvkm_vmm_put_locked(vmm, vma); ret = 0; done: - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); return ret; } @@ -275,10 +287,10 @@ nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_get_locked(vmm, getref, mapref, sparse, page, align, size, &vma); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); if (ret) return ret; @@ -314,6 +326,168 @@ nvkm_uvmm_mthd_page(struct nvkm_uvmm *uvmm, void *argv, u32 argc) return 0; } +static inline int +nvkm_uvmm_page_index(struct nvkm_uvmm *uvmm, u64 size, u8 shift, u8 *refd) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + const struct nvkm_vmm_page *page; + + if (likely(shift)) { + for (page = vmm->func->page; page->shift; page++) { + if (shift == page->shift) + break; + } + + if (!page->shift || !IS_ALIGNED(size, 1ULL << page->shift)) { + VMM_DEBUG(vmm, "page %d %016llx", shift, size); + return -EINVAL; + } + } else { + return -EINVAL; + } + *refd = page - vmm->func->page; + + return 0; +} + +static int +nvkm_uvmm_mthd_raw_get(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + return nvkm_vmm_raw_get(vmm, args->addr, args->size, refd); +} + +static int +nvkm_uvmm_mthd_raw_put(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + nvkm_vmm_raw_put(vmm, args->addr, args->size, refd); + + return 0; +} + +static int +nvkm_uvmm_mthd_raw_map(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_client *client = uvmm->object.client; + struct nvkm_vmm *vmm = uvmm->vmm; + struct nvkm_vma vma = { + .addr = args->addr, + .size = args->size, + .used = true, + .mapref = false, + .no_comp = true, + }; + struct nvkm_memory *memory; + void *argv = (void *)(uintptr_t)args->argv; + unsigned int argc = args->argc; + u64 handle = args->memory; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + vma.page = vma.refd = refd; + + memory = nvkm_umem_search(client, args->memory); + if (IS_ERR(memory)) { + VMM_DEBUG(vmm, "memory %016llx %ld\n", handle, PTR_ERR(memory)); + return PTR_ERR(memory); + } + + ret = nvkm_memory_map(memory, args->offset, vmm, &vma, argv, argc); + + nvkm_memory_unref(&vma.memory); + nvkm_memory_unref(&memory); + return ret; +} + +static int +nvkm_uvmm_mthd_raw_unmap(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + nvkm_vmm_raw_unmap(vmm, args->addr, args->size, + args->sparse, refd); + + return 0; +} + +static int +nvkm_uvmm_mthd_raw_sparse(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + return nvkm_vmm_raw_sparse(vmm, args->addr, args->size, args->ref); +} + +static int +nvkm_uvmm_mthd_raw(struct nvkm_uvmm *uvmm, void *argv, u32 argc) +{ + union { + struct nvif_vmm_raw_v0 v0; + } *args = argv; + int ret = -ENOSYS; + + if (!uvmm->vmm->managed.raw) + return -EINVAL; + + if ((ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) + return ret; + + switch (args->v0.op) { + case NVIF_VMM_RAW_V0_GET: + return nvkm_uvmm_mthd_raw_get(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_PUT: + return nvkm_uvmm_mthd_raw_put(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_MAP: + return nvkm_uvmm_mthd_raw_map(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_UNMAP: + return nvkm_uvmm_mthd_raw_unmap(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_SPARSE: + return nvkm_uvmm_mthd_raw_sparse(uvmm, &args->v0); + default: + return -EINVAL; + }; +} + static int nvkm_uvmm_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) { @@ -326,6 +500,7 @@ nvkm_uvmm_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) case NVIF_VMM_V0_UNMAP : return nvkm_uvmm_mthd_unmap (uvmm, argv, argc); case NVIF_VMM_V0_PFNMAP: return nvkm_uvmm_mthd_pfnmap(uvmm, argv, argc); case NVIF_VMM_V0_PFNCLR: return nvkm_uvmm_mthd_pfnclr(uvmm, argv, argc); + case NVIF_VMM_V0_RAW : return nvkm_uvmm_mthd_raw (uvmm, argv, argc); case NVIF_VMM_V0_MTHD(0x00) ... NVIF_VMM_V0_MTHD(0x7f): if (uvmm->vmm->func->mthd) { return uvmm->vmm->func->mthd(uvmm->vmm, @@ -366,10 +541,11 @@ nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_uvmm *uvmm; int ret = -ENOSYS; u64 addr, size; - bool managed; + bool managed, raw; if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, more))) { - managed = args->v0.managed != 0; + managed = args->v0.type == NVIF_VMM_V0_TYPE_MANAGED; + raw = args->v0.type == NVIF_VMM_V0_TYPE_RAW; addr = args->v0.addr; size = args->v0.size; } else @@ -377,12 +553,13 @@ nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, if (!(uvmm = kzalloc(sizeof(*uvmm), GFP_KERNEL))) return -ENOMEM; + nvkm_object_ctor(&nvkm_uvmm, oclass, &uvmm->object); *pobject = &uvmm->object; if (!mmu->vmm) { - ret = mmu->func->vmm.ctor(mmu, managed, addr, size, argv, argc, - NULL, "user", &uvmm->vmm); + ret = mmu->func->vmm.ctor(mmu, managed || raw, addr, size, + argv, argc, NULL, "user", &uvmm->vmm); if (ret) return ret; @@ -393,6 +570,7 @@ nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, uvmm->vmm = nvkm_vmm_ref(mmu->vmm); } + uvmm->vmm->managed.raw = raw; page = uvmm->vmm->func->page; args->v0.page_nr = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c index ae793f400ba1..eb5fcadcb39a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c @@ -677,40 +677,17 @@ nvkm_vmm_ptes_sparse(struct nvkm_vmm *vmm, u64 addr, u64 size, bool ref) } static void -nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, - u64 addr, u64 size, bool sparse, bool pfn) -{ - const struct nvkm_vmm_desc_func *func = page->desc->func; - nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref", - false, pfn, nvkm_vmm_unref_ptes, NULL, NULL, - sparse ? func->sparse : func->invalid ? func->invalid : - func->unmap); -} - -static int -nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, - u64 addr, u64 size, struct nvkm_vmm_map *map, - nvkm_vmm_pte_func func) -{ - u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true, - false, nvkm_vmm_ref_ptes, func, map, NULL); - if (fail != ~0ULL) { - if ((size = fail - addr)) - nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false, false); - return -ENOMEM; - } - return 0; -} - -static void nvkm_vmm_ptes_unmap(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, u64 addr, u64 size, bool sparse, bool pfn) { const struct nvkm_vmm_desc_func *func = page->desc->func; + + mutex_lock(&vmm->mutex.map); nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, pfn, NULL, NULL, NULL, sparse ? func->sparse : func->invalid ? func->invalid : func->unmap); + mutex_unlock(&vmm->mutex.map); } static void @@ -718,33 +695,108 @@ nvkm_vmm_ptes_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, u64 addr, u64 size, struct nvkm_vmm_map *map, nvkm_vmm_pte_func func) { + mutex_lock(&vmm->mutex.map); nvkm_vmm_iter(vmm, page, addr, size, "map", false, false, NULL, func, map, NULL); + mutex_unlock(&vmm->mutex.map); } static void -nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, - u64 addr, u64 size) +nvkm_vmm_ptes_put_locked(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) { nvkm_vmm_iter(vmm, page, addr, size, "unref", false, false, nvkm_vmm_unref_ptes, NULL, NULL, NULL); } +static void +nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) +{ + mutex_lock(&vmm->mutex.ref); + nvkm_vmm_ptes_put_locked(vmm, page, addr, size); + mutex_unlock(&vmm->mutex.ref); +} + static int nvkm_vmm_ptes_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, u64 addr, u64 size) { - u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, false, - nvkm_vmm_ref_ptes, NULL, NULL, NULL); + u64 fail; + + mutex_lock(&vmm->mutex.ref); + fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, false, + nvkm_vmm_ref_ptes, NULL, NULL, NULL); if (fail != ~0ULL) { if (fail != addr) - nvkm_vmm_ptes_put(vmm, page, addr, fail - addr); + nvkm_vmm_ptes_put_locked(vmm, page, addr, fail - addr); + mutex_unlock(&vmm->mutex.ref); + return -ENOMEM; + } + mutex_unlock(&vmm->mutex.ref); + return 0; +} + +static void +__nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, bool sparse, bool pfn) +{ + const struct nvkm_vmm_desc_func *func = page->desc->func; + + nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref", + false, pfn, nvkm_vmm_unref_ptes, NULL, NULL, + sparse ? func->sparse : func->invalid ? func->invalid : + func->unmap); +} + +static void +nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, bool sparse, bool pfn) +{ + if (vmm->managed.raw) { + nvkm_vmm_ptes_unmap(vmm, page, addr, size, sparse, pfn); + nvkm_vmm_ptes_put(vmm, page, addr, size); + } else { + __nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, sparse, pfn); + } +} + +static int +__nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, struct nvkm_vmm_map *map, + nvkm_vmm_pte_func func) +{ + u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true, + false, nvkm_vmm_ref_ptes, func, map, NULL); + if (fail != ~0ULL) { + if ((size = fail - addr)) + nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false, false); return -ENOMEM; } return 0; } -static inline struct nvkm_vma * +static int +nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, struct nvkm_vmm_map *map, + nvkm_vmm_pte_func func) +{ + int ret; + + if (vmm->managed.raw) { + ret = nvkm_vmm_ptes_get(vmm, page, addr, size); + if (ret) + return ret; + + nvkm_vmm_ptes_map(vmm, page, addr, size, map, func); + + return 0; + } else { + return __nvkm_vmm_ptes_get_map(vmm, page, addr, size, map, func); + } +} + +struct nvkm_vma * nvkm_vma_new(u64 addr, u64 size) { struct nvkm_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); @@ -1045,7 +1097,9 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, vmm->debug = mmu->subdev.debug; kref_init(&vmm->kref); - __mutex_init(&vmm->mutex, "&vmm->mutex", key ? key : &_key); + __mutex_init(&vmm->mutex.vmm, "&vmm->mutex.vmm", key ? key : &_key); + mutex_init(&vmm->mutex.ref); + mutex_init(&vmm->mutex.map); /* Locate the smallest page size supported by the backend, it will * have the deepest nesting of page tables. @@ -1101,6 +1155,9 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, if (addr && (ret = nvkm_vmm_ctor_managed(vmm, 0, addr))) return ret; + vmm->managed.p.addr = 0; + vmm->managed.p.size = addr; + /* NVKM-managed area. */ if (size) { if (!(vma = nvkm_vma_new(addr, size))) @@ -1114,6 +1171,9 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, size = vmm->limit - addr; if (size && (ret = nvkm_vmm_ctor_managed(vmm, addr, size))) return ret; + + vmm->managed.n.addr = addr; + vmm->managed.n.size = size; } else { /* Address-space fully managed by NVKM, requiring calls to * nvkm_vmm_get()/nvkm_vmm_put() to allocate address-space. @@ -1362,9 +1422,9 @@ void nvkm_vmm_unmap(struct nvkm_vmm *vmm, struct nvkm_vma *vma) { if (vma->memory) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); nvkm_vmm_unmap_locked(vmm, vma, false); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } } @@ -1423,6 +1483,8 @@ nvkm_vmm_map_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma, nvkm_vmm_pte_func func; int ret; + map->no_comp = vma->no_comp; + /* Make sure we won't overrun the end of the memory object. */ if (unlikely(nvkm_memory_size(map->memory) < map->offset + vma->size)) { VMM_DEBUG(vmm, "overrun %016llx %016llx %016llx", @@ -1507,10 +1569,15 @@ nvkm_vmm_map(struct nvkm_vmm *vmm, struct nvkm_vma *vma, void *argv, u32 argc, struct nvkm_vmm_map *map) { int ret; - mutex_lock(&vmm->mutex); + + if (nvkm_vmm_in_managed_range(vmm, vma->addr, vma->size) && + vmm->managed.raw) + return nvkm_vmm_map_locked(vmm, vma, argv, argc, map); + + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_map_locked(vmm, vma, argv, argc, map); vma->busy = false; - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); return ret; } @@ -1620,9 +1687,9 @@ nvkm_vmm_put(struct nvkm_vmm *vmm, struct nvkm_vma **pvma) { struct nvkm_vma *vma = *pvma; if (vma) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); nvkm_vmm_put_locked(vmm, vma); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); *pvma = NULL; } } @@ -1769,9 +1836,49 @@ int nvkm_vmm_get(struct nvkm_vmm *vmm, u8 page, u64 size, struct nvkm_vma **pvma) { int ret; - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_get_locked(vmm, false, true, false, page, 0, size, pvma); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); + return ret; +} + +void +nvkm_vmm_raw_unmap(struct nvkm_vmm *vmm, u64 addr, u64 size, + bool sparse, u8 refd) +{ + const struct nvkm_vmm_page *page = &vmm->func->page[refd]; + + nvkm_vmm_ptes_unmap(vmm, page, addr, size, sparse, false); +} + +void +nvkm_vmm_raw_put(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd) +{ + const struct nvkm_vmm_page *page = vmm->func->page; + + nvkm_vmm_ptes_put(vmm, &page[refd], addr, size); +} + +int +nvkm_vmm_raw_get(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd) +{ + const struct nvkm_vmm_page *page = vmm->func->page; + + if (unlikely(!size)) + return -EINVAL; + + return nvkm_vmm_ptes_get(vmm, &page[refd], addr, size); +} + +int +nvkm_vmm_raw_sparse(struct nvkm_vmm *vmm, u64 addr, u64 size, bool ref) +{ + int ret; + + mutex_lock(&vmm->mutex.ref); + ret = nvkm_vmm_ptes_sparse(vmm, addr, size, ref); + mutex_unlock(&vmm->mutex.ref); + return ret; } @@ -1779,9 +1886,9 @@ void nvkm_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst) { if (inst && vmm && vmm->func->part) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); vmm->func->part(vmm, inst); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } } @@ -1790,9 +1897,9 @@ nvkm_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) { int ret = 0; if (vmm->func->join) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = vmm->func->join(vmm, inst); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h index f6188aa9171c..f9bc30cdb2b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h @@ -163,6 +163,7 @@ int nvkm_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, u32 pd_header, bool managed, u64 addr, u64 size, struct lock_class_key *, const char *name, struct nvkm_vmm **); +struct nvkm_vma *nvkm_vma_new(u64 addr, u64 size); struct nvkm_vma *nvkm_vmm_node_search(struct nvkm_vmm *, u64 addr); struct nvkm_vma *nvkm_vmm_node_split(struct nvkm_vmm *, struct nvkm_vma *, u64 addr, u64 size); @@ -173,6 +174,30 @@ void nvkm_vmm_put_locked(struct nvkm_vmm *, struct nvkm_vma *); void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *, bool pfn); void nvkm_vmm_unmap_region(struct nvkm_vmm *, struct nvkm_vma *); +int nvkm_vmm_raw_get(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd); +void nvkm_vmm_raw_put(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd); +void nvkm_vmm_raw_unmap(struct nvkm_vmm *vmm, u64 addr, u64 size, + bool sparse, u8 refd); +int nvkm_vmm_raw_sparse(struct nvkm_vmm *, u64 addr, u64 size, bool ref); + +static inline bool +nvkm_vmm_in_managed_range(struct nvkm_vmm *vmm, u64 start, u64 size) +{ + u64 p_start = vmm->managed.p.addr; + u64 p_end = p_start + vmm->managed.p.size; + u64 n_start = vmm->managed.n.addr; + u64 n_end = n_start + vmm->managed.n.size; + u64 end = start + size; + + if (start >= p_start && end <= p_end) + return true; + + if (start >= n_start && end <= n_end) + return true; + + return false; +} + #define NVKM_VMM_PFN_ADDR 0xfffffffffffff000ULL #define NVKM_VMM_PFN_ADDR_SHIFT 12 #define NVKM_VMM_PFN_APER 0x00000000000000f0ULL diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c index 5438384d9a67..5e857c02e9aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c @@ -287,15 +287,17 @@ gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return -EINVAL; } - ret = nvkm_memory_tags_get(memory, device, tags, - nvkm_ltc_tags_clear, - &map->tags); - if (ret) { - VMM_DEBUG(vmm, "comp %d", ret); - return ret; + if (!map->no_comp) { + ret = nvkm_memory_tags_get(memory, device, tags, + nvkm_ltc_tags_clear, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } } - if (map->tags->mn) { + if (!map->no_comp && map->tags->mn) { u64 tags = map->tags->mn->offset + (map->offset >> 17); if (page->shift == 17 || !gm20x) { map->type |= tags << 44; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c index 17899fc95b2d..f3630d0e0d55 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c @@ -453,15 +453,17 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return -EINVAL; } - ret = nvkm_memory_tags_get(memory, device, tags, - nvkm_ltc_tags_clear, - &map->tags); - if (ret) { - VMM_DEBUG(vmm, "comp %d", ret); - return ret; + if (!map->no_comp) { + ret = nvkm_memory_tags_get(memory, device, tags, + nvkm_ltc_tags_clear, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } } - if (map->tags->mn) { + if (!map->no_comp && map->tags->mn) { tags = map->tags->mn->offset + (map->offset >> 16); map->ctag |= ((1ULL << page->shift) >> 16) << 36; map->type |= tags << 36; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c index b7548dcd72c7..ff08ad5005a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c @@ -296,19 +296,22 @@ nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return -EINVAL; } - ret = nvkm_memory_tags_get(memory, device, tags, NULL, - &map->tags); - if (ret) { - VMM_DEBUG(vmm, "comp %d", ret); - return ret; - } + if (!map->no_comp) { + ret = nvkm_memory_tags_get(memory, device, tags, NULL, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } - if (map->tags->mn) { - u32 tags = map->tags->mn->offset + (map->offset >> 16); - map->ctag |= (u64)comp << 49; - map->type |= (u64)comp << 47; - map->type |= (u64)tags << 49; - map->next |= map->ctag; + if (map->tags->mn) { + u32 tags = map->tags->mn->offset + + (map->offset >> 16); + map->ctag |= (u64)comp << 49; + map->type |= (u64)comp << 47; + map->type |= (u64)tags << 49; + map->next |= map->ctag; + } } } |