diff options
Diffstat (limited to 'kernel/irq/chip.c')
| -rw-r--r-- | kernel/irq/chip.c | 89 |
1 files changed, 68 insertions, 21 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index ecc3fa28f666..b7091d5ca2f8 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -18,11 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #include "internals.h" | 19 | #include "internals.h" |
| 20 | 20 | ||
| 21 | /** | 21 | static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data) |
| 22 | * dynamic_irq_init - initialize a dynamically allocated irq | ||
| 23 | * @irq: irq number to initialize | ||
| 24 | */ | ||
| 25 | void dynamic_irq_init(unsigned int irq) | ||
| 26 | { | 22 | { |
| 27 | struct irq_desc *desc; | 23 | struct irq_desc *desc; |
| 28 | unsigned long flags; | 24 | unsigned long flags; |
| @@ -41,7 +37,8 @@ void dynamic_irq_init(unsigned int irq) | |||
| 41 | desc->depth = 1; | 37 | desc->depth = 1; |
| 42 | desc->msi_desc = NULL; | 38 | desc->msi_desc = NULL; |
| 43 | desc->handler_data = NULL; | 39 | desc->handler_data = NULL; |
| 44 | desc->chip_data = NULL; | 40 | if (!keep_chip_data) |
| 41 | desc->chip_data = NULL; | ||
| 45 | desc->action = NULL; | 42 | desc->action = NULL; |
| 46 | desc->irq_count = 0; | 43 | desc->irq_count = 0; |
| 47 | desc->irqs_unhandled = 0; | 44 | desc->irqs_unhandled = 0; |
| @@ -55,10 +52,26 @@ void dynamic_irq_init(unsigned int irq) | |||
| 55 | } | 52 | } |
| 56 | 53 | ||
| 57 | /** | 54 | /** |
| 58 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | 55 | * dynamic_irq_init - initialize a dynamically allocated irq |
| 59 | * @irq: irq number to initialize | 56 | * @irq: irq number to initialize |
| 60 | */ | 57 | */ |
| 61 | void dynamic_irq_cleanup(unsigned int irq) | 58 | void dynamic_irq_init(unsigned int irq) |
| 59 | { | ||
| 60 | dynamic_irq_init_x(irq, false); | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq | ||
| 65 | * @irq: irq number to initialize | ||
| 66 | * | ||
| 67 | * does not set irq_to_desc(irq)->chip_data to NULL | ||
| 68 | */ | ||
| 69 | void dynamic_irq_init_keep_chip_data(unsigned int irq) | ||
| 70 | { | ||
| 71 | dynamic_irq_init_x(irq, true); | ||
| 72 | } | ||
| 73 | |||
| 74 | static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data) | ||
| 62 | { | 75 | { |
| 63 | struct irq_desc *desc = irq_to_desc(irq); | 76 | struct irq_desc *desc = irq_to_desc(irq); |
| 64 | unsigned long flags; | 77 | unsigned long flags; |
| @@ -77,7 +90,8 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
| 77 | } | 90 | } |
| 78 | desc->msi_desc = NULL; | 91 | desc->msi_desc = NULL; |
| 79 | desc->handler_data = NULL; | 92 | desc->handler_data = NULL; |
| 80 | desc->chip_data = NULL; | 93 | if (!keep_chip_data) |
| 94 | desc->chip_data = NULL; | ||
| 81 | desc->handle_irq = handle_bad_irq; | 95 | desc->handle_irq = handle_bad_irq; |
| 82 | desc->chip = &no_irq_chip; | 96 | desc->chip = &no_irq_chip; |
| 83 | desc->name = NULL; | 97 | desc->name = NULL; |
| @@ -85,6 +99,26 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
| 85 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 99 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 86 | } | 100 | } |
| 87 | 101 | ||
| 102 | /** | ||
| 103 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | ||
| 104 | * @irq: irq number to initialize | ||
| 105 | */ | ||
| 106 | void dynamic_irq_cleanup(unsigned int irq) | ||
| 107 | { | ||
| 108 | dynamic_irq_cleanup_x(irq, false); | ||
| 109 | } | ||
| 110 | |||
| 111 | /** | ||
| 112 | * dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq | ||
| 113 | * @irq: irq number to initialize | ||
| 114 | * | ||
| 115 | * does not set irq_to_desc(irq)->chip_data to NULL | ||
| 116 | */ | ||
| 117 | void dynamic_irq_cleanup_keep_chip_data(unsigned int irq) | ||
| 118 | { | ||
| 119 | dynamic_irq_cleanup_x(irq, true); | ||
| 120 | } | ||
| 121 | |||
| 88 | 122 | ||
| 89 | /** | 123 | /** |
| 90 | * set_irq_chip - set the irq chip for an irq | 124 | * set_irq_chip - set the irq chip for an irq |
| @@ -325,6 +359,23 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq) | |||
| 325 | if (desc->chip->ack) | 359 | if (desc->chip->ack) |
| 326 | desc->chip->ack(irq); | 360 | desc->chip->ack(irq); |
| 327 | } | 361 | } |
| 362 | desc->status |= IRQ_MASKED; | ||
| 363 | } | ||
| 364 | |||
| 365 | static inline void mask_irq(struct irq_desc *desc, int irq) | ||
| 366 | { | ||
| 367 | if (desc->chip->mask) { | ||
| 368 | desc->chip->mask(irq); | ||
| 369 | desc->status |= IRQ_MASKED; | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | static inline void unmask_irq(struct irq_desc *desc, int irq) | ||
| 374 | { | ||
| 375 | if (desc->chip->unmask) { | ||
| 376 | desc->chip->unmask(irq); | ||
| 377 | desc->status &= ~IRQ_MASKED; | ||
| 378 | } | ||
| 328 | } | 379 | } |
| 329 | 380 | ||
| 330 | /* | 381 | /* |
| @@ -450,10 +501,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 450 | raw_spin_lock(&desc->lock); | 501 | raw_spin_lock(&desc->lock); |
| 451 | desc->status &= ~IRQ_INPROGRESS; | 502 | desc->status &= ~IRQ_INPROGRESS; |
| 452 | 503 | ||
| 453 | if (unlikely(desc->status & IRQ_ONESHOT)) | 504 | if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT))) |
| 454 | desc->status |= IRQ_MASKED; | 505 | unmask_irq(desc, irq); |
| 455 | else if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) | ||
| 456 | desc->chip->unmask(irq); | ||
| 457 | out_unlock: | 506 | out_unlock: |
| 458 | raw_spin_unlock(&desc->lock); | 507 | raw_spin_unlock(&desc->lock); |
| 459 | } | 508 | } |
| @@ -490,8 +539,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
| 490 | action = desc->action; | 539 | action = desc->action; |
| 491 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) { | 540 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) { |
| 492 | desc->status |= IRQ_PENDING; | 541 | desc->status |= IRQ_PENDING; |
| 493 | if (desc->chip->mask) | 542 | mask_irq(desc, irq); |
| 494 | desc->chip->mask(irq); | ||
| 495 | goto out; | 543 | goto out; |
| 496 | } | 544 | } |
| 497 | 545 | ||
| @@ -520,7 +568,7 @@ out: | |||
| 520 | * signal. The occurence is latched into the irq controller hardware | 568 | * signal. The occurence is latched into the irq controller hardware |
| 521 | * and must be acked in order to be reenabled. After the ack another | 569 | * and must be acked in order to be reenabled. After the ack another |
| 522 | * interrupt can happen on the same source even before the first one | 570 | * interrupt can happen on the same source even before the first one |
| 523 | * is handled by the assosiacted event handler. If this happens it | 571 | * is handled by the associated event handler. If this happens it |
| 524 | * might be necessary to disable (mask) the interrupt depending on the | 572 | * might be necessary to disable (mask) the interrupt depending on the |
| 525 | * controller hardware. This requires to reenable the interrupt inside | 573 | * controller hardware. This requires to reenable the interrupt inside |
| 526 | * of the loop which handles the interrupts which have arrived while | 574 | * of the loop which handles the interrupts which have arrived while |
| @@ -559,7 +607,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 559 | irqreturn_t action_ret; | 607 | irqreturn_t action_ret; |
| 560 | 608 | ||
| 561 | if (unlikely(!action)) { | 609 | if (unlikely(!action)) { |
| 562 | desc->chip->mask(irq); | 610 | mask_irq(desc, irq); |
| 563 | goto out_unlock; | 611 | goto out_unlock; |
| 564 | } | 612 | } |
| 565 | 613 | ||
| @@ -571,8 +619,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 571 | if (unlikely((desc->status & | 619 | if (unlikely((desc->status & |
| 572 | (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == | 620 | (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == |
| 573 | (IRQ_PENDING | IRQ_MASKED))) { | 621 | (IRQ_PENDING | IRQ_MASKED))) { |
| 574 | desc->chip->unmask(irq); | 622 | unmask_irq(desc, irq); |
| 575 | desc->status &= ~IRQ_MASKED; | ||
| 576 | } | 623 | } |
| 577 | 624 | ||
| 578 | desc->status &= ~IRQ_PENDING; | 625 | desc->status &= ~IRQ_PENDING; |
| @@ -682,7 +729,7 @@ set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, | |||
| 682 | __set_irq_handler(irq, handle, 0, name); | 729 | __set_irq_handler(irq, handle, 0, name); |
| 683 | } | 730 | } |
| 684 | 731 | ||
| 685 | void __init set_irq_noprobe(unsigned int irq) | 732 | void set_irq_noprobe(unsigned int irq) |
| 686 | { | 733 | { |
| 687 | struct irq_desc *desc = irq_to_desc(irq); | 734 | struct irq_desc *desc = irq_to_desc(irq); |
| 688 | unsigned long flags; | 735 | unsigned long flags; |
| @@ -697,7 +744,7 @@ void __init set_irq_noprobe(unsigned int irq) | |||
| 697 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 744 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 698 | } | 745 | } |
| 699 | 746 | ||
| 700 | void __init set_irq_probe(unsigned int irq) | 747 | void set_irq_probe(unsigned int irq) |
| 701 | { | 748 | { |
| 702 | struct irq_desc *desc = irq_to_desc(irq); | 749 | struct irq_desc *desc = irq_to_desc(irq); |
| 703 | unsigned long flags; | 750 | unsigned long flags; |
