diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm')
70 files changed, 768 insertions, 247 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/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 40c8ea43c42f..b8ac66b4a2c4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -26,6 +26,8 @@ #include "head.h" #include "ior.h" +#include <drm/display/drm_dp.h> + #include <subdev/bios.h> #include <subdev/bios/init.h> #include <subdev/gpio.h> @@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) return outp->dp.rates != 0; } +/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps() + * converted to work inside nvkm. This is a temporary holdover until we start + * passing the drm_dp_aux device through NVKM + */ +static int +nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp) +{ + struct nvkm_i2c_aux *aux = outp->dp.aux; + u8 dpcd_ext[DP_RECEIVER_CAP_SIZE]; + int ret; + + ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, DP_RECEIVER_CAP_SIZE); + if (ret < 0) + return ret; + + /* + * Prior to DP1.3 the bit represented by + * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. + * If it is set DP_DPCD_REV at 0000h could be at a value less than + * the true capability of the panel. The only way to check is to + * then compare 0000h and 2200h. + */ + if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] & + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) + return 0; + + ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext)); + if (ret < 0) + return ret; + + if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { + OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > %d)\n", + outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]); + return 0; + } + + if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext))) + return 0; + + memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)); + + return 0; +} + void nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) { @@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr)); } - if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) { + if (!nvkm_dp_read_dpcd_caps(outp)) { const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; const u8 *rate; int rate_max; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index a4853c4e5ee3..67ef889a0c5f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -295,6 +295,7 @@ g94_sor = { .clock = nv50_sor_clock, .war_2 = g94_sor_war_2, .war_3 = g94_sor_war_3, + .hdmi = &g84_sor_hdmi, .dp = &g94_sor_dp, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index a2c7c6f83dcd..506ffbe7b842 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -125,7 +125,7 @@ gt215_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 siz pack_hdmi_infoframe(&avi, data, size); nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - if (size) + if (!size) return; nvkm_wr32(device, 0x61c528 + soff, avi.header); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c index dad942be6679..46b057fe1412 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -81,20 +81,29 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ return -ENOSYS; list_for_each_entry(outp, &conn->disp->outps, head) { - if (outp->info.connector == conn->index && outp->dp.aux) { - if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG; - if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG; - if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ; + if (outp->info.connector == conn->index) + break; + } - return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits, - nvkm_uconn_uevent_aux); - } + if (&outp->head == &conn->disp->outps) + return -EINVAL; + + if (outp->dp.aux && !outp->info.location) { + if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ; + + return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits, + nvkm_uconn_uevent_aux); } if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_GPIO_HI; if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO; - if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) - return -EINVAL; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) { + /* TODO: support DP IRQ on ANX9805 and remove this hack. */ + if (!outp->info.location) + return -EINVAL; + } return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits, nvkm_uconn_uevent_gpio); 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/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 00dbeda7e346..de161e7a04aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -117,6 +117,7 @@ void gk104_grctx_generate_r418800(struct gf100_gr *); extern const struct gf100_grctx_func gk110_grctx; void gk110_grctx_generate_r419eb0(struct gf100_gr *); +void gk110_grctx_generate_r419f78(struct gf100_gr *); extern const struct gf100_grctx_func gk110b_grctx; extern const struct gf100_grctx_func gk208_grctx; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index 94233d0119df..52a234b1ef01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -906,7 +906,9 @@ static void gk104_grctx_generate_r419f78(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; - nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000); + + /* bit 3 set disables loads in fp helper invocations, we need it enabled */ + nvkm_mask(device, 0x419f78, 0x00000009, 0x00000000); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c index 4391458e1fb2..3acdd9eeb74a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c @@ -820,6 +820,15 @@ gk110_grctx_generate_r419eb0(struct gf100_gr *gr) nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000); } +void +gk110_grctx_generate_r419f78(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + /* bit 3 set disables loads in fp helper invocations, we need it enabled */ + nvkm_mask(device, 0x419f78, 0x00000008, 0x00000000); +} + const struct gf100_grctx_func gk110_grctx = { .main = gf100_grctx_generate_main, @@ -854,4 +863,5 @@ gk110_grctx = { .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r418800 = gk104_grctx_generate_r418800, .r419eb0 = gk110_grctx_generate_r419eb0, + .r419f78 = gk110_grctx_generate_r419f78, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c index 7b9a34f9ec3c..5597e87624ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c @@ -103,4 +103,5 @@ gk110b_grctx = { .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r418800 = gk104_grctx_generate_r418800, .r419eb0 = gk110_grctx_generate_r419eb0, + .r419f78 = gk110_grctx_generate_r419f78, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c index c78d07a8bb7d..612656496541 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c @@ -568,4 +568,5 @@ gk208_grctx = { .dist_skip_table = gf117_grctx_generate_dist_skip_table, .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r418800 = gk104_grctx_generate_r418800, + .r419f78 = gk110_grctx_generate_r419f78, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index beac66eb2a80..9906974ac3f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -988,4 +988,5 @@ gm107_grctx = { .r406500 = gm107_grctx_generate_r406500, .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r419e00 = gm107_grctx_generate_r419e00, + .r419f78 = gk110_grctx_generate_r419f78, }; 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/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 3b6c8100a242..a7775aa18541 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -206,19 +206,6 @@ tu102_gr_av_to_init_veid(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack); } -int -tu102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) -{ - int ret; - - ret = gm200_gr_load(gr, ver, fwif); - if (ret) - return ret; - - return gk20a_gr_load_net(gr, "gr/", "sw_veid_bundle_init", ver, tu102_gr_av_to_init_veid, - &gr->bundle_veid); -} - static const struct gf100_gr_fwif tu102_gr_fwif[] = { { 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr }, 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/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 795f3a649b12..9b8ca4e898f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -224,7 +224,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) u64 falcons; int ret, i; - if (list_empty(&acr->hsfw)) { + if (list_empty(&acr->hsfw) || !acr->func || !acr->func->wpr_layout) { nvkm_debug(subdev, "No HSFW(s)\n"); nvkm_acr_cleanup(acr); return 0; 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/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 976539de4220..731b2f68d3db 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, { struct nvkm_bios *bios = device->bios; struct nvkm_i2c *i2c; + struct nvkm_i2c_aux *aux; struct dcb_i2c_entry ccbE; struct dcb_output dcbE; u8 ver, hdr; - int ret, i; + int ret, i, ids; if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) return -ENOMEM; @@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, } } - return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event); + ids = 0; + list_for_each_entry(aux, &i2c->aux, head) + ids = max(ids, aux->id + 1); + if (!ids) + return 0; + + return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event); } 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; + } } } |