drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c
Extension
.c
Size
16609 bytes
Lines
627
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (chan) {
			nvkm_chan_error(chan, true);
			nvkm_chan_put(&chan, flags);
		}

		nvkm_mask(device, 0x0400ac + (runq->id * 0x800), 0x00030000, 0x00030000);
		stat &= ~0x80000000;
	}

	if (stat) {
		RUNQ_ERROR(runq, "intr1 %08x", stat);
		nvkm_wr32(device, 0x0401a0 + (runq->id * 0x800), stat);
	}

	nvkm_wr32(device, 0x040148 + (runq->id * 0x800), intr);
	return true;
}

static bool
ga100_runq_intr_0(struct nvkm_runq *runq, struct nvkm_runl *runl)
{
	struct nvkm_device *device = runq->fifo->engine.subdev.device;
	u32 inte = nvkm_rd32(device, 0x040170 + (runq->id * 0x800));
	u32 intr = nvkm_rd32(device, 0x040108 + (runq->id * 0x800));
	u32 stat = intr & inte;

	if (!stat) {
		RUNQ_DEBUG(runq, "inte0 %08x %08x", intr, inte);
		return false;
	}

	/*TODO: expand on this when fixing up gf100's version. */
	if (stat & 0xc6afe000) {
		u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x0800)) & runl->chid->mask;
		struct nvkm_chan *chan;
		unsigned long flags;

		RUNQ_ERROR(runq, "intr0 %08x", stat);
		chan = nvkm_runl_chan_get_chid(runl, chid, &flags);
		if (chan) {
			nvkm_chan_error(chan, true);
			nvkm_chan_put(&chan, flags);
		}

		stat &= ~0xc6afe000;
	}

	if (stat) {
		RUNQ_ERROR(runq, "intr0 %08x", stat);
		nvkm_wr32(device, 0x040190 + (runq->id * 0x800), stat);
	}

	nvkm_wr32(device, 0x040108 + (runq->id * 0x800), intr);
	return true;
}

static bool
ga100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *runl)
{
	bool intr0 = ga100_runq_intr_0(runq, runl);
	bool intr1 = ga100_runq_intr_1(runq, runl);

	return intr0 || intr1;
}

static void
ga100_runq_init(struct nvkm_runq *runq)
{
	struct nvkm_device *device = runq->fifo->engine.subdev.device;

	nvkm_wr32(device, 0x040108 + (runq->id * 0x800), 0xffffffff); /* INTR_0 */
	nvkm_wr32(device, 0x040148 + (runq->id * 0x800), 0xffffffff); /* INTR_1 */
	nvkm_wr32(device, 0x040170 + (runq->id * 0x800), 0xffffffff); /* INTR_0_EN_SET_TREE */
	nvkm_wr32(device, 0x040180 + (runq->id * 0x800), 0xffffffff); /* INTR_1_EN_SET_TREE */
}

const struct nvkm_runq_func
ga100_runq = {
	.init = ga100_runq_init,
	.intr = ga100_runq_intr,
	.idle = ga100_runq_idle,
};

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

static void

Annotation

Implementation Notes