Commit 4a492fd5 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fifo: add runlist wait()



- adds g8x/turing registers, which were missing before
- switches fermi to polled wait, like later hw (see: 4f2fc25c...)

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent f48dd293
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -54,6 +54,10 @@ struct nvkm_fifo {
		struct nvkm_event event;
	} nonstall;

	struct {
		u32 chan_msec;
	} timeout;

	int nr;
	struct list_head chan;
	spinlock_t lock;
+5 −0
Original line number Diff line number Diff line
@@ -319,6 +319,11 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
	fifo->func = func;
	INIT_LIST_HEAD(&fifo->runqs);
	INIT_LIST_HEAD(&fifo->runls);
	/*TODO: Needs to be >CTXSW_TIMEOUT, so RC can recover before this is hit.
	 *      CTXSW_TIMEOUT HW default seems to differ between GPUs, so just a
	 *      large number for now until we support changing it.
	 */
	fifo->timeout.chan_msec = 10000;
	spin_lock_init(&fifo->lock);
	mutex_init(&fifo->mutex);

+13 −10
Original line number Diff line number Diff line
@@ -115,12 +115,19 @@ gf100_runq = {
	.intr_0_names = gf100_runq_intr_0_names,
};

static bool
gf100_runl_pending(struct nvkm_runl *runl)
{
	return nvkm_rd32(runl->fifo->engine.subdev.device, 0x00227c) & 0x00100000;
}

void
gf100_fifo_runlist_commit(struct gf100_fifo *fifo)
{
	struct gf100_fifo_chan *chan;
	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_runl *runl = nvkm_runl_first(&fifo->base);
	struct nvkm_memory *cur;
	int nr = 0;
	int target;
@@ -150,10 +157,7 @@ gf100_fifo_runlist_commit(struct gf100_fifo *fifo)
				    (target << 28));
	nvkm_wr32(device, 0x002274, 0x01f00000 | nr);

	if (wait_event_timeout(fifo->runlist.wait,
			       !(nvkm_rd32(device, 0x00227c) & 0x00100000),
			       msecs_to_jiffies(2000)) == 0)
		nvkm_error(subdev, "runlist update timeout\n");
	runl->func->wait(runl);
	mutex_unlock(&fifo->base.mutex);
}

@@ -175,6 +179,8 @@ gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)

static const struct nvkm_runl_func
gf100_runl = {
	.wait = nv50_runl_wait,
	.pending = gf100_runl_pending,
};

static void
@@ -558,14 +564,13 @@ gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo)
}

static void
gf100_fifo_intr_runlist(struct gf100_fifo *fifo)
gf100_fifo_intr_runlist(struct nvkm_fifo *fifo)
{
	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
	struct nvkm_subdev *subdev = &fifo->engine.subdev;
	struct nvkm_device *device = subdev->device;
	u32 intr = nvkm_rd32(device, 0x002a00);

	if (intr & 0x10000000) {
		wake_up(&fifo->runlist.wait);
		nvkm_wr32(device, 0x002a00, 0x10000000);
		intr &= ~0x10000000;
	}
@@ -660,7 +665,7 @@ gf100_fifo_intr(struct nvkm_inth *inth)
	}

	if (stat & 0x40000000) {
		gf100_fifo_intr_runlist(gf100_fifo(fifo));
		gf100_fifo_intr_runlist(fifo);
		stat &= ~0x40000000;
	}

@@ -779,8 +784,6 @@ gf100_fifo_oneinit(struct nvkm_fifo *base)
	if (ret)
		return ret;

	init_waitqueue_head(&fifo->runlist.wait);

	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000,
			      0x1000, false, &fifo->user.mem);
	if (ret)
+0 −1
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ struct gf100_fifo {
	struct {
		struct nvkm_memory *mem[2];
		int active;
		wait_queue_head_t wait;
	} runlist;

	struct {
+19 −14
Original line number Diff line number Diff line
@@ -197,12 +197,21 @@ gk104_runq = {
	.intr_0_names = gk104_runq_intr_0_names,
};

bool
gk104_runl_pending(struct nvkm_runl *runl)
{
	struct nvkm_device *device = runl->fifo->engine.subdev.device;

	return nvkm_rd32(device, 0x002284 + (runl->id * 0x08)) & 0x00100000;
}

void
gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
			  struct nvkm_memory *mem, int nr)
{
	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_runl *rl = nvkm_runl_get(&fifo->base, runl, 0);
	int target;

	switch (nvkm_memory_target(mem)) {
@@ -217,11 +226,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
				    (target << 28));
	nvkm_wr32(device, 0x002274, (runl << 20) | nr);

	if (nvkm_msec(device, 2000,
		if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000))
			break;
	) < 0)
		nvkm_error(subdev, "runlist %d update timeout\n", runl);
	rl->func->wait(rl);
}

void
@@ -299,6 +304,8 @@ gk104_fifo_runlist = {

static const struct nvkm_runl_func
gk104_runl = {
	.wait = nv50_runl_wait,
	.pending = gk104_runl_pending,
};

int
@@ -736,15 +743,14 @@ gk104_fifo_intr_dropped_fault(struct nvkm_fifo *fifo)
}

void
gk104_fifo_intr_runlist(struct gk104_fifo *fifo)
gk104_fifo_intr_runlist(struct nvkm_fifo *fifo)
{
	struct nvkm_device *device = fifo->base.engine.subdev.device;
	struct nvkm_device *device = fifo->engine.subdev.device;
	struct nvkm_runl *runl;
	u32 mask = nvkm_rd32(device, 0x002a00);
	while (mask) {
		int runl = __ffs(mask);
		wake_up(&fifo->runlist[runl].wait);
		nvkm_wr32(device, 0x002a00, 1 << runl);
		mask &= ~(1 << runl);

	nvkm_runl_foreach_cond(runl, fifo, mask & BIT(runl->id)) {
		nvkm_wr32(device, 0x002a00, BIT(runl->id));
	}
}

@@ -810,7 +816,7 @@ gk104_fifo_intr(struct nvkm_inth *inth)
	}

	if (stat & 0x40000000) {
		gk104_fifo_intr_runlist(gk104_fifo(fifo));
		gk104_fifo_intr_runlist(fifo);
		stat &= ~0x40000000;
	}

@@ -949,7 +955,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
				return ret;
		}

		init_waitqueue_head(&fifo->runlist[i].wait);
		INIT_LIST_HEAD(&fifo->runlist[i].cgrp);
		INIT_LIST_HEAD(&fifo->runlist[i].chan);
	}
Loading