Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -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);
}
+4 −1
Original line number Diff line number Diff line
@@ -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
+4 −4
Original line number Diff line number Diff line
@@ -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);
	}
}