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

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

File Facts

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

#include "chid.h"

void
nvkm_chid_put(struct nvkm_chid *chid, int id, spinlock_t *data_lock)
{
	if (id >= 0) {
		spin_lock_irq(&chid->lock);
		spin_lock(data_lock);
		chid->data[id] = NULL;
		spin_unlock(data_lock);
		clear_bit(id, chid->used);
		spin_unlock_irq(&chid->lock);
	}
}

int
nvkm_chid_get(struct nvkm_chid *chid, void *data)
{
	int id = -1, cid;

	spin_lock_irq(&chid->lock);
	cid = find_first_zero_bit(chid->used, chid->nr);
	if (cid < chid->nr) {
		set_bit(cid, chid->used);
		chid->data[cid] = data;
		id = cid;
	}
	spin_unlock_irq(&chid->lock);
	return id;
}

static void
nvkm_chid_del(struct kref *kref)
{
	struct nvkm_chid *chid = container_of(kref, typeof(*chid), kref);

	nvkm_event_fini(&chid->event);

	kvfree(chid->data);
	kfree(chid);
}

void
nvkm_chid_unref(struct nvkm_chid **pchid)
{
	struct nvkm_chid *chid = *pchid;

	if (!chid)
		return;

	kref_put(&chid->kref, nvkm_chid_del);
	*pchid = NULL;
}

struct nvkm_chid *
nvkm_chid_ref(struct nvkm_chid *chid)
{
	if (chid)
		kref_get(&chid->kref);

	return chid;
}

int
nvkm_chid_new(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
	      int nr, int first, int count, struct nvkm_chid **pchid)
{
	struct nvkm_chid *chid;
	int id;

	if (!(chid = *pchid = kzalloc_flex(*chid, used, nr)))
		return -ENOMEM;

	kref_init(&chid->kref);
	chid->nr = nr;
	chid->mask = chid->nr - 1;
	spin_lock_init(&chid->lock);

	if (!(chid->data = kvzalloc(sizeof(*chid->data) * nr, GFP_KERNEL))) {
		nvkm_chid_unref(pchid);
		return -ENOMEM;
	}

	for (id = 0; id < first; id++)
		__set_bit(id, chid->used);
	for (id = first + count; id < nr; id++)
		__set_bit(id, chid->used);

	return nvkm_event_init(func, subdev, 1, nr, &chid->event);
}

Annotation

Implementation Notes