Commit 9195157f authored by Ben Skeggs's avatar Ben Skeggs Committed by Greg Kroah-Hartman

drm/nouveau/fifo/gf100-: protect channel preempt with subdev mutex

commit b27add13 upstream.

This avoids an issue that occurs when we're attempting to preempt multiple
channels simultaneously.  HW seems to ignore preempt requests while it's
still processing a previous one, which, well, makes sense.

Fixes random "fifo: SCHED_ERROR 0d []" + GPCCS page faults during parallel
piglit runs on (at least) GM107.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 64a5c472
...@@ -60,6 +60,7 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, ...@@ -60,6 +60,7 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
struct nvkm_gpuobj *inst = chan->base.inst; struct nvkm_gpuobj *inst = chan->base.inst;
int ret = 0; int ret = 0;
mutex_lock(&subdev->mutex);
nvkm_wr32(device, 0x002634, chan->base.chid); nvkm_wr32(device, 0x002634, chan->base.chid);
if (nvkm_msec(device, 2000, if (nvkm_msec(device, 2000,
if (nvkm_rd32(device, 0x002634) == chan->base.chid) if (nvkm_rd32(device, 0x002634) == chan->base.chid)
...@@ -67,10 +68,12 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, ...@@ -67,10 +68,12 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
) < 0) { ) < 0) {
nvkm_error(subdev, "channel %d [%s] kick timeout\n", nvkm_error(subdev, "channel %d [%s] kick timeout\n",
chan->base.chid, chan->base.object.client->name); chan->base.chid, chan->base.object.client->name);
ret = -EBUSY; ret = -ETIMEDOUT;
if (suspend)
return ret;
} }
mutex_unlock(&subdev->mutex);
if (ret && suspend)
return ret;
if (offset) { if (offset) {
nvkm_kmap(inst); nvkm_kmap(inst);
......
...@@ -40,7 +40,9 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan) ...@@ -40,7 +40,9 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device; struct nvkm_device *device = subdev->device;
struct nvkm_client *client = chan->base.object.client; struct nvkm_client *client = chan->base.object.client;
int ret = 0;
mutex_lock(&subdev->mutex);
nvkm_wr32(device, 0x002634, chan->base.chid); nvkm_wr32(device, 0x002634, chan->base.chid);
if (nvkm_msec(device, 2000, if (nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x002634) & 0x00100000)) if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
...@@ -48,10 +50,10 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan) ...@@ -48,10 +50,10 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
) < 0) { ) < 0) {
nvkm_error(subdev, "channel %d [%s] kick timeout\n", nvkm_error(subdev, "channel %d [%s] kick timeout\n",
chan->base.chid, client->name); chan->base.chid, client->name);
return -EBUSY; ret = -ETIMEDOUT;
} }
mutex_unlock(&subdev->mutex);
return 0; return ret;
} }
static u32 static u32
......
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