Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b27add13 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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: default avatarBen Skeggs <bskeggs@redhat.com>
Cc: stable@vger.kernel.org
parent e137040e
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -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);
+5 −3
Original line number Original line Diff line number Diff line
@@ -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