drivers/gpu/drm/nouveau/nvkm/engine/falcon.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
Extension
.c
Size
10439 bytes
Lines
356
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 (c++ == index) {
			oclass->base = falcon->func->sclass[index];
			return index;
		}
	}

	return c;
}

static int
nvkm_falcon_cclass_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
			int align, struct nvkm_gpuobj **pgpuobj)
{
	return nvkm_gpuobj_new(object->engine->subdev.device, 256,
			       align, true, parent, pgpuobj);
}

static const struct nvkm_object_func
nvkm_falcon_cclass = {
	.bind = nvkm_falcon_cclass_bind,
};

static void
nvkm_falcon_intr(struct nvkm_engine *engine)
{
	struct nvkm_falcon *falcon = nvkm_falcon(engine);
	struct nvkm_subdev *subdev = &falcon->engine.subdev;
	struct nvkm_device *device = subdev->device;
	const u32 base = falcon->addr;
	u32 dest = nvkm_rd32(device, base + 0x01c);
	u32 intr = nvkm_rd32(device, base + 0x008) & dest & ~(dest >> 16);
	u32 inst = nvkm_rd32(device, base + 0x050) & 0x3fffffff;
	struct nvkm_chan *chan;
	unsigned long flags;

	chan = nvkm_chan_get_inst(engine, (u64)inst << 12, &flags);

	if (intr & 0x00000040) {
		if (falcon->func->intr) {
			falcon->func->intr(falcon, chan);
			nvkm_wr32(device, base + 0x004, 0x00000040);
			intr &= ~0x00000040;
		}
	}

	if (intr & 0x00000010) {
		nvkm_debug(subdev, "ucode halted\n");
		nvkm_wr32(device, base + 0x004, 0x00000010);
		intr &= ~0x00000010;
	}

	if (intr)  {
		nvkm_error(subdev, "intr %08x\n", intr);
		nvkm_wr32(device, base + 0x004, intr);
	}

	nvkm_chan_put(&chan, flags);
}

static int
nvkm_falcon_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
	struct nvkm_falcon *falcon = nvkm_falcon(engine);
	struct nvkm_device *device = falcon->engine.subdev.device;
	const u32 base = falcon->addr;

	if (suspend == NVKM_POWEROFF) {
		nvkm_memory_unref(&falcon->core);
		if (falcon->external) {
			vfree(falcon->data.data);
			vfree(falcon->code.data);
			falcon->code.data = NULL;
		}
	}

	if (nvkm_mc_enabled(device, engine->subdev.type, engine->subdev.inst)) {
		nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
		nvkm_wr32(device, base + 0x014, 0xffffffff);
	}
	return 0;
}

static void *
vmemdup(const void *src, size_t len)
{
	void *p = vmalloc(len);

	if (p)
		memcpy(p, src, len);
	return p;

Annotation

Implementation Notes