Commit d40d0fd4 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo/gf100: fix race condition when updating engine runlists

Similar in spirit to the gk104 fix with a similar title.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 386ffd5e
...@@ -47,7 +47,7 @@ gf100_fifo_uevent_fini(struct nvkm_fifo *fifo) ...@@ -47,7 +47,7 @@ gf100_fifo_uevent_fini(struct nvkm_fifo *fifo)
} }
void void
gf100_fifo_runlist_update(struct gf100_fifo *fifo) gf100_fifo_runlist_commit(struct gf100_fifo *fifo)
{ {
struct gf100_fifo_chan *chan; struct gf100_fifo_chan *chan;
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
...@@ -77,6 +77,22 @@ gf100_fifo_runlist_update(struct gf100_fifo *fifo) ...@@ -77,6 +77,22 @@ gf100_fifo_runlist_update(struct gf100_fifo *fifo)
mutex_unlock(&subdev->mutex); 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 static inline int
gf100_fifo_engidx(struct gf100_fifo *fifo, u32 engn) gf100_fifo_engidx(struct gf100_fifo *fifo, u32 engn)
{ {
...@@ -139,7 +155,7 @@ gf100_fifo_recover_work(struct work_struct *work) ...@@ -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_wr32(device, 0x00262c, engm);
nvkm_mask(device, 0x002630, engm, 0x00000000); nvkm_mask(device, 0x002630, engm, 0x00000000);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <subdev/mmu.h> #include <subdev/mmu.h>
struct gf100_fifo_chan;
struct gf100_fifo { struct gf100_fifo {
struct nvkm_fifo base; struct nvkm_fifo base;
...@@ -27,5 +28,7 @@ struct gf100_fifo { ...@@ -27,5 +28,7 @@ struct gf100_fifo {
}; };
void gf100_fifo_intr_engine(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 #endif
...@@ -138,9 +138,9 @@ gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) ...@@ -138,9 +138,9 @@ gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
u32 coff = chan->base.chid * 8; u32 coff = chan->base.chid * 8;
if (!list_empty(&chan->head) && !chan->killed) { 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); nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000);
gf100_fifo_runlist_update(fifo); gf100_fifo_runlist_commit(fifo);
} }
gf100_fifo_intr_engine(fifo); gf100_fifo_intr_engine(fifo);
...@@ -160,9 +160,9 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base) ...@@ -160,9 +160,9 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr); nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr);
if (list_empty(&chan->head) && !chan->killed) { 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); nvkm_wr32(device, 0x003004 + coff, 0x001f0001);
gf100_fifo_runlist_update(fifo); gf100_fifo_runlist_commit(fifo);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment