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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c
Extension
.c
Size
6549 bytes
Lines
256
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 (refcount_dec_and_test(&ectx->refs)) {
			CGRP_TRACE(cgrp, "dtor ectx %d[%s]", engn->id, engn->engine->subdev.name);
			nvkm_object_del(&ectx->object);
			list_del(&ectx->head);
			kfree(ectx);
		}

		*pectx = NULL;
	}
}

static int
nvkm_cgrp_ectx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_ectx **pectx,
		   struct nvkm_chan *chan, struct nvkm_client *client)
{
	struct nvkm_engine *engine = engn->engine;
	struct nvkm_oclass cclass = {
		.client = client,
		.engine = engine,
	};
	struct nvkm_ectx *ectx;
	int ret = 0;

	/* Look for an existing context for this engine in the channel group. */
	ectx = nvkm_list_find(ectx, &cgrp->ectxs, head, ectx->engn == engn);
	if (ectx) {
		refcount_inc(&ectx->refs);
		*pectx = ectx;
		return 0;
	}

	/* Nope - create a fresh one. */
	CGRP_TRACE(cgrp, "ctor ectx %d[%s]", engn->id, engn->engine->subdev.name);
	if (!(ectx = *pectx = kzalloc_obj(*ectx)))
		return -ENOMEM;

	ectx->engn = engn;
	refcount_set(&ectx->refs, 1);
	refcount_set(&ectx->uses, 0);
	list_add_tail(&ectx->head, &cgrp->ectxs);

	/* Allocate the HW structures. */
	if (engine->func->fifo.cclass)
		ret = engine->func->fifo.cclass(chan, &cclass, &ectx->object);
	else if (engine->func->cclass)
		ret = nvkm_object_new_(engine->func->cclass, &cclass, NULL, 0, &ectx->object);

	if (ret)
		nvkm_cgrp_ectx_put(cgrp, pectx);

	return ret;
}

void
nvkm_cgrp_vctx_put(struct nvkm_cgrp *cgrp, struct nvkm_vctx **pvctx)
{
	struct nvkm_vctx *vctx = *pvctx;

	if (vctx) {
		struct nvkm_engn *engn = vctx->ectx->engn;

		if (refcount_dec_and_test(&vctx->refs)) {
			CGRP_TRACE(cgrp, "dtor vctx %d[%s]", engn->id, engn->engine->subdev.name);
			nvkm_vmm_put(vctx->vmm, &vctx->vma);
			nvkm_gpuobj_del(&vctx->inst);

			nvkm_cgrp_ectx_put(cgrp, &vctx->ectx);
			if (vctx->vmm) {
				atomic_dec(&vctx->vmm->engref[engn->engine->subdev.type]);
				nvkm_vmm_unref(&vctx->vmm);
			}
			list_del(&vctx->head);
			kfree(vctx);
		}

		*pvctx = NULL;
	}
}

int
nvkm_cgrp_vctx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_chan *chan,
		   struct nvkm_vctx **pvctx, struct nvkm_client *client)
{
	struct nvkm_ectx *ectx;
	struct nvkm_vctx *vctx;
	int ret;

	/* Look for an existing sub-context for this engine+VEID in the channel group. */
	vctx = nvkm_list_find(vctx, &cgrp->vctxs, head,
			      vctx->ectx->engn == engn && vctx->vmm == chan->vmm);

Annotation

Implementation Notes