diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2016-11-05 00:33:14 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2016-11-06 23:05:13 -0500 |
| commit | b27add13f500469127afdf011dbcc9c649e16e54 (patch) | |
| tree | 29f3d0087452fdcf7166d83c82a936af26f3e8e0 | |
| parent | e137040e0d0376b404fc5155eba44ea07126e3bd (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.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 8 |
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 | ||
| 57 | static u32 | 59 | static u32 |
