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: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 @@
|
|||||||
|
|
||||||
#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 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user