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 |