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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c
Extension
.c
Size
10671 bytes
Lines
419
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

struct nvkm_uchan {
	struct nvkm_object object;
	struct nvkm_chan *chan;
};

static int
nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
{
	struct nvkm_chan *chan = nvkm_uchan(object)->chan;
	struct nvkm_runl *runl = chan->cgrp->runl;
	union nvif_chan_event_args *args = argv;

	if (!uevent)
		return 0;
	if (argc != sizeof(args->v0) || args->v0.version != 0)
		return -ENOSYS;

	switch (args->v0.type) {
	case NVIF_CHAN_EVENT_V0_NON_STALL_INTR:
		return nvkm_uevent_add(uevent, &runl->fifo->nonstall.event, runl->id,
				       NVKM_FIFO_NONSTALL_EVENT, NULL);
	case NVIF_CHAN_EVENT_V0_KILLED:
		return nvkm_uevent_add(uevent, &runl->chid->event, chan->id,
				       NVKM_CHAN_EVENT_ERRORED, NULL);
	default:
		break;
	}

	return -ENOSYS;
}

struct nvkm_uobj {
	struct nvkm_oproxy oproxy;
	struct nvkm_chan *chan;
	struct nvkm_cctx *cctx;
	int hash;
};

static int
nvkm_uchan_object_fini_1(struct nvkm_oproxy *oproxy, enum nvkm_suspend_state suspend)
{
	struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy);
	struct nvkm_chan *chan = uobj->chan;
	struct nvkm_cctx *cctx = uobj->cctx;
	struct nvkm_ectx *ectx = cctx->vctx->ectx;

	if (!ectx->object)
		return 0;

	/* Unbind engine context from channel, if no longer required. */
	if (refcount_dec_and_mutex_lock(&cctx->uses, &chan->cgrp->mutex)) {
		nvkm_chan_cctx_bind(chan, ectx->engn, NULL);

		if (refcount_dec_and_test(&ectx->uses))
			nvkm_object_fini(ectx->object, NVKM_POWEROFF);
		mutex_unlock(&chan->cgrp->mutex);
	}

	return 0;
}

static int
nvkm_uchan_object_init_0(struct nvkm_oproxy *oproxy)
{
	struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy);
	struct nvkm_chan *chan = uobj->chan;
	struct nvkm_cctx *cctx = uobj->cctx;
	struct nvkm_ectx *ectx = cctx->vctx->ectx;
	int ret = 0;

	if (!ectx->object)
		return 0;

	/* Bind engine context to channel, if it hasn't been already. */
	if (!refcount_inc_not_zero(&cctx->uses)) {
		mutex_lock(&chan->cgrp->mutex);
		if (!refcount_inc_not_zero(&cctx->uses)) {
			if (!refcount_inc_not_zero(&ectx->uses)) {
				ret = nvkm_object_init(ectx->object);
				if (ret == 0)
					refcount_set(&ectx->uses, 1);
			}

			if (ret == 0) {
				nvkm_chan_cctx_bind(chan, ectx->engn, cctx);
				refcount_set(&cctx->uses, 1);
			}
		}
		mutex_unlock(&chan->cgrp->mutex);
	}

Annotation

Implementation Notes