Commit f21cfb258df6dd3ea0b3e56d75c7e994edb81b35

Authored by Magnus Damm
Committed by Ingo Molnar
1 parent f8cb22cbb8

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

... ... @@ -236,6 +236,7 @@
236 236 #include <asm/hw_irq.h>
237 237  
238 238 extern int setup_irq(unsigned int irq, struct irqaction *new);
  239 +extern struct irqaction *remove_irq(unsigned int irq, void *dev_id);
239 240  
240 241 #ifdef CONFIG_GENERIC_HARDIRQS
241 242  
... ... @@ -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