Source
x
/*
* Support for virtual IRQ subgroups.
*
* Copyright (C) 2010 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
static struct intc_map_entry intc_irq_xlate[INTC_NR_IRQS];
struct intc_virq_list {
unsigned int irq;
struct intc_virq_list *next;
};
/*
* Tags for the radix tree
*/
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;