drivers/gpu/host1x/intr.c

Source file repositories/reference/linux-study-clean/drivers/gpu/host1x/intr.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/host1x/intr.c
Extension
.c
Size
3897 bytes
Lines
160
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 ((s32)(fence_in_list->threshold - fence->threshold) <= 0) {
			/* Fence in list is before us, we can insert here */
			list_add(&fence->list, &fence_in_list->list);
			return;
		}
	}

	/* Add as first in list */
	list_add(&fence->list, &list->list);
}

static void host1x_intr_update_hw_state(struct host1x *host, struct host1x_syncpt *sp)
{
	struct host1x_syncpt_fence *fence;

	if (!list_empty(&sp->fences.list)) {
		fence = list_first_entry(&sp->fences.list, struct host1x_syncpt_fence, list);

		host1x_hw_intr_set_syncpt_threshold(host, sp->id, fence->threshold);
		host1x_hw_intr_enable_syncpt_intr(host, sp->id);
	} else {
		host1x_hw_intr_disable_syncpt_intr(host, sp->id);
	}
}

void host1x_intr_add_fence_locked(struct host1x *host, struct host1x_syncpt_fence *fence)
{
	struct host1x_fence_list *fence_list = &fence->sp->fences;

	INIT_LIST_HEAD(&fence->list);

	host1x_intr_add_fence_to_list(fence_list, fence);
	host1x_intr_update_hw_state(host, fence->sp);
}

bool host1x_intr_remove_fence(struct host1x *host, struct host1x_syncpt_fence *fence)
{
	struct host1x_fence_list *fence_list = &fence->sp->fences;
	unsigned long irqflags;

	spin_lock_irqsave(&fence_list->lock, irqflags);

	if (list_empty(&fence->list)) {
		spin_unlock_irqrestore(&fence_list->lock, irqflags);
		return false;
	}

	list_del_init(&fence->list);
	host1x_intr_update_hw_state(host, fence->sp);

	spin_unlock_irqrestore(&fence_list->lock, irqflags);

	return true;
}

void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id)
{
	struct host1x_syncpt *sp = &host->syncpt[id];
	struct host1x_syncpt_fence *fence, *tmp;
	unsigned int value;

	value = host1x_syncpt_load(sp);

	spin_lock(&sp->fences.lock);

	list_for_each_entry_safe(fence, tmp, &sp->fences.list, list) {
		if (((value - fence->threshold) & 0x80000000U) != 0U) {
			/* Fence is not yet expired, we are done */
			break;
		}

		list_del_init(&fence->list);
		host1x_fence_signal(fence);
	}

	/*
	 * Re-enable interrupt if necessary. The ISR already disabled the interrupt,
	 * so if no fences remain, no update is needed.
	 */
	if (!list_empty(&sp->fences.list))
		host1x_intr_update_hw_state(host, sp);

	spin_unlock(&sp->fences.lock);
}

int host1x_intr_init(struct host1x *host)
{
	struct host1x_intr_irq_data *irq_data;
	unsigned int id;
	int i, err;

Annotation

Implementation Notes