mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
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
This commit is contained in:
parent
e137040e0d
commit
b27add13f5
2 changed files with 11 additions and 6 deletions
|
@ -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,
|
||||||
) < 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)
|
||||||
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)
|
||||||
) < 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue