aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:37 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:27 -0400
commit3a16d713626735f3016da0521b7bf251cd78e836 (patch)
tree39147d40b681391a578b19fceb50dfe5a7a4a1ab
parent92db6d10bc1bc43330a4c540fa5b64c83d9d865f (diff)
[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>
-rw-r--r--include/linux/irq.h9
-rw-r--r--kernel/irq/chip.c56
2 files changed, 64 insertions, 1 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index a31a7d8acdb2..82dbb0e8f40b 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -404,8 +404,15 @@ set_irq_chained_handler(unsigned int irq,
404 __set_irq_handler(irq, handle, 1); 404 __set_irq_handler(irq, handle, 1);
405} 405}
406 406
407/* Set/get chip/data for an IRQ: */ 407/* Handle dynamic irq creation and destruction */
408extern int create_irq(void);
409extern void destroy_irq(unsigned int irq);
410
411/* Dynamic irq helper functions */
412extern void dynamic_irq_init(unsigned int irq);
413extern void dynamic_irq_cleanup(unsigned int irq);
408 414
415/* Set/get chip/data for an IRQ: */
409extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); 416extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
410extern int set_irq_data(unsigned int irq, void *data); 417extern int set_irq_data(unsigned int irq, void *data);
411extern int set_irq_chip_data(unsigned int irq, void *data); 418extern int set_irq_chip_data(unsigned int irq, void *data);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 736cb0bd498f..0dc24386dd99 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -18,6 +18,62 @@
18#include "internals.h" 18#include "internals.h"
19 19
20/** 20/**
21 * dynamic_irq_init - initialize a dynamically allocated irq
22 * @irq: irq number to initialize
23 */
24void dynamic_irq_init(unsigned int irq)
25{
26 struct irq_desc *desc;
27 unsigned long flags;
28
29 if (irq >= NR_IRQS) {
30 printk(KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
31 WARN_ON(1);
32 return;
33 }
34
35 /* Ensure we don't have left over values from a previous use of this irq */
36 desc = irq_desc + irq;
37 spin_lock_irqsave(&desc->lock, flags);
38 desc->status = IRQ_DISABLED;
39 desc->chip = &no_irq_chip;
40 desc->handle_irq = handle_bad_irq;
41 desc->depth = 1;
42 desc->handler_data = NULL;
43 desc->chip_data = NULL;
44 desc->action = NULL;
45 desc->irq_count = 0;
46 desc->irqs_unhandled = 0;
47#ifdef CONFIG_SMP
48 desc->affinity = CPU_MASK_ALL;
49#endif
50 spin_unlock_irqrestore(&desc->lock, flags);
51}
52
53/**
54 * dynamic_irq_cleanup - cleanup a dynamically allocated irq
55 * @irq: irq number to initialize
56 */
57void dynamic_irq_cleanup(unsigned int irq)
58{
59 struct irq_desc *desc;
60 unsigned long flags;
61
62 if (irq >= NR_IRQS) {
63 printk(KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
64 WARN_ON(1);
65 return;
66 }
67
68 desc = irq_desc + irq;
69 spin_lock_irqsave(&desc->lock, flags);
70 desc->handle_irq = handle_bad_irq;
71 desc->chip = &no_irq_chip;
72 spin_unlock_irqrestore(&desc->lock, flags);
73}
74
75
76/**
21 * set_irq_chip - set the irq chip for an irq 77 * set_irq_chip - set the irq chip for an irq
22 * @irq: irq number 78 * @irq: irq number
23 * @chip: pointer to irq chip description structure 79 * @chip: pointer to irq chip description structure