summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2022-06-01 20:47:31 +1000
committerBen Skeggs <bskeggs@redhat.com>2022-11-09 10:44:48 +1000
commit3a6bc9c242e10c203a5b083af7823b50b5d63010 (patch)
treeafb02468e4bed3900a9708c42c76605627e1ad32
parent4a492fd5d26298c82c555f603fe4aa38cf512464 (diff)
downloadlinux-3a6bc9c242e10c203a5b083af7823b50b5d63010.tar.bz2
drm/nouveau/fifo: add runlist block()/allow()
Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c2
13 files changed, 95 insertions, 14 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
index f250b0f9e274..748f3f199b9f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
@@ -211,11 +211,24 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
void
nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct nvkm_cctx *cctx)
{
+ struct nvkm_cgrp *cgrp = chan->cgrp;
+ struct nvkm_runl *runl = cgrp->runl;
+
+ /* Prevent any channel in channel group from being rescheduled, kick them
+ * off host and any engine(s) they're loaded on.
+ */
+ if (cgrp->hw)
+ nvkm_runl_block(runl);
+
/* Update context pointer. */
if (cctx)
nvkm_fifo_chan_child_init(nvkm_oproxy(oproxy->object));
else
nvkm_fifo_chan_child_fini(nvkm_oproxy(oproxy->object), false);
+
+ /* Resume normal operation. */
+ if (cgrp->hw)
+ nvkm_runl_allow(runl);
}
void
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index 70a2609479b9..fcfc241c8a99 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -115,6 +115,18 @@ gf100_runq = {
.intr_0_names = gf100_runq_intr_0_names,
};
+static void
+gf100_runl_allow(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, 0x00000000);
+}
+
+static void
+gf100_runl_block(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, engm);
+}
+
static bool
gf100_runl_pending(struct nvkm_runl *runl)
{
@@ -181,6 +193,8 @@ static const struct nvkm_runl_func
gf100_runl = {
.wait = nv50_runl_wait,
.pending = gf100_runl_pending,
+ .block = gf100_runl_block,
+ .allow = gf100_runl_allow,
};
static void
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index c816654dc245..12aebf83f090 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -197,6 +197,18 @@ gk104_runq = {
.intr_0_names = gk104_runq_intr_0_names,
};
+void
+gk104_runl_allow(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), 0x00000000);
+}
+
+void
+gk104_runl_block(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), BIT(runl->id));
+}
+
bool
gk104_runl_pending(struct nvkm_runl *runl)
{
@@ -306,6 +318,8 @@ static const struct nvkm_runl_func
gk104_runl = {
.wait = nv50_runl_wait,
.pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
index bcc78b35d4e2..134de3c71ad5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
@@ -62,6 +62,8 @@ const struct nvkm_runl_func
gk110_runl = {
.wait = nv50_runl_wait,
.pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
index b6a2210f42c2..d3b2aa701f53 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
@@ -56,6 +56,8 @@ const struct nvkm_runl_func
gm107_runl = {
.wait = nv50_runl_wait,
.pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
};
static const struct nvkm_enum
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
index b810175209d1..4dd3fb04d7e5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
@@ -33,6 +33,8 @@ static const struct nvkm_runl_func
gp100_runl = {
.wait = nv50_runl_wait,
.pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
};
static const struct nvkm_enum
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
index 34a8e792c0e8..6e74fdc0dc24 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
@@ -37,15 +37,12 @@ gv100_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *chan)
static int
gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid)
{
- struct nvkm_subdev *subdev = &chan->base.fifo->engine.subdev;
- struct nvkm_device *device = subdev->device;
const u32 mask = ce ? 0x00020000 : 0x00010000;
const u32 data = valid ? mask : 0x00000000;
int ret;
/* Block runlist to prevent the channel from being rescheduled. */
mutex_lock(&chan->fifo->base.mutex);
- nvkm_mask(device, 0x002630, BIT(chan->runl), BIT(chan->runl));
/* Preempt the channel. */
ret = gk104_fifo_gpfifo_kick_locked(chan);
@@ -57,7 +54,6 @@ gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid
}
/* Resume runlist. */
- nvkm_mask(device, 0x002630, BIT(chan->runl), 0);
mutex_unlock(&chan->fifo->base.mutex);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
index 7ad04e97a82d..c147c26b80ca 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
@@ -86,6 +86,8 @@ static const struct nvkm_runl_func
gv100_runl = {
.wait = nv50_runl_wait,
.pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
};
const struct nvkm_enum
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
index 85f22fce11ed..446e65dcb036 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
@@ -129,14 +129,13 @@ nv04_engn = {
};
void
-nv04_fifo_pause(struct nvkm_fifo *base, unsigned long *pflags)
-__acquires(fifo->base.lock)
+nv04_fifo_pause(struct nvkm_fifo *fifo, unsigned long *pflags)
+__acquires(fifo->lock)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = fifo->engine.subdev.device;
unsigned long flags;
- spin_lock_irqsave(&fifo->base.lock, flags);
+ spin_lock_irqsave(&fifo->lock, flags);
*pflags = flags;
nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000000);
@@ -165,17 +164,16 @@ __acquires(fifo->base.lock)
}
void
-nv04_fifo_start(struct nvkm_fifo *base, unsigned long *pflags)
-__releases(fifo->base.lock)
+nv04_fifo_start(struct nvkm_fifo *fifo, unsigned long *pflags)
+__releases(fifo->lock)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = fifo->engine.subdev.device;
unsigned long flags = *pflags;
nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000001);
nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000001);
- spin_unlock_irqrestore(&fifo->base.lock, flags);
+ spin_unlock_irqrestore(&fifo->lock, flags);
}
const struct nvkm_runl_func
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
index bab3cfbc5fcf..16fe77ee4c86 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
@@ -134,6 +134,8 @@ extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[];
void gk104_fifo_recover_chan(struct nvkm_fifo *, int);
int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *);
bool gk104_runl_pending(struct nvkm_runl *);
+void gk104_runl_block(struct nvkm_runl *, u32);
+void gk104_runl_allow(struct nvkm_runl *, u32);
extern const struct nvkm_runq_func gk104_runq;
void gk104_runq_init(struct nvkm_runq *);
bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c
index 0e1d703456b6..438e884b8100 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c
@@ -83,6 +83,34 @@ nvkm_runl_update_pending(struct nvkm_runl *runl)
}
void
+nvkm_runl_allow(struct nvkm_runl *runl)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ if (!--runl->blocked) {
+ RUNL_TRACE(runl, "running");
+ runl->func->allow(runl, ~0);
+ }
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+void
+nvkm_runl_block(struct nvkm_runl *runl)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ if (!runl->blocked++) {
+ RUNL_TRACE(runl, "stopped");
+ runl->func->block(runl, ~0);
+ }
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+void
nvkm_runl_del(struct nvkm_runl *runl)
{
struct nvkm_engn *engn, *engt;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h
index 7682731c3af6..aebd8a750d38 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h
@@ -26,6 +26,8 @@ struct nvkm_runl {
const struct nvkm_runl_func {
int (*wait)(struct nvkm_runl *);
bool (*pending)(struct nvkm_runl *);
+ void (*block)(struct nvkm_runl *, u32 engm);
+ void (*allow)(struct nvkm_runl *, u32 engm);
} *func;
struct nvkm_fifo *fifo;
int id;
@@ -44,6 +46,8 @@ struct nvkm_runl {
int chan_nr;
struct mutex mutex;
+ int blocked;
+
struct list_head head;
};
@@ -52,6 +56,8 @@ struct nvkm_runl *nvkm_runl_get(struct nvkm_fifo *, int runi, u32 addr);
struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_engn_func *,
enum nvkm_subdev_type, int inst);
void nvkm_runl_del(struct nvkm_runl *);
+void nvkm_runl_block(struct nvkm_runl *);
+void nvkm_runl_allow(struct nvkm_runl *);
bool nvkm_runl_update_pending(struct nvkm_runl *);
struct nvkm_chan *nvkm_runl_chan_get_chid(struct nvkm_runl *, int chid, unsigned long *irqflags);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c
index f0564fa400b7..7d3c9d8e54a7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c
@@ -68,6 +68,8 @@ static const struct nvkm_runl_func
tu102_runl = {
.wait = nv50_runl_wait,
.pending = tu102_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
};
static const struct nvkm_enum