Commit 3a16d713 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds

[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: default avatarEric 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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 92db6d10
...@@ -404,8 +404,15 @@ set_irq_chained_handler(unsigned int irq, ...@@ -404,8 +404,15 @@ set_irq_chained_handler(unsigned int irq,
__set_irq_handler(irq, handle, 1); __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_chip(unsigned int irq, struct irq_chip *chip);
extern int set_irq_data(unsigned int irq, void *data); extern int set_irq_data(unsigned int irq, void *data);
extern int set_irq_chip_data(unsigned int irq, void *data); extern int set_irq_chip_data(unsigned int irq, void *data);
......
...@@ -17,6 +17,62 @@ ...@@ -17,6 +17,62 @@
#include "internals.h" #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 * set_irq_chip - set the irq chip for an irq
* @irq: irq number * @irq: irq number
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment