diff options
| -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) |
