diff options
Diffstat (limited to 'kernel/irq/irqdesc.c')
| -rw-r--r-- | kernel/irq/irqdesc.c | 102 |
1 files changed, 70 insertions, 32 deletions
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index a7174617616b..7339e42a85ab 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
| @@ -278,7 +278,12 @@ EXPORT_SYMBOL(irq_to_desc); | |||
| 278 | 278 | ||
| 279 | static void free_desc(unsigned int irq) | 279 | static void free_desc(unsigned int irq) |
| 280 | { | 280 | { |
| 281 | dynamic_irq_cleanup(irq); | 281 | struct irq_desc *desc = irq_to_desc(irq); |
| 282 | unsigned long flags; | ||
| 283 | |||
| 284 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 285 | desc_set_defaults(irq, desc, desc_node(desc), NULL); | ||
| 286 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 282 | } | 287 | } |
| 283 | 288 | ||
| 284 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, | 289 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, |
| @@ -299,6 +304,20 @@ static int irq_expand_nr_irqs(unsigned int nr) | |||
| 299 | return -ENOMEM; | 304 | return -ENOMEM; |
| 300 | } | 305 | } |
| 301 | 306 | ||
| 307 | void irq_mark_irq(unsigned int irq) | ||
| 308 | { | ||
| 309 | mutex_lock(&sparse_irq_lock); | ||
| 310 | bitmap_set(allocated_irqs, irq, 1); | ||
| 311 | mutex_unlock(&sparse_irq_lock); | ||
| 312 | } | ||
| 313 | |||
| 314 | #ifdef CONFIG_GENERIC_IRQ_LEGACY | ||
| 315 | void irq_init_desc(unsigned int irq) | ||
| 316 | { | ||
| 317 | free_desc(irq); | ||
| 318 | } | ||
| 319 | #endif | ||
| 320 | |||
| 302 | #endif /* !CONFIG_SPARSE_IRQ */ | 321 | #endif /* !CONFIG_SPARSE_IRQ */ |
| 303 | 322 | ||
| 304 | /** | 323 | /** |
| @@ -363,6 +382,13 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, | |||
| 363 | if (from > irq) | 382 | if (from > irq) |
| 364 | return -EINVAL; | 383 | return -EINVAL; |
| 365 | from = irq; | 384 | from = irq; |
| 385 | } else { | ||
| 386 | /* | ||
| 387 | * For interrupts which are freely allocated the | ||
| 388 | * architecture can force a lower bound to the @from | ||
| 389 | * argument. x86 uses this to exclude the GSI space. | ||
| 390 | */ | ||
| 391 | from = arch_dynirq_lower_bound(from); | ||
| 366 | } | 392 | } |
| 367 | 393 | ||
| 368 | mutex_lock(&sparse_irq_lock); | 394 | mutex_lock(&sparse_irq_lock); |
| @@ -389,30 +415,56 @@ err: | |||
| 389 | } | 415 | } |
| 390 | EXPORT_SYMBOL_GPL(__irq_alloc_descs); | 416 | EXPORT_SYMBOL_GPL(__irq_alloc_descs); |
| 391 | 417 | ||
| 418 | #ifdef CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ | ||
| 392 | /** | 419 | /** |
| 393 | * irq_reserve_irqs - mark irqs allocated | 420 | * irq_alloc_hwirqs - Allocate an irq descriptor and initialize the hardware |
| 394 | * @from: mark from irq number | 421 | * @cnt: number of interrupts to allocate |
| 395 | * @cnt: number of irqs to mark | 422 | * @node: node on which to allocate |
| 396 | * | 423 | * |
| 397 | * Returns 0 on success or an appropriate error code | 424 | * Returns an interrupt number > 0 or 0, if the allocation fails. |
| 398 | */ | 425 | */ |
| 399 | int irq_reserve_irqs(unsigned int from, unsigned int cnt) | 426 | unsigned int irq_alloc_hwirqs(int cnt, int node) |
| 400 | { | 427 | { |
| 401 | unsigned int start; | 428 | int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL); |
| 402 | int ret = 0; | ||
| 403 | 429 | ||
| 404 | if (!cnt || (from + cnt) > nr_irqs) | 430 | if (irq < 0) |
| 405 | return -EINVAL; | 431 | return 0; |
| 406 | 432 | ||
| 407 | mutex_lock(&sparse_irq_lock); | 433 | for (i = irq; cnt > 0; i++, cnt--) { |
| 408 | start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0); | 434 | if (arch_setup_hwirq(i, node)) |
| 409 | if (start == from) | 435 | goto err; |
| 410 | bitmap_set(allocated_irqs, start, cnt); | 436 | irq_clear_status_flags(i, _IRQ_NOREQUEST); |
| 411 | else | 437 | } |
| 412 | ret = -EEXIST; | 438 | return irq; |
| 413 | mutex_unlock(&sparse_irq_lock); | 439 | |
| 414 | return ret; | 440 | err: |
| 441 | for (i--; i >= irq; i--) { | ||
| 442 | irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE); | ||
| 443 | arch_teardown_hwirq(i); | ||
| 444 | } | ||
| 445 | irq_free_descs(irq, cnt); | ||
| 446 | return 0; | ||
| 447 | } | ||
| 448 | EXPORT_SYMBOL_GPL(irq_alloc_hwirqs); | ||
| 449 | |||
| 450 | /** | ||
| 451 | * irq_free_hwirqs - Free irq descriptor and cleanup the hardware | ||
| 452 | * @from: Free from irq number | ||
| 453 | * @cnt: number of interrupts to free | ||
| 454 | * | ||
| 455 | */ | ||
| 456 | void irq_free_hwirqs(unsigned int from, int cnt) | ||
| 457 | { | ||
| 458 | int i; | ||
| 459 | |||
| 460 | for (i = from; cnt > 0; i++, cnt--) { | ||
| 461 | irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE); | ||
| 462 | arch_teardown_hwirq(i); | ||
| 463 | } | ||
| 464 | irq_free_descs(from, cnt); | ||
| 415 | } | 465 | } |
| 466 | EXPORT_SYMBOL_GPL(irq_free_hwirqs); | ||
| 467 | #endif | ||
| 416 | 468 | ||
| 417 | /** | 469 | /** |
| 418 | * irq_get_next_irq - get next allocated irq number | 470 | * irq_get_next_irq - get next allocated irq number |
| @@ -475,20 +527,6 @@ int irq_set_percpu_devid(unsigned int irq) | |||
| 475 | return 0; | 527 | return 0; |
| 476 | } | 528 | } |
| 477 | 529 | ||
| 478 | /** | ||
| 479 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | ||
| 480 | * @irq: irq number to initialize | ||
| 481 | */ | ||
| 482 | void dynamic_irq_cleanup(unsigned int irq) | ||
| 483 | { | ||
| 484 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 485 | unsigned long flags; | ||
| 486 | |||
| 487 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 488 | desc_set_defaults(irq, desc, desc_node(desc), NULL); | ||
| 489 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 490 | } | ||
| 491 | |||
| 492 | void kstat_incr_irq_this_cpu(unsigned int irq) | 530 | void kstat_incr_irq_this_cpu(unsigned int irq) |
| 493 | { | 531 | { |
| 494 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 532 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); |
