summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-11-11 10:07:22 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-11-25 15:38:13 +1000
commitcdefd837a91e7d21ce79daeedfbe8e60c5cf8398 (patch)
tree25ca6e5f61d97a3d3ca4f5bc0013129913e18ff5
parente94867173e1ca254c30b12f9859f00c990268abb (diff)
fifo/gf100: fix race condition when updating engine runlists
Similar in spirit to the gk104 fix with a similar title. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drm/nouveau/nvkm/engine/fifo/gf100.c20
-rw-r--r--drm/nouveau/nvkm/engine/fifo/gf100.h5
-rw-r--r--drm/nouveau/nvkm/engine/fifo/gpfifogf100.c8
3 files changed, 26 insertions, 7 deletions
diff --git a/drm/nouveau/nvkm/engine/fifo/gf100.c b/drm/nouveau/nvkm/engine/fifo/gf100.c
index ff6fcbda..6f276dab 100644
--- a/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -47,7 +47,7 @@ gf100_fifo_uevent_fini(struct nvkm_fifo *fifo)
}
void
-gf100_fifo_runlist_update(struct gf100_fifo *fifo)
+gf100_fifo_runlist_commit(struct gf100_fifo *fifo)
{
struct gf100_fifo_chan *chan;
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
@@ -77,6 +77,22 @@ gf100_fifo_runlist_update(struct gf100_fifo *fifo)
mutex_unlock(&subdev->mutex);
}
+void
+gf100_fifo_runlist_remove(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
+{
+ mutex_lock(&fifo->base.engine.subdev.mutex);
+ list_del_init(&chan->head);
+ mutex_unlock(&fifo->base.engine.subdev.mutex);
+}
+
+void
+gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
+{
+ mutex_lock(&fifo->base.engine.subdev.mutex);
+ list_add_tail(&chan->head, &fifo->chan);
+ mutex_unlock(&fifo->base.engine.subdev.mutex);
+}
+
static inline int
gf100_fifo_engidx(struct gf100_fifo *fifo, u32 engn)
{
@@ -139,7 +155,7 @@ gf100_fifo_recover_work(struct work_struct *work)
}
}
- gf100_fifo_runlist_update(fifo);
+ gf100_fifo_runlist_commit(fifo);
nvkm_wr32(device, 0x00262c, engm);
nvkm_mask(device, 0x002630, engm, 0x00000000);
}
diff --git a/drm/nouveau/nvkm/engine/fifo/gf100.h b/drm/nouveau/nvkm/engine/fifo/gf100.h
index c649ca9b..08c33c3c 100644
--- a/drm/nouveau/nvkm/engine/fifo/gf100.h
+++ b/drm/nouveau/nvkm/engine/fifo/gf100.h
@@ -5,6 +5,7 @@
#include <subdev/mmu.h>
+struct gf100_fifo_chan;
struct gf100_fifo {
struct nvkm_fifo base;
@@ -27,5 +28,7 @@ struct gf100_fifo {
};
void gf100_fifo_intr_engine(struct gf100_fifo *);
-void gf100_fifo_runlist_update(struct gf100_fifo *);
+void gf100_fifo_runlist_insert(struct gf100_fifo *, struct gf100_fifo_chan *);
+void gf100_fifo_runlist_remove(struct gf100_fifo *, struct gf100_fifo_chan *);
+void gf100_fifo_runlist_commit(struct gf100_fifo *);
#endif
diff --git a/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
index e7cbc139..3f376751 100644
--- a/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ b/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
@@ -138,9 +138,9 @@ gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
u32 coff = chan->base.chid * 8;
if (!list_empty(&chan->head) && !chan->killed) {
- list_del_init(&chan->head);
+ gf100_fifo_runlist_remove(fifo, chan);
nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000);
- gf100_fifo_runlist_update(fifo);
+ gf100_fifo_runlist_commit(fifo);
}
gf100_fifo_intr_engine(fifo);
@@ -160,9 +160,9 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr);
if (list_empty(&chan->head) && !chan->killed) {
- list_add_tail(&chan->head, &fifo->chan);
+ gf100_fifo_runlist_insert(fifo, chan);
nvkm_wr32(device, 0x003004 + coff, 0x001f0001);
- gf100_fifo_runlist_update(fifo);
+ gf100_fifo_runlist_commit(fifo);
}
}