mirror of https://gitee.com/openkylin/linux.git
[PATCH] genirq: irq: add a dynamic irq creation API
With the msi support comes a new concept in irq handling, irqs that are created dynamically at run time. Currently the msi code allocates irqs backwards. First it allocates a platform dependent routing value for an interrupt the ``vector'' and then it figures out from the vector which irq you are on. This msi backwards allocator suffers from two basic problems. The allocator suffers because it is trying to do something that is architecture specific in a generic way making it brittle, inflexible, and tied to tightly to the architecture implementation. The alloctor also suffers from it's very backwards nature as it has tied things together that should have no dependencies. To solve the basic dynamic irq allocation problem two new architecture specific functions are added: create_irq and destroy_irq. create_irq takes no input and returns an unused irq number, that won't be reused until it is returned to the free poll with destroy_irq. The irq then can be used for any purpose although the only initial consumer is the msi code. destroy_irq takes an irq number allocated with create_irq and returns it to the free pool. Making this functionality per architecture increases the simplicity of the irq allocation code and increases it's flexibility. dynamic_irq_init() and dynamic_irq_cleanup() are added to automate the irq_desc initializtion that should happen for dynamic irqs. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rajesh Shah <rajesh.shah@intel.com> Cc: Andi Kleen <ak@muc.de> Cc: "Protasevich, Natalie" <Natalie.Protasevich@UNISYS.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
92db6d10bc
commit
3a16d71362
|
@ -404,8 +404,15 @@ set_irq_chained_handler(unsigned int irq,
|
|||
__set_irq_handler(irq, handle, 1);
|
||||
}
|
||||
|
||||
/* Set/get chip/data for an IRQ: */
|
||||
/* Handle dynamic irq creation and destruction */
|
||||
extern int create_irq(void);
|
||||
extern void destroy_irq(unsigned int irq);
|
||||
|
||||
/* Dynamic irq helper functions */
|
||||
extern void dynamic_irq_init(unsigned int irq);
|
||||
extern void dynamic_irq_cleanup(unsigned int irq);
|
||||
|
||||
/* Set/get chip/data for an IRQ: */
|
||||
extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
|
||||
extern int set_irq_data(unsigned int irq, void *data);
|
||||
extern int set_irq_chip_data(unsigned int irq, void *data);
|
||||
|
|
|
@ -17,6 +17,62 @@
|
|||
|
||||
#include "internals.h"
|
||||
|
||||
/**
|
||||
* dynamic_irq_init - initialize a dynamically allocated irq
|
||||
* @irq: irq number to initialize
|
||||
*/
|
||||
void dynamic_irq_init(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS) {
|
||||
printk(KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure we don't have left over values from a previous use of this irq */
|
||||
desc = irq_desc + irq;
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
desc->status = IRQ_DISABLED;
|
||||
desc->chip = &no_irq_chip;
|
||||
desc->handle_irq = handle_bad_irq;
|
||||
desc->depth = 1;
|
||||
desc->handler_data = NULL;
|
||||
desc->chip_data = NULL;
|
||||
desc->action = NULL;
|
||||
desc->irq_count = 0;
|
||||
desc->irqs_unhandled = 0;
|
||||
#ifdef CONFIG_SMP
|
||||
desc->affinity = CPU_MASK_ALL;
|
||||
#endif
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* dynamic_irq_cleanup - cleanup a dynamically allocated irq
|
||||
* @irq: irq number to initialize
|
||||
*/
|
||||
void dynamic_irq_cleanup(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS) {
|
||||
printk(KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
desc = irq_desc + irq;
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
desc->handle_irq = handle_bad_irq;
|
||||
desc->chip = &no_irq_chip;
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set_irq_chip - set the irq chip for an irq
|
||||
* @irq: irq number
|
||||
|
|
Loading…
Reference in New Issue