aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2016-11-05 00:33:14 -0400
committerBen Skeggs <bskeggs@redhat.com>2016-11-06 23:05:13 -0500
commitb27add13f500469127afdf011dbcc9c649e16e54 (patch)
tree29f3d0087452fdcf7166d83c82a936af26f3e8e0
parente137040e0d0376b404fc5155eba44ea07126e3bd (diff)
drm/nouveau/fifo/gf100-: protect channel preempt with subdev mutex
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: Ben Skeggs <bskeggs@redhat.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c8
2 files changed, 11 insertions, 6 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
index cbc67f262322..12d964260a29 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
@@ -60,6 +60,7 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
60 struct nvkm_gpuobj *inst = chan->base.inst; 60 struct nvkm_gpuobj *inst = chan->base.inst;
61 int ret = 0; 61 int ret = 0;
62 62
63 mutex_lock(&subdev->mutex);
63 nvkm_wr32(device, 0x002634, chan->base.chid); 64 nvkm_wr32(device, 0x002634, chan->base.chid);
64 if (nvkm_msec(device, 2000, 65 if (nvkm_msec(device, 2000,
65 if (nvkm_rd32(device, 0x002634) == chan->base.chid) 66 if (nvkm_rd32(device, 0x002634) == chan->base.chid)
@@ -67,10 +68,12 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
67 ) < 0) { 68 ) < 0) {
68 nvkm_error(subdev, "channel %d [%s] kick timeout\n", 69 nvkm_error(subdev, "channel %d [%s] kick timeout\n",
69 chan->base.chid, chan->base.object.client->name); 70 chan->base.chid, chan->base.object.client->name);
70 ret = -EBUSY; 71 ret = -ETIMEDOUT;
71 if (suspend)
72 return ret;
73 } 72 }
73 mutex_unlock(&subdev->mutex);
74
75 if (ret && suspend)
76 return ret;
74 77
75 if (offset) { 78 if (offset) {
76 nvkm_kmap(inst); 79 nvkm_kmap(inst);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
index ed4351032ed6..a2df4f3e7763 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
@@ -40,7 +40,9 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
40 struct nvkm_subdev *subdev = &fifo->base.engine.subdev; 40 struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
41 struct nvkm_device *device = subdev->device; 41 struct nvkm_device *device = subdev->device;
42 struct nvkm_client *client = chan->base.object.client; 42 struct nvkm_client *client = chan->base.object.client;
43 int ret = 0;
43 44
45 mutex_lock(&subdev->mutex);
44 nvkm_wr32(device, 0x002634, chan->base.chid); 46 nvkm_wr32(device, 0x002634, chan->base.chid);
45 if (nvkm_msec(device, 2000, 47 if (nvkm_msec(device, 2000,
46 if (!(nvkm_rd32(device, 0x002634) & 0x00100000)) 48 if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
@@ -48,10 +50,10 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
48 ) < 0) { 50 ) < 0) {
49 nvkm_error(subdev, "channel %d [%s] kick timeout\n", 51 nvkm_error(subdev, "channel %d [%s] kick timeout\n",
50 chan->base.chid, client->name); 52 chan->base.chid, client->name);
51 return -EBUSY; 53 ret = -ETIMEDOUT;
52 } 54 }
53 55 mutex_unlock(&subdev->mutex);
54 return 0; 56 return ret;
55} 57}
56 58
57static u32 59static u32