From d74310d3b18aabbb7d0549ea9e3fd3259c1dce00 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 5 Oct 2010 18:13:23 +0900 Subject: sh: intc: Handle early lookups of subgroup IRQs. If lookups happen while the radix node still points to a subgroup mapping, an IRQ hasn't yet been made available for the specified id, so error out accordingly. Once the slot is replaced with an IRQ mapping and the tag is discarded, lookup can commence as normal. Signed-off-by: Paul Mundt --- drivers/sh/intc.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'drivers/sh') diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index c81fe23db7f7..d4325c70cf61 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -927,19 +927,35 @@ static unsigned int __init intc_sense_data(struct intc_desc *desc, return 0; } -unsigned int intc_irq_lookup(const char *chipname, intc_enum enum_id) +#define INTC_TAG_VIRQ_NEEDS_ALLOC 0 + +int intc_irq_lookup(const char *chipname, intc_enum enum_id) { struct intc_map_entry *ptr; struct intc_desc_int *d; - unsigned int irq = 0; + int irq = -1; list_for_each_entry(d, &intc_list, list) { - if (strcmp(d->chip.name, chipname) == 0) { - ptr = radix_tree_lookup(&d->tree, enum_id); - if (ptr) { - irq = ptr - intc_irq_xlate; - break; - } + 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; } } @@ -1003,8 +1019,6 @@ static unsigned long __init intc_subgroup_data(struct intc_subgroup *subgroup, 0, 1, (subgroup->reg_width - 1) - index); } -#define INTC_TAG_VIRQ_NEEDS_ALLOC 0 - static void __init intc_subgroup_init_one(struct intc_desc *desc, struct intc_desc_int *d, struct intc_subgroup *subgroup) -- cgit v1.2.1