[PATCH 9/25] irq: Add a dynamic irq creation API

From: Eric W. Biederman
Date: Tue Jun 20 2006 - 18:37:58 EST


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@xxxxxxxxxxxx>
---
include/linux/irq.h | 9 +++++++-
kernel/irq/chip.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+), 1 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index b79d178..6d1ad88 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -392,8 +392,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);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 431e9d5..9c01e48 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -18,6 +18,62 @@ #include <linux/kernel_stat.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
* @irq: irq number
* @chip: pointer to irq chip description structure
--
1.4.0.gc07e

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/