diff options
author | Nishanth Menon <nm@ti.com> | 2014-06-26 03:10:20 -0400 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-06-30 15:11:17 -0400 |
commit | 6f16fc878a51572a998655e5ef1c396cb269648d (patch) | |
tree | e97ef38d5c8a50c26dc9eefb8648700f81cf27b4 /drivers/irqchip | |
parent | 1d50d2ce6337724d30055bdbe082236cc86e6785 (diff) |
irqchip: crossbar: Check for premapped crossbar before allocating
If irq_of_parse_and_map is executed twice, the same crossbar is mapped to two
different GIC interrupts. This is completely undesirable. Instead, check
if the requested crossbar event is pre-allocated and provide that GIC
mapping back to caller if already allocated.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Sricharan R <r.sricharan@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Link: https://lkml.kernel.org/r/1403766634-18543-3-git-send-email-r.sricharan@ti.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-crossbar.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index 20105bcdf408..51d4b878e5d6 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c | |||
@@ -51,6 +51,17 @@ static inline void crossbar_writeb(int irq_no, int cb_no) | |||
51 | writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); | 51 | writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); |
52 | } | 52 | } |
53 | 53 | ||
54 | static inline int get_prev_map_irq(int cb_no) | ||
55 | { | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < cb->int_max; i++) | ||
59 | if (cb->irq_map[i] == cb_no) | ||
60 | return i; | ||
61 | |||
62 | return -ENODEV; | ||
63 | } | ||
64 | |||
54 | static inline int allocate_free_irq(int cb_no) | 65 | static inline int allocate_free_irq(int cb_no) |
55 | { | 66 | { |
56 | int i; | 67 | int i; |
@@ -88,11 +99,16 @@ static int crossbar_domain_xlate(struct irq_domain *d, | |||
88 | { | 99 | { |
89 | unsigned long ret; | 100 | unsigned long ret; |
90 | 101 | ||
102 | ret = get_prev_map_irq(intspec[1]); | ||
103 | if (!IS_ERR_VALUE(ret)) | ||
104 | goto found; | ||
105 | |||
91 | ret = allocate_free_irq(intspec[1]); | 106 | ret = allocate_free_irq(intspec[1]); |
92 | 107 | ||
93 | if (IS_ERR_VALUE(ret)) | 108 | if (IS_ERR_VALUE(ret)) |
94 | return ret; | 109 | return ret; |
95 | 110 | ||
111 | found: | ||
96 | *out_hwirq = ret + GIC_IRQ_START; | 112 | *out_hwirq = ret + GIC_IRQ_START; |
97 | return 0; | 113 | return 0; |
98 | } | 114 | } |