drivers/sh/intc/virq.c

Source file repositories/reference/linux-study-clean/drivers/sh/intc/virq.c

File Facts

System
Linux kernel
Corpus path
drivers/sh/intc/virq.c
Extension
.c
Size
6350 bytes
Lines
270
Domain
Driver Families
Bucket
drivers/sh
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 intc_virq_list {
	unsigned int irq;
	struct intc_virq_list *next;
};

#define for_each_virq(entry, head) \
	for (entry = head; entry; entry = entry->next)

/*
 * Tags for the radix tree
 */
#define INTC_TAG_VIRQ_NEEDS_ALLOC	0

void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d)
{
	unsigned long flags;

	raw_spin_lock_irqsave(&intc_big_lock, flags);
	intc_irq_xlate[irq].enum_id = id;
	intc_irq_xlate[irq].desc = d;
	raw_spin_unlock_irqrestore(&intc_big_lock, flags);
}

struct intc_map_entry *intc_irq_xlate_get(unsigned int irq)
{
	return intc_irq_xlate + irq;
}

int intc_irq_lookup(const char *chipname, intc_enum enum_id)
{
	struct intc_map_entry *ptr;
	struct intc_desc_int *d;
	int irq = -1;

	list_for_each_entry(d, &intc_list, list) {
		int tagged;

		if (strcmp(d->chip.name, chipname) != 0)
			continue;

		/*
		 * Catch early lookups for subgroup VIRQs that have not
		 * yet been allocated an IRQ. This already includes a
		 * fast-path out if the tree is untagged, so there is no
		 * need to explicitly test the root tree.
		 */
		tagged = radix_tree_tag_get(&d->tree, enum_id,
					    INTC_TAG_VIRQ_NEEDS_ALLOC);
		if (unlikely(tagged))
			break;

		ptr = radix_tree_lookup(&d->tree, enum_id);
		if (ptr) {
			irq = ptr - intc_irq_xlate;
			break;
		}
	}

	return irq;
}
EXPORT_SYMBOL_GPL(intc_irq_lookup);

static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
{
	struct intc_virq_list *entry;
	struct intc_virq_list **last = NULL;

	/* scan for duplicates */
	for_each_virq(entry, irq_get_handler_data(irq)) {
		if (entry->irq == virq)
			return 0;
		last = &entry->next;
	}

	entry = kzalloc_obj(struct intc_virq_list, GFP_ATOMIC);
	if (!entry)
		return -ENOMEM;

	entry->irq = virq;

	if (last)
		*last = entry;
	else
		irq_set_handler_data(irq, entry);

	return 0;
}

static void intc_virq_handler(struct irq_desc *desc)
{

Annotation

Implementation Notes