Commit d40d0fd4 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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)
}
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);
}
......
......@@ -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
......@@ -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);
}
}
......
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