aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/irqdesc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/irqdesc.c')
-rw-r--r--kernel/irq/irqdesc.c86
1 files changed, 51 insertions, 35 deletions
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 282f20230e67..2c039c9b9383 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -79,7 +79,8 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
79 desc->irq_data.chip_data = NULL; 79 desc->irq_data.chip_data = NULL;
80 desc->irq_data.handler_data = NULL; 80 desc->irq_data.handler_data = NULL;
81 desc->irq_data.msi_desc = NULL; 81 desc->irq_data.msi_desc = NULL;
82 desc->status = IRQ_DEFAULT_INIT_FLAGS; 82 irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
83 irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
83 desc->handle_irq = handle_bad_irq; 84 desc->handle_irq = handle_bad_irq;
84 desc->depth = 1; 85 desc->depth = 1;
85 desc->irq_count = 0; 86 desc->irq_count = 0;
@@ -94,7 +95,7 @@ int nr_irqs = NR_IRQS;
94EXPORT_SYMBOL_GPL(nr_irqs); 95EXPORT_SYMBOL_GPL(nr_irqs);
95 96
96static DEFINE_MUTEX(sparse_irq_lock); 97static DEFINE_MUTEX(sparse_irq_lock);
97static DECLARE_BITMAP(allocated_irqs, NR_IRQS); 98static DECLARE_BITMAP(allocated_irqs, IRQ_BITMAP_BITS);
98 99
99#ifdef CONFIG_SPARSE_IRQ 100#ifdef CONFIG_SPARSE_IRQ
100 101
@@ -197,13 +198,12 @@ err:
197 return -ENOMEM; 198 return -ENOMEM;
198} 199}
199 200
200struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) 201static int irq_expand_nr_irqs(unsigned int nr)
201{ 202{
202 int res = irq_alloc_descs(irq, irq, 1, node); 203 if (nr > IRQ_BITMAP_BITS)
203 204 return -ENOMEM;
204 if (res == -EEXIST || res == irq) 205 nr_irqs = nr;
205 return irq_to_desc(irq); 206 return 0;
206 return NULL;
207} 207}
208 208
209int __init early_irq_init(void) 209int __init early_irq_init(void)
@@ -217,6 +217,15 @@ int __init early_irq_init(void)
217 initcnt = arch_probe_nr_irqs(); 217 initcnt = arch_probe_nr_irqs();
218 printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d %d\n", NR_IRQS, nr_irqs, initcnt); 218 printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d %d\n", NR_IRQS, nr_irqs, initcnt);
219 219
220 if (WARN_ON(nr_irqs > IRQ_BITMAP_BITS))
221 nr_irqs = IRQ_BITMAP_BITS;
222
223 if (WARN_ON(initcnt > IRQ_BITMAP_BITS))
224 initcnt = IRQ_BITMAP_BITS;
225
226 if (initcnt > nr_irqs)
227 nr_irqs = initcnt;
228
220 for (i = 0; i < initcnt; i++) { 229 for (i = 0; i < initcnt; i++) {
221 desc = alloc_desc(i, node); 230 desc = alloc_desc(i, node);
222 set_bit(i, allocated_irqs); 231 set_bit(i, allocated_irqs);
@@ -229,7 +238,6 @@ int __init early_irq_init(void)
229 238
230struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { 239struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
231 [0 ... NR_IRQS-1] = { 240 [0 ... NR_IRQS-1] = {
232 .status = IRQ_DEFAULT_INIT_FLAGS,
233 .handle_irq = handle_bad_irq, 241 .handle_irq = handle_bad_irq,
234 .depth = 1, 242 .depth = 1,
235 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), 243 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
@@ -251,8 +259,8 @@ int __init early_irq_init(void)
251 for (i = 0; i < count; i++) { 259 for (i = 0; i < count; i++) {
252 desc[i].irq_data.irq = i; 260 desc[i].irq_data.irq = i;
253 desc[i].irq_data.chip = &no_irq_chip; 261 desc[i].irq_data.chip = &no_irq_chip;
254 /* TODO : do this allocation on-demand ... */
255 desc[i].kstat_irqs = alloc_percpu(unsigned int); 262 desc[i].kstat_irqs = alloc_percpu(unsigned int);
263 irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
256 alloc_masks(desc + i, GFP_KERNEL, node); 264 alloc_masks(desc + i, GFP_KERNEL, node);
257 desc_smp_init(desc + i, node); 265 desc_smp_init(desc + i, node);
258 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); 266 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
@@ -265,11 +273,6 @@ struct irq_desc *irq_to_desc(unsigned int irq)
265 return (irq < NR_IRQS) ? irq_desc + irq : NULL; 273 return (irq < NR_IRQS) ? irq_desc + irq : NULL;
266} 274}
267 275
268struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
269{
270 return irq_to_desc(irq);
271}
272
273static void free_desc(unsigned int irq) 276static void free_desc(unsigned int irq)
274{ 277{
275 dynamic_irq_cleanup(irq); 278 dynamic_irq_cleanup(irq);
@@ -277,24 +280,14 @@ static void free_desc(unsigned int irq)
277 280
278static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) 281static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
279{ 282{
280#if defined(CONFIG_KSTAT_IRQS_ONDEMAND)
281 struct irq_desc *desc;
282 unsigned int i;
283
284 for (i = 0; i < cnt; i++) {
285 desc = irq_to_desc(start + i);
286 if (desc && !desc->kstat_irqs) {
287 unsigned int __percpu *stats = alloc_percpu(unsigned int);
288
289 if (!stats)
290 return -1;
291 if (cmpxchg(&desc->kstat_irqs, NULL, stats) != NULL)
292 free_percpu(stats);
293 }
294 }
295#endif
296 return start; 283 return start;
297} 284}
285
286static int irq_expand_nr_irqs(unsigned int nr)
287{
288 return -ENOMEM;
289}
290
298#endif /* !CONFIG_SPARSE_IRQ */ 291#endif /* !CONFIG_SPARSE_IRQ */
299 292
300/* Dynamic interrupt handling */ 293/* Dynamic interrupt handling */
@@ -338,14 +331,17 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
338 331
339 mutex_lock(&sparse_irq_lock); 332 mutex_lock(&sparse_irq_lock);
340 333
341 start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0); 334 start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
335 from, cnt, 0);
342 ret = -EEXIST; 336 ret = -EEXIST;
343 if (irq >=0 && start != irq) 337 if (irq >=0 && start != irq)
344 goto err; 338 goto err;
345 339
346 ret = -ENOMEM; 340 if (start + cnt > nr_irqs) {
347 if (start >= nr_irqs) 341 ret = irq_expand_nr_irqs(start + cnt);
348 goto err; 342 if (ret)
343 goto err;
344 }
349 345
350 bitmap_set(allocated_irqs, start, cnt); 346 bitmap_set(allocated_irqs, start, cnt);
351 mutex_unlock(&sparse_irq_lock); 347 mutex_unlock(&sparse_irq_lock);
@@ -392,6 +388,26 @@ unsigned int irq_get_next_irq(unsigned int offset)
392 return find_next_bit(allocated_irqs, nr_irqs, offset); 388 return find_next_bit(allocated_irqs, nr_irqs, offset);
393} 389}
394 390
391struct irq_desc *
392__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus)
393{
394 struct irq_desc *desc = irq_to_desc(irq);
395
396 if (desc) {
397 if (bus)
398 chip_bus_lock(desc);
399 raw_spin_lock_irqsave(&desc->lock, *flags);
400 }
401 return desc;
402}
403
404void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus)
405{
406 raw_spin_unlock_irqrestore(&desc->lock, flags);
407 if (bus)
408 chip_bus_sync_unlock(desc);
409}
410
395/** 411/**
396 * dynamic_irq_cleanup - cleanup a dynamically allocated irq 412 * dynamic_irq_cleanup - cleanup a dynamically allocated irq
397 * @irq: irq number to initialize 413 * @irq: irq number to initialize