drivers/gpu/drm/nouveau/nvkm/core/intr.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/core/intr.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/core/intr.c
Extension
.c
Size
10997 bytes
Lines
443
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 (type == NVKM_INTR_SUBDEV) {
			const struct nvkm_intr_data *data = intr->data;
			struct nvkm_top_device *tdev;

			while (data && data->mask) {
				if (data->type == NVKM_SUBDEV_TOP) {
					list_for_each_entry(tdev, &device->top->device, head) {
						if (tdev->intr >= 0 &&
						    tdev->type == subdev->type &&
						    tdev->inst == subdev->inst) {
							if (data->mask & BIT(tdev->intr)) {
								*leaf = data->leaf;
								*mask = BIT(tdev->intr);
								return 0;
							}
						}
					}
				} else
				if (data->type == subdev->type && data->inst == subdev->inst) {
					*leaf = data->leaf;
					*mask = data->mask;
					return 0;
				}

				data++;
			}
		} else {
			return -ENOSYS;
		}
	} else {
		if (type < intr->leaves * sizeof(*intr->stat) * 8) {
			*leaf = type / 32;
			*mask = BIT(type % 32);
			return 0;
		}
	}

	return -EINVAL;
}

static struct nvkm_intr *
nvkm_intr_find(struct nvkm_subdev *subdev, enum nvkm_intr_type type, int *leaf, u32 *mask)
{
	struct nvkm_intr *intr;
	int ret;

	list_for_each_entry(intr, &subdev->device->intr.intr, head) {
		ret = nvkm_intr_xlat(subdev, intr, type, leaf, mask);
		if (ret == 0)
			return intr;
	}

	return NULL;
}

static void
nvkm_intr_allow_locked(struct nvkm_intr *intr, int leaf, u32 mask)
{
	intr->mask[leaf] |= mask;
	if (intr->func->allow) {
		if (intr->func->reset)
			intr->func->reset(intr, leaf, mask);
		intr->func->allow(intr, leaf, mask);
	}
}

void
nvkm_intr_allow(struct nvkm_subdev *subdev, enum nvkm_intr_type type)
{
	struct nvkm_device *device = subdev->device;
	struct nvkm_intr *intr;
	unsigned long flags;
	int leaf;
	u32 mask;

	intr = nvkm_intr_find(subdev, type, &leaf, &mask);
	if (intr) {
		nvkm_debug(intr->subdev, "intr %d/%08x allowed by %s\n", leaf, mask, subdev->name);
		spin_lock_irqsave(&device->intr.lock, flags);
		nvkm_intr_allow_locked(intr, leaf, mask);
		spin_unlock_irqrestore(&device->intr.lock, flags);
	}
}

static void
nvkm_intr_block_locked(struct nvkm_intr *intr, int leaf, u32 mask)
{
	intr->mask[leaf] &= ~mask;
	if (intr->func->block)
		intr->func->block(intr, leaf, mask);

Annotation

Implementation Notes