diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2010-09-29 20:46:07 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2010-10-12 10:39:07 -0400 |
| commit | 13bfe99e09123ef5edb6acb81ba337d2db600b53 (patch) | |
| tree | f96f5be41c90e1ab437bb40a02a8f137deb9e3ab | |
| parent | 1f5a5b87f78fade3ae48dfd55e8765d1d622ea4e (diff) | |
genirq: Prepare proc for real sparse irq support
/proc/irq never removes any entries, but when irq descriptors can be
freed for real this is necessary. Otherwise we'd reference a freed
descriptor in /proc/irq/N
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | kernel/irq/internals.h | 2 | ||||
| -rw-r--r-- | kernel/irq/irqdesc.c | 2 | ||||
| -rw-r--r-- | kernel/irq/proc.c | 18 |
3 files changed, 22 insertions, 0 deletions
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index e281e45fbb55..8eb01e379ccc 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
| @@ -32,10 +32,12 @@ void replace_irq_desc(unsigned int irq, struct irq_desc *desc); | |||
| 32 | 32 | ||
| 33 | #ifdef CONFIG_PROC_FS | 33 | #ifdef CONFIG_PROC_FS |
| 34 | extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); | 34 | extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); |
| 35 | extern void unregister_irq_proc(unsigned int irq, struct irq_desc *desc); | ||
| 35 | extern void register_handler_proc(unsigned int irq, struct irqaction *action); | 36 | extern void register_handler_proc(unsigned int irq, struct irqaction *action); |
| 36 | extern void unregister_handler_proc(unsigned int irq, struct irqaction *action); | 37 | extern void unregister_handler_proc(unsigned int irq, struct irqaction *action); |
| 37 | #else | 38 | #else |
| 38 | static inline void register_irq_proc(unsigned int irq, struct irq_desc *desc) { } | 39 | static inline void register_irq_proc(unsigned int irq, struct irq_desc *desc) { } |
| 40 | static inline void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) { } | ||
| 39 | static inline void register_handler_proc(unsigned int irq, | 41 | static inline void register_handler_proc(unsigned int irq, |
| 40 | struct irqaction *action) { } | 42 | struct irqaction *action) { } |
| 41 | static inline void unregister_handler_proc(unsigned int irq, | 43 | static inline void unregister_handler_proc(unsigned int irq, |
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 4eea48b4f576..6312a2c83971 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
| @@ -205,6 +205,8 @@ static void free_desc(unsigned int irq) | |||
| 205 | struct irq_desc *desc = irq_to_desc(irq); | 205 | struct irq_desc *desc = irq_to_desc(irq); |
| 206 | unsigned long flags; | 206 | unsigned long flags; |
| 207 | 207 | ||
| 208 | unregister_irq_proc(irq, desc); | ||
| 209 | |||
| 208 | raw_spin_lock_irqsave(&sparse_irq_lock, flags); | 210 | raw_spin_lock_irqsave(&sparse_irq_lock, flags); |
| 209 | delete_irq_desc(irq); | 211 | delete_irq_desc(irq); |
| 210 | raw_spin_unlock_irqrestore(&sparse_irq_lock, flags); | 212 | raw_spin_unlock_irqrestore(&sparse_irq_lock, flags); |
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index d9fddf918b41..01b1d3a88983 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
| @@ -297,6 +297,24 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) | |||
| 297 | &irq_spurious_proc_fops, (void *)(long)irq); | 297 | &irq_spurious_proc_fops, (void *)(long)irq); |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) | ||
| 301 | { | ||
| 302 | char name [MAX_NAMELEN]; | ||
| 303 | |||
| 304 | if (!root_irq_dir || !desc->dir) | ||
| 305 | return; | ||
| 306 | #ifdef CONFIG_SMP | ||
| 307 | remove_proc_entry("smp_affinity", desc->dir); | ||
| 308 | remove_proc_entry("affinity_hint", desc->dir); | ||
| 309 | remove_proc_entry("node", desc->dir); | ||
| 310 | #endif | ||
| 311 | remove_proc_entry("spurious", desc->dir); | ||
| 312 | |||
| 313 | memset(name, 0, MAX_NAMELEN); | ||
| 314 | sprintf(name, "%u", irq); | ||
| 315 | remove_proc_entry(name, root_irq_dir); | ||
| 316 | } | ||
| 317 | |||
| 300 | #undef MAX_NAMELEN | 318 | #undef MAX_NAMELEN |
| 301 | 319 | ||
| 302 | void unregister_handler_proc(unsigned int irq, struct irqaction *action) | 320 | void unregister_handler_proc(unsigned int irq, struct irqaction *action) |
