diff options
Diffstat (limited to 'kernel/irq/irqdesc.c')
-rw-r--r-- | kernel/irq/irqdesc.c | 86 |
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; | |||
94 | EXPORT_SYMBOL_GPL(nr_irqs); | 95 | EXPORT_SYMBOL_GPL(nr_irqs); |
95 | 96 | ||
96 | static DEFINE_MUTEX(sparse_irq_lock); | 97 | static DEFINE_MUTEX(sparse_irq_lock); |
97 | static DECLARE_BITMAP(allocated_irqs, NR_IRQS); | 98 | static 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 | ||
200 | struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) | 201 | static 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 | ||
209 | int __init early_irq_init(void) | 209 | int __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 | ||
230 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 239 | struct 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 | ||
268 | struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node) | ||
269 | { | ||
270 | return irq_to_desc(irq); | ||
271 | } | ||
272 | |||
273 | static void free_desc(unsigned int irq) | 276 | static 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 | ||
278 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) | 281 | static 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 | |||
286 | static 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 | ||
391 | struct 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 | |||
404 | void __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 |