drivers/gpu/drm/nouveau/nouveau_chan.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nouveau_chan.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nouveau_chan.c
Extension
.c
Size
16740 bytes
Lines
580
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 (!ret) {
			ret = nouveau_fence_wait(fence, false, false);
			nouveau_fence_unref(&fence);
		}

		if (ret) {
			NV_PRINTK(err, cli, "failed to idle channel %d [%s]\n",
				  chan->chid, cli->name);
			return ret;
		}
	}
	return 0;
}

void
nouveau_channel_del(struct nouveau_channel **pchan)
{
	struct nouveau_channel *chan = *pchan;
	if (chan) {
		if (chan->fence)
			nouveau_fence(chan->cli->drm)->context_del(chan);

		if (nvif_object_constructed(&chan->user))
			nouveau_svmm_part(chan->vmm->svmm, chan->inst);

		nvif_object_dtor(&chan->blit);
		nvif_object_dtor(&chan->nvsw);
		nvif_object_dtor(&chan->gart);
		nvif_object_dtor(&chan->vram);
		nvif_event_dtor(&chan->kill);
		nvif_object_dtor(&chan->user);
		nvif_mem_dtor(&chan->mem_userd);
		nouveau_vma_del(&chan->sema.vma);
		nouveau_bo_unpin_del(&chan->sema.bo);
		nvif_object_dtor(&chan->push.ctxdma);
		nouveau_vma_del(&chan->push.vma);
		nouveau_bo_unpin_del(&chan->push.buffer);
		kfree(chan);
	}
	*pchan = NULL;
}

static void
nouveau_channel_kick(struct nvif_push *push)
{
	struct nouveau_channel *chan = container_of(push, typeof(*chan), chan.push);
	chan->dma.cur = chan->dma.cur + (chan->chan.push.cur - chan->chan.push.bgn);
	FIRE_RING(chan);
	chan->chan.push.bgn = chan->chan.push.cur;
}

static int
nouveau_channel_wait(struct nvif_push *push, u32 size)
{
	struct nouveau_channel *chan = container_of(push, typeof(*chan), chan.push);
	int ret;
	chan->dma.cur = chan->dma.cur + (chan->chan.push.cur - chan->chan.push.bgn);
	ret = RING_SPACE(chan, size);
	if (ret == 0) {
		chan->chan.push.bgn = chan->chan.push.mem.object.map.ptr;
		chan->chan.push.bgn = chan->chan.push.bgn + chan->dma.cur;
		chan->chan.push.cur = chan->chan.push.bgn;
		chan->chan.push.end = chan->chan.push.bgn + size;
	}
	return ret;
}

static int
nouveau_channel_prep(struct nouveau_cli *cli,
		     u32 size, struct nouveau_channel **pchan)
{
	struct nouveau_drm *drm = cli->drm;
	struct nvif_device *device = &cli->device;
	struct nv_dma_v0 args = {};
	struct nouveau_channel *chan;
	u32 target;
	int ret;

	chan = *pchan = kzalloc_obj(*chan);
	if (!chan)
		return -ENOMEM;

	chan->cli = cli;
	chan->vmm = nouveau_cli_vmm(cli);
	atomic_set(&chan->killed, 0);

	/* allocate memory for dma push buffer */
	target = NOUVEAU_GEM_DOMAIN_GART | NOUVEAU_GEM_DOMAIN_COHERENT;
	if (nouveau_vram_pushbuf)
		target = NOUVEAU_GEM_DOMAIN_VRAM;

Annotation

Implementation Notes