diff options
Diffstat (limited to 'kernel/irq/irqdesc.c')
-rw-r--r-- | kernel/irq/irqdesc.c | 68 |
1 files changed, 45 insertions, 23 deletions
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 2039bea31bdf..dbccc799407f 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 | desc->istate = IRQS_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; |
@@ -206,6 +207,14 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) | |||
206 | return NULL; | 207 | return NULL; |
207 | } | 208 | } |
208 | 209 | ||
210 | static int irq_expand_nr_irqs(unsigned int nr) | ||
211 | { | ||
212 | if (nr > IRQ_BITMAP_BITS) | ||
213 | return -ENOMEM; | ||
214 | nr_irqs = nr; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
209 | int __init early_irq_init(void) | 218 | int __init early_irq_init(void) |
210 | { | 219 | { |
211 | int i, initcnt, node = first_online_node; | 220 | int i, initcnt, node = first_online_node; |
@@ -238,7 +247,7 @@ int __init early_irq_init(void) | |||
238 | 247 | ||
239 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 248 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { |
240 | [0 ... NR_IRQS-1] = { | 249 | [0 ... NR_IRQS-1] = { |
241 | .status = IRQ_DEFAULT_INIT_FLAGS, | 250 | .istate = IRQS_DISABLED, |
242 | .handle_irq = handle_bad_irq, | 251 | .handle_irq = handle_bad_irq, |
243 | .depth = 1, | 252 | .depth = 1, |
244 | .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), | 253 | .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), |
@@ -260,8 +269,8 @@ int __init early_irq_init(void) | |||
260 | for (i = 0; i < count; i++) { | 269 | for (i = 0; i < count; i++) { |
261 | desc[i].irq_data.irq = i; | 270 | desc[i].irq_data.irq = i; |
262 | desc[i].irq_data.chip = &no_irq_chip; | 271 | desc[i].irq_data.chip = &no_irq_chip; |
263 | /* TODO : do this allocation on-demand ... */ | ||
264 | desc[i].kstat_irqs = alloc_percpu(unsigned int); | 272 | desc[i].kstat_irqs = alloc_percpu(unsigned int); |
273 | irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); | ||
265 | alloc_masks(desc + i, GFP_KERNEL, node); | 274 | alloc_masks(desc + i, GFP_KERNEL, node); |
266 | desc_smp_init(desc + i, node); | 275 | desc_smp_init(desc + i, node); |
267 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); | 276 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); |
@@ -286,24 +295,14 @@ static void free_desc(unsigned int irq) | |||
286 | 295 | ||
287 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) | 296 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) |
288 | { | 297 | { |
289 | #if defined(CONFIG_KSTAT_IRQS_ONDEMAND) | ||
290 | struct irq_desc *desc; | ||
291 | unsigned int i; | ||
292 | |||
293 | for (i = 0; i < cnt; i++) { | ||
294 | desc = irq_to_desc(start + i); | ||
295 | if (desc && !desc->kstat_irqs) { | ||
296 | unsigned int __percpu *stats = alloc_percpu(unsigned int); | ||
297 | |||
298 | if (!stats) | ||
299 | return -1; | ||
300 | if (cmpxchg(&desc->kstat_irqs, NULL, stats) != NULL) | ||
301 | free_percpu(stats); | ||
302 | } | ||
303 | } | ||
304 | #endif | ||
305 | return start; | 298 | return start; |
306 | } | 299 | } |
300 | |||
301 | static int irq_expand_nr_irqs(unsigned int nr) | ||
302 | { | ||
303 | return -ENOMEM; | ||
304 | } | ||
305 | |||
307 | #endif /* !CONFIG_SPARSE_IRQ */ | 306 | #endif /* !CONFIG_SPARSE_IRQ */ |
308 | 307 | ||
309 | /* Dynamic interrupt handling */ | 308 | /* Dynamic interrupt handling */ |
@@ -347,14 +346,17 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node) | |||
347 | 346 | ||
348 | mutex_lock(&sparse_irq_lock); | 347 | mutex_lock(&sparse_irq_lock); |
349 | 348 | ||
350 | start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0); | 349 | start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS, |
350 | from, cnt, 0); | ||
351 | ret = -EEXIST; | 351 | ret = -EEXIST; |
352 | if (irq >=0 && start != irq) | 352 | if (irq >=0 && start != irq) |
353 | goto err; | 353 | goto err; |
354 | 354 | ||
355 | ret = -ENOMEM; | 355 | if (start + cnt > nr_irqs) { |
356 | if (start >= nr_irqs) | 356 | ret = irq_expand_nr_irqs(start + cnt); |
357 | goto err; | 357 | if (ret) |
358 | goto err; | ||
359 | } | ||
358 | 360 | ||
359 | bitmap_set(allocated_irqs, start, cnt); | 361 | bitmap_set(allocated_irqs, start, cnt); |
360 | mutex_unlock(&sparse_irq_lock); | 362 | mutex_unlock(&sparse_irq_lock); |
@@ -401,6 +403,26 @@ unsigned int irq_get_next_irq(unsigned int offset) | |||
401 | return find_next_bit(allocated_irqs, nr_irqs, offset); | 403 | return find_next_bit(allocated_irqs, nr_irqs, offset); |
402 | } | 404 | } |
403 | 405 | ||
406 | struct irq_desc * | ||
407 | __irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus) | ||
408 | { | ||
409 | struct irq_desc *desc = irq_to_desc(irq); | ||
410 | |||
411 | if (desc) { | ||
412 | if (bus) | ||
413 | chip_bus_lock(desc); | ||
414 | raw_spin_lock_irqsave(&desc->lock, *flags); | ||
415 | } | ||
416 | return desc; | ||
417 | } | ||
418 | |||
419 | void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus) | ||
420 | { | ||
421 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
422 | if (bus) | ||
423 | chip_bus_sync_unlock(desc); | ||
424 | } | ||
425 | |||
404 | /** | 426 | /** |
405 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | 427 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq |
406 | * @irq: irq number to initialize | 428 | * @irq: irq number to initialize |