From d40d0fd487375c66ed444ec2bbd5ffa5d64ebede Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Nov 2015 10:07:22 +1000 Subject: [PATCH] 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 --- .../gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 20 +++++++++++++++++-- .../gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 5 ++++- .../nouveau/nvkm/engine/fifo/gpfifogf100.c | 8 ++++---- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index ff6fcbda615b..6f276dab4a25 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index c649ca9b53e3..08c33c3ceaf7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -5,6 +5,7 @@ #include +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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index e7cbc139c1d4..3f3767518558 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -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); } } -- 2.30.2