diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-09-29 12:46:55 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-10-12 10:53:44 -0400 |
commit | b7b29338dc7111ed8bd4d6555d84afae13ebe752 (patch) | |
tree | 4c3159ea8bb0489ba463a061d3e6446dbfb45af2 | |
parent | b7d0d8258a9f71949b810e0f82a3d75088f4d364 (diff) |
genirq: Sanitize dynamic irq handling
Use the cleanup functions of the dynamic allocator. No need to have
separate implementations.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | include/linux/irq.h | 12 | ||||
-rw-r--r-- | kernel/irq/chip.c | 102 | ||||
-rw-r--r-- | kernel/irq/internals.h | 1 | ||||
-rw-r--r-- | kernel/irq/irqdesc.c | 41 |
4 files changed, 31 insertions, 125 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 49702b22883e..e9639115dff1 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -326,11 +326,15 @@ extern unsigned int create_irq_nr(unsigned int irq_want, int node); | |||
326 | extern int create_irq(void); | 326 | extern int create_irq(void); |
327 | extern void destroy_irq(unsigned int irq); | 327 | extern void destroy_irq(unsigned int irq); |
328 | 328 | ||
329 | /* Dynamic irq helper functions */ | 329 | /* |
330 | extern void dynamic_irq_init(unsigned int irq); | 330 | * Dynamic irq helper functions. Obsolete. Use irq_alloc_desc* and |
331 | void dynamic_irq_init_keep_chip_data(unsigned int irq); | 331 | * irq_free_desc instead. |
332 | */ | ||
332 | extern void dynamic_irq_cleanup(unsigned int irq); | 333 | extern void dynamic_irq_cleanup(unsigned int irq); |
333 | void dynamic_irq_cleanup_keep_chip_data(unsigned int irq); | 334 | static inline void dynamic_irq_init(unsigned int irq) |
335 | { | ||
336 | dynamic_irq_cleanup(irq); | ||
337 | } | ||
334 | 338 | ||
335 | /* Set/get chip/data for an IRQ: */ | 339 | /* Set/get chip/data for an IRQ: */ |
336 | extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); | 340 | extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 3405761d6224..baa5c4acad83 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -18,108 +18,6 @@ | |||
18 | 18 | ||
19 | #include "internals.h" | 19 | #include "internals.h" |
20 | 20 | ||
21 | static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data) | ||
22 | { | ||
23 | struct irq_desc *desc; | ||
24 | unsigned long flags; | ||
25 | |||
26 | desc = irq_to_desc(irq); | ||
27 | if (!desc) { | ||
28 | WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq); | ||
29 | return; | ||
30 | } | ||
31 | |||
32 | /* Ensure we don't have left over values from a previous use of this irq */ | ||
33 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
34 | desc->status = IRQ_DEFAULT_INIT_FLAGS; | ||
35 | desc->irq_data.chip = &no_irq_chip; | ||
36 | desc->handle_irq = handle_bad_irq; | ||
37 | desc->depth = 1; | ||
38 | desc->irq_data.msi_desc = NULL; | ||
39 | desc->irq_data.handler_data = NULL; | ||
40 | if (!keep_chip_data) | ||
41 | desc->irq_data.chip_data = NULL; | ||
42 | desc->action = NULL; | ||
43 | desc->irq_count = 0; | ||
44 | desc->irqs_unhandled = 0; | ||
45 | #ifdef CONFIG_SMP | ||
46 | cpumask_setall(desc->irq_data.affinity); | ||
47 | #ifdef CONFIG_GENERIC_PENDING_IRQ | ||
48 | cpumask_clear(desc->pending_mask); | ||
49 | #endif | ||
50 | #endif | ||
51 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * dynamic_irq_init - initialize a dynamically allocated irq | ||
56 | * @irq: irq number to initialize | ||
57 | */ | ||
58 | void dynamic_irq_init(unsigned int irq) | ||
59 | { | ||
60 | dynamic_irq_init_x(irq, false); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq | ||
65 | * @irq: irq number to initialize | ||
66 | * | ||
67 | * does not set irq_to_desc(irq)->irq_data.chip_data to NULL | ||
68 | */ | ||
69 | void dynamic_irq_init_keep_chip_data(unsigned int irq) | ||
70 | { | ||
71 | dynamic_irq_init_x(irq, true); | ||
72 | } | ||
73 | |||
74 | static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data) | ||
75 | { | ||
76 | struct irq_desc *desc = irq_to_desc(irq); | ||
77 | unsigned long flags; | ||
78 | |||
79 | if (!desc) { | ||
80 | WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
85 | if (desc->action) { | ||
86 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
87 | WARN(1, KERN_ERR "Destroying IRQ%d without calling free_irq\n", | ||
88 | irq); | ||
89 | return; | ||
90 | } | ||
91 | desc->irq_data.msi_desc = NULL; | ||
92 | desc->irq_data.handler_data = NULL; | ||
93 | if (!keep_chip_data) | ||
94 | desc->irq_data.chip_data = NULL; | ||
95 | desc->handle_irq = handle_bad_irq; | ||
96 | desc->irq_data.chip = &no_irq_chip; | ||
97 | desc->name = NULL; | ||
98 | clear_kstat_irqs(desc); | ||
99 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | ||
104 | * @irq: irq number to initialize | ||
105 | */ | ||
106 | void dynamic_irq_cleanup(unsigned int irq) | ||
107 | { | ||
108 | dynamic_irq_cleanup_x(irq, false); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq | ||
113 | * @irq: irq number to initialize | ||
114 | * | ||
115 | * does not set irq_to_desc(irq)->irq_data.chip_data to NULL | ||
116 | */ | ||
117 | void dynamic_irq_cleanup_keep_chip_data(unsigned int irq) | ||
118 | { | ||
119 | dynamic_irq_cleanup_x(irq, true); | ||
120 | } | ||
121 | |||
122 | |||
123 | /** | 21 | /** |
124 | * set_irq_chip - set the irq chip for an irq | 22 | * set_irq_chip - set the irq chip for an irq |
125 | * @irq: irq number | 23 | * @irq: irq number |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 8eb01e379ccc..f444203a772d 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -20,7 +20,6 @@ extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); | |||
20 | 20 | ||
21 | extern struct lock_class_key irq_desc_lock_class; | 21 | extern struct lock_class_key irq_desc_lock_class; |
22 | extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); | 22 | extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); |
23 | extern void clear_kstat_irqs(struct irq_desc *desc); | ||
24 | extern raw_spinlock_t sparse_irq_lock; | 23 | extern raw_spinlock_t sparse_irq_lock; |
25 | 24 | ||
26 | /* Resending of interrupts :*/ | 25 | /* Resending of interrupts :*/ |
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 6c71f8ea5d7d..c9d5a1c12874 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -53,12 +53,21 @@ static void desc_smp_init(struct irq_desc *desc, int node) | |||
53 | { | 53 | { |
54 | desc->irq_data.node = node; | 54 | desc->irq_data.node = node; |
55 | cpumask_copy(desc->irq_data.affinity, irq_default_affinity); | 55 | cpumask_copy(desc->irq_data.affinity, irq_default_affinity); |
56 | #ifdef CONFIG_GENERIC_PENDING_IRQ | ||
57 | cpumask_clear(desc->pending_mask); | ||
58 | #endif | ||
59 | } | ||
60 | |||
61 | static inline int desc_node(struct irq_desc *desc) | ||
62 | { | ||
63 | return desc->irq_data.node; | ||
56 | } | 64 | } |
57 | 65 | ||
58 | #else | 66 | #else |
59 | static inline int | 67 | static inline int |
60 | alloc_masks(struct irq_desc *desc, gfp_t gfp, int node) { return 0; } | 68 | alloc_masks(struct irq_desc *desc, gfp_t gfp, int node) { return 0; } |
61 | static inline void desc_smp_init(struct irq_desc *desc, int node) { } | 69 | static inline void desc_smp_init(struct irq_desc *desc, int node) { } |
70 | static inline int desc_node(struct irq_desc *desc) { return 0; } | ||
62 | #endif | 71 | #endif |
63 | 72 | ||
64 | static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) | 73 | static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) |
@@ -71,6 +80,8 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) | |||
71 | desc->status = IRQ_DEFAULT_INIT_FLAGS; | 80 | desc->status = IRQ_DEFAULT_INIT_FLAGS; |
72 | desc->handle_irq = handle_bad_irq; | 81 | desc->handle_irq = handle_bad_irq; |
73 | desc->depth = 1; | 82 | desc->depth = 1; |
83 | desc->irq_count = 0; | ||
84 | desc->irqs_unhandled = 0; | ||
74 | desc->name = NULL; | 85 | desc->name = NULL; |
75 | memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs))); | 86 | memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs))); |
76 | desc_smp_init(desc, node); | 87 | desc_smp_init(desc, node); |
@@ -286,23 +297,9 @@ struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node) | |||
286 | return irq_to_desc(irq); | 297 | return irq_to_desc(irq); |
287 | } | 298 | } |
288 | 299 | ||
289 | #ifdef CONFIG_SMP | ||
290 | static inline int desc_node(struct irq_desc *desc) | ||
291 | { | ||
292 | return desc->irq_data.node; | ||
293 | } | ||
294 | #else | ||
295 | static inline int desc_node(struct irq_desc *desc) { return 0; } | ||
296 | #endif | ||
297 | |||
298 | static void free_desc(unsigned int irq) | 300 | static void free_desc(unsigned int irq) |
299 | { | 301 | { |
300 | struct irq_desc *desc = irq_to_desc(irq); | 302 | dynamic_irq_cleanup(irq); |
301 | unsigned long flags; | ||
302 | |||
303 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
304 | desc_set_defaults(irq, desc, desc_node(desc)); | ||
305 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
306 | } | 303 | } |
307 | 304 | ||
308 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) | 305 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) |
@@ -409,10 +406,18 @@ unsigned int irq_get_next_irq(unsigned int offset) | |||
409 | return find_next_bit(allocated_irqs, nr_irqs, offset); | 406 | return find_next_bit(allocated_irqs, nr_irqs, offset); |
410 | } | 407 | } |
411 | 408 | ||
412 | /* Statistics access */ | 409 | /** |
413 | void clear_kstat_irqs(struct irq_desc *desc) | 410 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq |
411 | * @irq: irq number to initialize | ||
412 | */ | ||
413 | void dynamic_irq_cleanup(unsigned int irq) | ||
414 | { | 414 | { |
415 | memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs))); | 415 | struct irq_desc *desc = irq_to_desc(irq); |
416 | unsigned long flags; | ||
417 | |||
418 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
419 | desc_set_defaults(irq, desc, desc_node(desc)); | ||
420 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
416 | } | 421 | } |
417 | 422 | ||
418 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | 423 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) |