aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/irq_ia64.c
diff options
context:
space:
mode:
authorYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>2007-07-17 08:22:23 -0400
committerTony Luck <tony.luck@intel.com>2007-07-17 12:51:49 -0400
commite1b30a392835e92581db09a4e8b4b2ad53a0c370 (patch)
tree1a0dacd37e682dc4c2222f415f8035057d6bbc30 /arch/ia64/kernel/irq_ia64.c
parentf8c087f31e1d3fbf1f7d0b3ea5e643f535e7de04 (diff)
[IA64] Add mapping table between irq and vector
Add mapping tables between irqs and vectors, and its management code. This is necessary for supporting multiple vector domain because 1:1 mapping between irq and vector will be changed to n:1. The irq == vector relationship between irqs and vectors is explicitly remained for percpu interrupts, platform interrupts, isa IRQs and vectors assigned using assign_irq_vector() because some programs might depend on it. And I should consider the following problem. When pci drivers enabled/disabled devices dynamically, its irq number is changed to the different one. Therefore, suspend/resume code may happen problem. To fix this problem, I bound gsi to irq. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/irq_ia64.c')
-rw-r--r--arch/ia64/kernel/irq_ia64.c201
1 files changed, 166 insertions, 35 deletions
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index bc47049f060f..072427c2c3f6 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -46,6 +46,12 @@
46 46
47#define IRQ_DEBUG 0 47#define IRQ_DEBUG 0
48 48
49#define IRQ_VECTOR_UNASSIGNED (0)
50
51#define IRQ_UNUSED (0)
52#define IRQ_USED (1)
53#define IRQ_RSVD (2)
54
49/* These can be overridden in platform_irq_init */ 55/* These can be overridden in platform_irq_init */
50int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; 56int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
51int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; 57int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
@@ -64,46 +70,161 @@ __u8 isa_irq_to_vector_map[16] = {
64}; 70};
65EXPORT_SYMBOL(isa_irq_to_vector_map); 71EXPORT_SYMBOL(isa_irq_to_vector_map);
66 72
67static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)]; 73DEFINE_SPINLOCK(vector_lock);
74
75struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
76 [0 ... NR_IRQS - 1] = { .vector = IRQ_VECTOR_UNASSIGNED }
77};
78
79DEFINE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq) = {
80 [0 ... IA64_NUM_VECTORS - 1] = IA64_SPURIOUS_INT_VECTOR
81};
82
83static int irq_status[NR_IRQS] = {
84 [0 ... NR_IRQS -1] = IRQ_UNUSED
85};
86
87int check_irq_used(int irq)
88{
89 if (irq_status[irq] == IRQ_USED)
90 return 1;
91
92 return -1;
93}
94
95static void reserve_irq(unsigned int irq)
96{
97 unsigned long flags;
98
99 spin_lock_irqsave(&vector_lock, flags);
100 irq_status[irq] = IRQ_RSVD;
101 spin_unlock_irqrestore(&vector_lock, flags);
102}
103
104static inline int find_unassigned_irq(void)
105{
106 int irq;
107
108 for (irq = IA64_FIRST_DEVICE_VECTOR; irq < NR_IRQS; irq++)
109 if (irq_status[irq] == IRQ_UNUSED)
110 return irq;
111 return -ENOSPC;
112}
113
114static inline int find_unassigned_vector(void)
115{
116 int vector;
117
118 for (vector = IA64_FIRST_DEVICE_VECTOR;
119 vector <= IA64_LAST_DEVICE_VECTOR; vector++)
120 if (__get_cpu_var(vector_irq[vector]) == IA64_SPURIOUS_INT_VECTOR)
121 return vector;
122 return -ENOSPC;
123}
124
125static int __bind_irq_vector(int irq, int vector)
126{
127 int cpu;
128
129 if (irq_to_vector(irq) == vector)
130 return 0;
131 if (irq_to_vector(irq) != IRQ_VECTOR_UNASSIGNED)
132 return -EBUSY;
133 for_each_online_cpu(cpu)
134 per_cpu(vector_irq, cpu)[vector] = irq;
135 irq_cfg[irq].vector = vector;
136 irq_status[irq] = IRQ_USED;
137 return 0;
138}
139
140int bind_irq_vector(int irq, int vector)
141{
142 unsigned long flags;
143 int ret;
144
145 spin_lock_irqsave(&vector_lock, flags);
146 ret = __bind_irq_vector(irq, vector);
147 spin_unlock_irqrestore(&vector_lock, flags);
148 return ret;
149}
150
151static void clear_irq_vector(int irq)
152{
153 unsigned long flags;
154 int vector, cpu;
155
156 spin_lock_irqsave(&vector_lock, flags);
157 BUG_ON((unsigned)irq >= NR_IRQS);
158 BUG_ON(irq_cfg[irq].vector == IRQ_VECTOR_UNASSIGNED);
159 vector = irq_cfg[irq].vector;
160 for_each_online_cpu(cpu)
161 per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR;
162 irq_cfg[irq].vector = IRQ_VECTOR_UNASSIGNED;
163 irq_status[irq] = IRQ_UNUSED;
164 spin_unlock_irqrestore(&vector_lock, flags);
165}
68 166
69int 167int
70assign_irq_vector (int irq) 168assign_irq_vector (int irq)
71{ 169{
72 int pos, vector; 170 unsigned long flags;
73 again: 171 int vector = -ENOSPC;
74 pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS); 172
75 vector = IA64_FIRST_DEVICE_VECTOR + pos; 173 if (irq < 0) {
76 if (vector > IA64_LAST_DEVICE_VECTOR) 174 goto out;
77 return -ENOSPC; 175 }
78 if (test_and_set_bit(pos, ia64_vector_mask)) 176 spin_lock_irqsave(&vector_lock, flags);
79 goto again; 177 vector = find_unassigned_vector();
178 if (vector < 0)
179 goto out;
180 BUG_ON(__bind_irq_vector(irq, vector));
181 spin_unlock_irqrestore(&vector_lock, flags);
182 out:
80 return vector; 183 return vector;
81} 184}
82 185
83void 186void
84free_irq_vector (int vector) 187free_irq_vector (int vector)
85{ 188{
86 int pos; 189 if (vector < IA64_FIRST_DEVICE_VECTOR ||
87 190 vector > IA64_LAST_DEVICE_VECTOR)
88 if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR)
89 return; 191 return;
90 192 clear_irq_vector(vector);
91 pos = vector - IA64_FIRST_DEVICE_VECTOR;
92 if (!test_and_clear_bit(pos, ia64_vector_mask))
93 printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
94} 193}
95 194
96int 195int
97reserve_irq_vector (int vector) 196reserve_irq_vector (int vector)
98{ 197{
99 int pos;
100
101 if (vector < IA64_FIRST_DEVICE_VECTOR || 198 if (vector < IA64_FIRST_DEVICE_VECTOR ||
102 vector > IA64_LAST_DEVICE_VECTOR) 199 vector > IA64_LAST_DEVICE_VECTOR)
103 return -EINVAL; 200 return -EINVAL;
201 return !!bind_irq_vector(vector, vector);
202}
104 203
105 pos = vector - IA64_FIRST_DEVICE_VECTOR; 204/*
106 return test_and_set_bit(pos, ia64_vector_mask); 205 * Initialize vector_irq on a new cpu. This function must be called
206 * with vector_lock held.
207 */
208void __setup_vector_irq(int cpu)
209{
210 int irq, vector;
211
212 /* Clear vector_irq */
213 for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
214 per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR;
215 /* Mark the inuse vectors */
216 for (irq = 0; irq < NR_IRQS; ++irq) {
217 if ((vector = irq_to_vector(irq)) != IRQ_VECTOR_UNASSIGNED)
218 per_cpu(vector_irq, cpu)[vector] = irq;
219 }
220}
221
222void destroy_and_reserve_irq(unsigned int irq)
223{
224 dynamic_irq_cleanup(irq);
225
226 clear_irq_vector(irq);
227 reserve_irq(irq);
107} 228}
108 229
109/* 230/*
@@ -111,18 +232,29 @@ reserve_irq_vector (int vector)
111 */ 232 */
112int create_irq(void) 233int create_irq(void)
113{ 234{
114 int vector = assign_irq_vector(AUTO_ASSIGN); 235 unsigned long flags;
115 236 int irq, vector;
116 if (vector >= 0) 237
117 dynamic_irq_init(vector); 238 irq = -ENOSPC;
118 239 spin_lock_irqsave(&vector_lock, flags);
119 return vector; 240 vector = find_unassigned_vector();
241 if (vector < 0)
242 goto out;
243 irq = find_unassigned_irq();
244 if (irq < 0)
245 goto out;
246 BUG_ON(__bind_irq_vector(irq, vector));
247 out:
248 spin_unlock_irqrestore(&vector_lock, flags);
249 if (irq >= 0)
250 dynamic_irq_init(irq);
251 return irq;
120} 252}
121 253
122void destroy_irq(unsigned int irq) 254void destroy_irq(unsigned int irq)
123{ 255{
124 dynamic_irq_cleanup(irq); 256 dynamic_irq_cleanup(irq);
125 free_irq_vector(irq); 257 clear_irq_vector(irq);
126} 258}
127 259
128#ifdef CONFIG_SMP 260#ifdef CONFIG_SMP
@@ -301,14 +433,13 @@ register_percpu_irq (ia64_vector vec, struct irqaction *action)
301 irq_desc_t *desc; 433 irq_desc_t *desc;
302 unsigned int irq; 434 unsigned int irq;
303 435
304 for (irq = 0; irq < NR_IRQS; ++irq) 436 irq = vec;
305 if (irq_to_vector(irq) == vec) { 437 BUG_ON(bind_irq_vector(irq, vec));
306 desc = irq_desc + irq; 438 desc = irq_desc + irq;
307 desc->status |= IRQ_PER_CPU; 439 desc->status |= IRQ_PER_CPU;
308 desc->chip = &irq_type_ia64_lsapic; 440 desc->chip = &irq_type_ia64_lsapic;
309 if (action) 441 if (action)
310 setup_irq(irq, action); 442 setup_irq(irq, action);
311 }
312} 443}
313 444
314void __init 445void __init