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:
Родитель
386ffd5e80
Коммит
d40d0fd487
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче