aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/intc.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-10-05 05:13:23 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-10-05 05:13:23 -0400
commitd74310d3b18aabbb7d0549ea9e3fd3259c1dce00 (patch)
treed31d696a25aa22e8f2490edf287fe28c3a3b98d5 /drivers/sh/intc.c
parentc1e30ad98fe210688edca872686db4a715c2fb23 (diff)
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 <lethal@linux-sh.org>
Diffstat (limited to 'drivers/sh/intc.c')
-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,
927 return 0; 927 return 0;
928} 928}
929 929
930unsigned int intc_irq_lookup(const char *chipname, intc_enum enum_id) 930#define INTC_TAG_VIRQ_NEEDS_ALLOC 0
931
932int intc_irq_lookup(const char *chipname, intc_enum enum_id)
931{ 933{
932 struct intc_map_entry *ptr; 934 struct intc_map_entry *ptr;
933 struct intc_desc_int *d; 935 struct intc_desc_int *d;
934 unsigned int irq = 0; 936 int irq = -1;
935 937
936 list_for_each_entry(d, &intc_list, list) { 938 list_for_each_entry(d, &intc_list, list) {
937 if (strcmp(d->chip.name, chipname) == 0) { 939 int tagged;
938 ptr = radix_tree_lookup(&d->tree, enum_id); 940
939 if (ptr) { 941 if (strcmp(d->chip.name, chipname) != 0)
940 irq = ptr - intc_irq_xlate; 942 continue;
941 break; 943
942 } 944 /*
945 * Catch early lookups for subgroup VIRQs that have not
946 * yet been allocated an IRQ. This already includes a
947 * fast-path out if the tree is untagged, so there is no
948 * need to explicitly test the root tree.
949 */
950 tagged = radix_tree_tag_get(&d->tree, enum_id,
951 INTC_TAG_VIRQ_NEEDS_ALLOC);
952 if (unlikely(tagged))
953 break;
954
955 ptr = radix_tree_lookup(&d->tree, enum_id);
956 if (ptr) {
957 irq = ptr - intc_irq_xlate;
958 break;
943 } 959 }
944 } 960 }
945 961
@@ -1003,8 +1019,6 @@ static unsigned long __init intc_subgroup_data(struct intc_subgroup *subgroup,
1003 0, 1, (subgroup->reg_width - 1) - index); 1019 0, 1, (subgroup->reg_width - 1) - index);
1004} 1020}
1005 1021
1006#define INTC_TAG_VIRQ_NEEDS_ALLOC 0
1007
1008static void __init intc_subgroup_init_one(struct intc_desc *desc, 1022static void __init intc_subgroup_init_one(struct intc_desc *desc,
1009 struct intc_desc_int *d, 1023 struct intc_desc_int *d,
1010 struct intc_subgroup *subgroup) 1024 struct intc_subgroup *subgroup)