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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
Extension
.c
Size
12038 bytes
Lines
483
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_mutex_lock(&cctx->refs, &chan->cgrp->mutex)) {
			CHAN_TRACE(chan, "dtor cctx %d[%s]", engn->id, engn->engine->subdev.name);
			nvkm_cgrp_vctx_put(chan->cgrp, &cctx->vctx);
			list_del(&cctx->head);
			kfree(cctx);
			mutex_unlock(&chan->cgrp->mutex);
		}

		*pcctx = NULL;
	}
}

int
nvkm_chan_cctx_get(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_cctx **pcctx,
		   struct nvkm_client *client)
{
	struct nvkm_cgrp *cgrp = chan->cgrp;
	struct nvkm_vctx *vctx;
	struct nvkm_cctx *cctx;
	int ret;

	/* Look for an existing channel context for this engine+VEID. */
	mutex_lock(&cgrp->mutex);
	cctx = nvkm_list_find(cctx, &chan->cctxs, head,
			      cctx->vctx->ectx->engn == engn && cctx->vctx->vmm == chan->vmm);
	if (cctx) {
		refcount_inc(&cctx->refs);
		*pcctx = cctx;
		mutex_unlock(&cgrp->mutex);
		return 0;
	}

	/* Nope - create a fresh one.  But, sub-context first. */
	ret = nvkm_cgrp_vctx_get(cgrp, engn, chan, &vctx, client);
	if (ret) {
		CHAN_ERROR(chan, "vctx %d[%s]: %d", engn->id, engn->engine->subdev.name, ret);
		goto done;
	}

	/* Now, create the channel context - to track engine binding. */
	CHAN_TRACE(chan, "ctor cctx %d[%s]", engn->id, engn->engine->subdev.name);
	if (!(cctx = *pcctx = kzalloc_obj(*cctx))) {
		nvkm_cgrp_vctx_put(cgrp, &vctx);
		ret = -ENOMEM;
		goto done;
	}

	cctx->vctx = vctx;
	refcount_set(&cctx->refs, 1);
	refcount_set(&cctx->uses, 0);
	list_add_tail(&cctx->head, &chan->cctxs);
done:
	mutex_unlock(&cgrp->mutex);
	return ret;
}

int
nvkm_chan_preempt_locked(struct nvkm_chan *chan, bool wait)
{
	struct nvkm_runl *runl = chan->cgrp->runl;

	CHAN_TRACE(chan, "preempt");
	chan->func->preempt(chan);
	if (!wait)
		return 0;

	return nvkm_runl_preempt_wait(runl);
}

int
nvkm_chan_preempt(struct nvkm_chan *chan, bool wait)
{
	int ret;

	if (!chan->func->preempt)
		return 0;

	mutex_lock(&chan->cgrp->runl->mutex);
	ret = nvkm_chan_preempt_locked(chan, wait);
	mutex_unlock(&chan->cgrp->runl->mutex);
	return ret;
}

void
nvkm_chan_remove_locked(struct nvkm_chan *chan)
{
	struct nvkm_cgrp *cgrp = chan->cgrp;
	struct nvkm_runl *runl = cgrp->runl;

	if (list_empty(&chan->head))

Annotation

Implementation Notes