diff options
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 6458e99984c0..1516ab77355c 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -162,6 +162,20 @@ static inline int setup_affinity(unsigned int irq, struct irq_desc *desc) | |||
162 | } | 162 | } |
163 | #endif | 163 | #endif |
164 | 164 | ||
165 | void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) | ||
166 | { | ||
167 | if (suspend) { | ||
168 | if (!desc->action || (desc->action->flags & IRQF_TIMER)) | ||
169 | return; | ||
170 | desc->status |= IRQ_SUSPENDED; | ||
171 | } | ||
172 | |||
173 | if (!desc->depth++) { | ||
174 | desc->status |= IRQ_DISABLED; | ||
175 | desc->chip->disable(irq); | ||
176 | } | ||
177 | } | ||
178 | |||
165 | /** | 179 | /** |
166 | * disable_irq_nosync - disable an irq without waiting | 180 | * disable_irq_nosync - disable an irq without waiting |
167 | * @irq: Interrupt to disable | 181 | * @irq: Interrupt to disable |
@@ -182,10 +196,7 @@ void disable_irq_nosync(unsigned int irq) | |||
182 | return; | 196 | return; |
183 | 197 | ||
184 | spin_lock_irqsave(&desc->lock, flags); | 198 | spin_lock_irqsave(&desc->lock, flags); |
185 | if (!desc->depth++) { | 199 | __disable_irq(desc, irq, false); |
186 | desc->status |= IRQ_DISABLED; | ||
187 | desc->chip->disable(irq); | ||
188 | } | ||
189 | spin_unlock_irqrestore(&desc->lock, flags); | 200 | spin_unlock_irqrestore(&desc->lock, flags); |
190 | } | 201 | } |
191 | EXPORT_SYMBOL(disable_irq_nosync); | 202 | EXPORT_SYMBOL(disable_irq_nosync); |
@@ -215,15 +226,21 @@ void disable_irq(unsigned int irq) | |||
215 | } | 226 | } |
216 | EXPORT_SYMBOL(disable_irq); | 227 | EXPORT_SYMBOL(disable_irq); |
217 | 228 | ||
218 | static void __enable_irq(struct irq_desc *desc, unsigned int irq) | 229 | void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) |
219 | { | 230 | { |
231 | if (resume) | ||
232 | desc->status &= ~IRQ_SUSPENDED; | ||
233 | |||
220 | switch (desc->depth) { | 234 | switch (desc->depth) { |
221 | case 0: | 235 | case 0: |
236 | err_out: | ||
222 | WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); | 237 | WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); |
223 | break; | 238 | break; |
224 | case 1: { | 239 | case 1: { |
225 | unsigned int status = desc->status & ~IRQ_DISABLED; | 240 | unsigned int status = desc->status & ~IRQ_DISABLED; |
226 | 241 | ||
242 | if (desc->status & IRQ_SUSPENDED) | ||
243 | goto err_out; | ||
227 | /* Prevent probing on this irq: */ | 244 | /* Prevent probing on this irq: */ |
228 | desc->status = status | IRQ_NOPROBE; | 245 | desc->status = status | IRQ_NOPROBE; |
229 | check_irq_resend(desc, irq); | 246 | check_irq_resend(desc, irq); |
@@ -253,7 +270,7 @@ void enable_irq(unsigned int irq) | |||
253 | return; | 270 | return; |
254 | 271 | ||
255 | spin_lock_irqsave(&desc->lock, flags); | 272 | spin_lock_irqsave(&desc->lock, flags); |
256 | __enable_irq(desc, irq); | 273 | __enable_irq(desc, irq, false); |
257 | spin_unlock_irqrestore(&desc->lock, flags); | 274 | spin_unlock_irqrestore(&desc->lock, flags); |
258 | } | 275 | } |
259 | EXPORT_SYMBOL(enable_irq); | 276 | EXPORT_SYMBOL(enable_irq); |
@@ -511,7 +528,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
511 | */ | 528 | */ |
512 | if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) { | 529 | if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) { |
513 | desc->status &= ~IRQ_SPURIOUS_DISABLED; | 530 | desc->status &= ~IRQ_SPURIOUS_DISABLED; |
514 | __enable_irq(desc, irq); | 531 | __enable_irq(desc, irq, false); |
515 | } | 532 | } |
516 | 533 | ||
517 | spin_unlock_irqrestore(&desc->lock, flags); | 534 | spin_unlock_irqrestore(&desc->lock, flags); |