summaryrefslogtreecommitdiff
path: root/drivers/sh
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sh')
-rw-r--r--drivers/sh/intc.c34
1 files changed, 24 insertions, 10 deletions
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)