diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-11-11 10:07:22 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2016-01-11 11:10:49 +1000 |
commit | 4f835fa2222a86c2fa3ec91ab30fb0c394842f20 (patch) | |
tree | 34ab37b597aad9e81178efc23369b6234a0d2961 | |
parent | 1e3ed86ff682ba1f963dd2ecce8feafe4b49ab8b (diff) | |
download | nouveau-4f835fa2222a86c2fa3ec91ab30fb0c394842f20.tar.gz |
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.c | 20 | ||||
-rw-r--r-- | drm/nouveau/nvkm/engine/fifo/gf100.h | 5 | ||||
-rw-r--r-- | drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 8 |
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 ff6fcbda6..6f276dab4 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 c649ca9b5..08c33c3ce 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 e7cbc139c..3f3767518 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); } } |