aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/sh/intc.c34
-rw-r--r--include/linux/sh_intc.h2
2 files changed, 25 insertions, 11 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index c81fe23..d4325c7 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)
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
index 04134a6..1fc6970 100644
--- a/include/linux/sh_intc.h
+++ b/include/linux/sh_intc.h
@@ -117,7 +117,7 @@ struct intc_desc symbol __initdata = { \
int __init register_intc_controller(struct intc_desc *desc);
void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs);
int intc_set_priority(unsigned int irq, unsigned int prio);
-unsigned int intc_irq_lookup(const char *chipname, intc_enum enum_id);
+int intc_irq_lookup(const char *chipname, intc_enum enum_id);
void intc_finalize(void);
#ifdef CONFIG_INTC_USERIMASK