diff options
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 18 | ||||
| -rw-r--r-- | include/linux/irq.h | 2 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 52 |
3 files changed, 50 insertions, 22 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 53243ca7816d..c86591b906fa 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -3228,12 +3228,9 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) | |||
| 3228 | } | 3228 | } |
| 3229 | spin_unlock_irqrestore(&vector_lock, flags); | 3229 | spin_unlock_irqrestore(&vector_lock, flags); |
| 3230 | 3230 | ||
| 3231 | if (irq > 0) { | 3231 | if (irq > 0) |
| 3232 | dynamic_irq_init(irq); | 3232 | dynamic_irq_init_keep_chip_data(irq); |
| 3233 | /* restore it, in case dynamic_irq_init clear it */ | 3233 | |
| 3234 | if (desc_new) | ||
| 3235 | desc_new->chip_data = cfg_new; | ||
| 3236 | } | ||
| 3237 | return irq; | 3234 | return irq; |
| 3238 | } | 3235 | } |
| 3239 | 3236 | ||
| @@ -3256,17 +3253,12 @@ void destroy_irq(unsigned int irq) | |||
| 3256 | { | 3253 | { |
| 3257 | unsigned long flags; | 3254 | unsigned long flags; |
| 3258 | struct irq_cfg *cfg; | 3255 | struct irq_cfg *cfg; |
| 3259 | struct irq_desc *desc; | ||
| 3260 | 3256 | ||
| 3261 | /* store it, in case dynamic_irq_cleanup clear it */ | 3257 | dynamic_irq_cleanup_keep_chip_data(irq); |
| 3262 | desc = irq_to_desc(irq); | ||
| 3263 | cfg = desc->chip_data; | ||
| 3264 | dynamic_irq_cleanup(irq); | ||
| 3265 | /* connect back irq_cfg */ | ||
| 3266 | desc->chip_data = cfg; | ||
| 3267 | 3258 | ||
| 3268 | free_irte(irq); | 3259 | free_irte(irq); |
| 3269 | spin_lock_irqsave(&vector_lock, flags); | 3260 | spin_lock_irqsave(&vector_lock, flags); |
| 3261 | cfg = irq_to_desc(irq)->chip_data; | ||
| 3270 | __clear_irq_vector(irq, cfg); | 3262 | __clear_irq_vector(irq, cfg); |
| 3271 | spin_unlock_irqrestore(&vector_lock, flags); | 3263 | spin_unlock_irqrestore(&vector_lock, flags); |
| 3272 | } | 3264 | } |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 451481c082b5..4d9b26e044bc 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -400,7 +400,9 @@ static inline int irq_has_action(unsigned int irq) | |||
| 400 | 400 | ||
| 401 | /* Dynamic irq helper functions */ | 401 | /* Dynamic irq helper functions */ |
| 402 | extern void dynamic_irq_init(unsigned int irq); | 402 | extern void dynamic_irq_init(unsigned int irq); |
| 403 | void dynamic_irq_init_keep_chip_data(unsigned int irq); | ||
| 403 | extern void dynamic_irq_cleanup(unsigned int irq); | 404 | extern void dynamic_irq_cleanup(unsigned int irq); |
| 405 | void dynamic_irq_cleanup_keep_chip_data(unsigned int irq); | ||
| 404 | 406 | ||
| 405 | /* Set/get chip/data for an IRQ: */ | 407 | /* Set/get chip/data for an IRQ: */ |
| 406 | extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); | 408 | 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 ecc3fa28f666..d70394f12ee9 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -18,11 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #include "internals.h" | 19 | #include "internals.h" |
| 20 | 20 | ||
| 21 | /** | 21 | static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data) |
| 22 | * dynamic_irq_init - initialize a dynamically allocated irq | ||
| 23 | * @irq: irq number to initialize | ||
| 24 | */ | ||
| 25 | void dynamic_irq_init(unsigned int irq) | ||
| 26 | { | 22 | { |
| 27 | struct irq_desc *desc; | 23 | struct irq_desc *desc; |
| 28 | unsigned long flags; | 24 | unsigned long flags; |
| @@ -41,7 +37,8 @@ void dynamic_irq_init(unsigned int irq) | |||
| 41 | desc->depth = 1; | 37 | desc->depth = 1; |
| 42 | desc->msi_desc = NULL; | 38 | desc->msi_desc = NULL; |
| 43 | desc->handler_data = NULL; | 39 | desc->handler_data = NULL; |
| 44 | desc->chip_data = NULL; | 40 | if (!keep_chip_data) |
| 41 | desc->chip_data = NULL; | ||
| 45 | desc->action = NULL; | 42 | desc->action = NULL; |
| 46 | desc->irq_count = 0; | 43 | desc->irq_count = 0; |
| 47 | desc->irqs_unhandled = 0; | 44 | desc->irqs_unhandled = 0; |
| @@ -55,10 +52,26 @@ void dynamic_irq_init(unsigned int irq) | |||
| 55 | } | 52 | } |
| 56 | 53 | ||
| 57 | /** | 54 | /** |
| 58 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | 55 | * dynamic_irq_init - initialize a dynamically allocated irq |
| 59 | * @irq: irq number to initialize | 56 | * @irq: irq number to initialize |
| 60 | */ | 57 | */ |
| 61 | void dynamic_irq_cleanup(unsigned int irq) | 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)->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) | ||
| 62 | { | 75 | { |
| 63 | struct irq_desc *desc = irq_to_desc(irq); | 76 | struct irq_desc *desc = irq_to_desc(irq); |
| 64 | unsigned long flags; | 77 | unsigned long flags; |
| @@ -77,7 +90,8 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
| 77 | } | 90 | } |
| 78 | desc->msi_desc = NULL; | 91 | desc->msi_desc = NULL; |
| 79 | desc->handler_data = NULL; | 92 | desc->handler_data = NULL; |
| 80 | desc->chip_data = NULL; | 93 | if (!keep_chip_data) |
| 94 | desc->chip_data = NULL; | ||
| 81 | desc->handle_irq = handle_bad_irq; | 95 | desc->handle_irq = handle_bad_irq; |
| 82 | desc->chip = &no_irq_chip; | 96 | desc->chip = &no_irq_chip; |
| 83 | desc->name = NULL; | 97 | desc->name = NULL; |
| @@ -85,6 +99,26 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
| 85 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 99 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 86 | } | 100 | } |
| 87 | 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)->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 | |||
| 88 | 122 | ||
| 89 | /** | 123 | /** |
| 90 | * set_irq_chip - set the irq chip for an irq | 124 | * set_irq_chip - set the irq chip for an irq |
