diff options
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 46e4ad1723f0..46d6611a33bb 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -150,6 +150,26 @@ void disable_irq(unsigned int irq) | |||
150 | } | 150 | } |
151 | EXPORT_SYMBOL(disable_irq); | 151 | EXPORT_SYMBOL(disable_irq); |
152 | 152 | ||
153 | static void __enable_irq(struct irq_desc *desc, unsigned int irq) | ||
154 | { | ||
155 | switch (desc->depth) { | ||
156 | case 0: | ||
157 | printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); | ||
158 | WARN_ON(1); | ||
159 | break; | ||
160 | case 1: { | ||
161 | unsigned int status = desc->status & ~IRQ_DISABLED; | ||
162 | |||
163 | /* Prevent probing on this irq: */ | ||
164 | desc->status = status | IRQ_NOPROBE; | ||
165 | check_irq_resend(desc, irq); | ||
166 | /* fall-through */ | ||
167 | } | ||
168 | default: | ||
169 | desc->depth--; | ||
170 | } | ||
171 | } | ||
172 | |||
153 | /** | 173 | /** |
154 | * enable_irq - enable handling of an irq | 174 | * enable_irq - enable handling of an irq |
155 | * @irq: Interrupt to enable | 175 | * @irq: Interrupt to enable |
@@ -169,22 +189,7 @@ void enable_irq(unsigned int irq) | |||
169 | return; | 189 | return; |
170 | 190 | ||
171 | spin_lock_irqsave(&desc->lock, flags); | 191 | spin_lock_irqsave(&desc->lock, flags); |
172 | switch (desc->depth) { | 192 | __enable_irq(desc, irq); |
173 | case 0: | ||
174 | printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); | ||
175 | WARN_ON(1); | ||
176 | break; | ||
177 | case 1: { | ||
178 | unsigned int status = desc->status & ~IRQ_DISABLED; | ||
179 | |||
180 | /* Prevent probing on this irq: */ | ||
181 | desc->status = status | IRQ_NOPROBE; | ||
182 | check_irq_resend(desc, irq); | ||
183 | /* fall-through */ | ||
184 | } | ||
185 | default: | ||
186 | desc->depth--; | ||
187 | } | ||
188 | spin_unlock_irqrestore(&desc->lock, flags); | 193 | spin_unlock_irqrestore(&desc->lock, flags); |
189 | } | 194 | } |
190 | EXPORT_SYMBOL(enable_irq); | 195 | EXPORT_SYMBOL(enable_irq); |
@@ -365,7 +370,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
365 | compat_irq_chip_set_default_handler(desc); | 370 | compat_irq_chip_set_default_handler(desc); |
366 | 371 | ||
367 | desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | | 372 | desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | |
368 | IRQ_INPROGRESS); | 373 | IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED); |
369 | 374 | ||
370 | if (!(desc->status & IRQ_NOAUTOEN)) { | 375 | if (!(desc->status & IRQ_NOAUTOEN)) { |
371 | desc->depth = 0; | 376 | desc->depth = 0; |
@@ -381,6 +386,16 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
381 | /* Reset broken irq detection when installing new handler */ | 386 | /* Reset broken irq detection when installing new handler */ |
382 | desc->irq_count = 0; | 387 | desc->irq_count = 0; |
383 | desc->irqs_unhandled = 0; | 388 | desc->irqs_unhandled = 0; |
389 | |||
390 | /* | ||
391 | * Check whether we disabled the irq via the spurious handler | ||
392 | * before. Reenable it and give it another chance. | ||
393 | */ | ||
394 | if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) { | ||
395 | desc->status &= ~IRQ_SPURIOUS_DISABLED; | ||
396 | __enable_irq(desc, irq); | ||
397 | } | ||
398 | |||
384 | spin_unlock_irqrestore(&desc->lock, flags); | 399 | spin_unlock_irqrestore(&desc->lock, flags); |
385 | 400 | ||
386 | new->irq = irq; | 401 | new->irq = irq; |