Commit f21cfb258df6dd3ea0b3e56d75c7e994edb81b35
Committed by
Ingo Molnar
1 parent
f8cb22cbb8
Exists in
master
and in
4 other branches
irq: add remove_irq() for freeing of setup_irq() irqs
Impact: add new API This patch adds a remove_irq() function for releasing interrupts requested with setup_irq(). Without this patch we have no way of releasing such interrupts since free_irq() today tries to kfree() the irqaction passed with setup_irq(). Signed-off-by: Magnus Damm <damm@igel.co.jp> LKML-Reference: <20090312120542.2926.56609.sendpatchset@rx1.opensource.se> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 2 changed files with 27 additions and 13 deletions Side-by-side Diff
include/linux/irq.h
kernel/irq/manage.c
... | ... | @@ -551,20 +551,14 @@ |
551 | 551 | } |
552 | 552 | |
553 | 553 | /** |
554 | - * free_irq - free an interrupt | |
554 | + * remove_irq - free an interrupt | |
555 | 555 | * @irq: Interrupt line to free |
556 | 556 | * @dev_id: Device identity to free |
557 | 557 | * |
558 | - * Remove an interrupt handler. The handler is removed and if the | |
559 | - * interrupt line is no longer in use by any driver it is disabled. | |
560 | - * On a shared IRQ the caller must ensure the interrupt is disabled | |
561 | - * on the card it drives before calling this function. The function | |
562 | - * does not return until any executing interrupts for this IRQ | |
563 | - * have completed. | |
564 | - * | |
565 | - * This function must not be called from interrupt context. | |
558 | + * Used to remove interrupts statically setup by the early boot process. | |
566 | 559 | */ |
567 | -void free_irq(unsigned int irq, void *dev_id) | |
560 | + | |
561 | +struct irqaction *remove_irq(unsigned int irq, void *dev_id) | |
568 | 562 | { |
569 | 563 | struct irq_desc *desc = irq_to_desc(irq); |
570 | 564 | struct irqaction *action, **action_ptr; |
... | ... | @@ -573,7 +567,7 @@ |
573 | 567 | WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); |
574 | 568 | |
575 | 569 | if (!desc) |
576 | - return; | |
570 | + return NULL; | |
577 | 571 | |
578 | 572 | spin_lock_irqsave(&desc->lock, flags); |
579 | 573 | |
... | ... | @@ -589,7 +583,7 @@ |
589 | 583 | WARN(1, "Trying to free already-free IRQ %d\n", irq); |
590 | 584 | spin_unlock_irqrestore(&desc->lock, flags); |
591 | 585 | |
592 | - return; | |
586 | + return NULL; | |
593 | 587 | } |
594 | 588 | |
595 | 589 | if (action->dev_id == dev_id) |
... | ... | @@ -636,7 +630,26 @@ |
636 | 630 | local_irq_restore(flags); |
637 | 631 | } |
638 | 632 | #endif |
639 | - kfree(action); | |
633 | + return action; | |
634 | +} | |
635 | + | |
636 | +/** | |
637 | + * free_irq - free an interrupt allocated with request_irq | |
638 | + * @irq: Interrupt line to free | |
639 | + * @dev_id: Device identity to free | |
640 | + * | |
641 | + * Remove an interrupt handler. The handler is removed and if the | |
642 | + * interrupt line is no longer in use by any driver it is disabled. | |
643 | + * On a shared IRQ the caller must ensure the interrupt is disabled | |
644 | + * on the card it drives before calling this function. The function | |
645 | + * does not return until any executing interrupts for this IRQ | |
646 | + * have completed. | |
647 | + * | |
648 | + * This function must not be called from interrupt context. | |
649 | + */ | |
650 | +void free_irq(unsigned int irq, void *dev_id) | |
651 | +{ | |
652 | + kfree(remove_irq(irq, dev_id)); | |
640 | 653 | } |
641 | 654 | EXPORT_SYMBOL(free_irq); |
642 | 655 |