diff options
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 3ed7aee84865..627d401c2979 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -225,8 +225,14 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
225 | p = &desc->action; | 225 | p = &desc->action; |
226 | old = *p; | 226 | old = *p; |
227 | if (old) { | 227 | if (old) { |
228 | /* Can't share interrupts unless both agree to */ | 228 | /* |
229 | if (!(old->flags & new->flags & SA_SHIRQ)) | 229 | * Can't share interrupts unless both agree to and are |
230 | * the same type (level, edge, polarity). So both flag | ||
231 | * fields must have SA_SHIRQ set and the bits which | ||
232 | * set the trigger type must match. | ||
233 | */ | ||
234 | if (!((old->flags & new->flags) & SA_SHIRQ) || | ||
235 | ((old->flags ^ new->flags) & SA_TRIGGER_MASK)) | ||
230 | goto mismatch; | 236 | goto mismatch; |
231 | 237 | ||
232 | #if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) | 238 | #if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) |
@@ -250,7 +256,22 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
250 | #endif | 256 | #endif |
251 | if (!shared) { | 257 | if (!shared) { |
252 | irq_chip_set_defaults(desc->chip); | 258 | irq_chip_set_defaults(desc->chip); |
253 | compat_irq_chip_set_default_handler(desc); | 259 | |
260 | /* Setup the type (level, edge polarity) if configured: */ | ||
261 | if (new->flags & SA_TRIGGER_MASK) { | ||
262 | if (desc->chip && desc->chip->set_type) | ||
263 | desc->chip->set_type(irq, | ||
264 | new->flags & SA_TRIGGER_MASK); | ||
265 | else | ||
266 | /* | ||
267 | * SA_TRIGGER_* but the PIC does not support | ||
268 | * multiple flow-types? | ||
269 | */ | ||
270 | printk(KERN_WARNING "setup_irq(%d) SA_TRIGGER" | ||
271 | "set. No set_type function available\n", | ||
272 | irq); | ||
273 | } else | ||
274 | compat_irq_chip_set_default_handler(desc); | ||
254 | 275 | ||
255 | desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | | 276 | desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | |
256 | IRQ_INPROGRESS); | 277 | IRQ_INPROGRESS); |
@@ -262,7 +283,9 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
262 | desc->chip->startup(irq); | 283 | desc->chip->startup(irq); |
263 | else | 284 | else |
264 | desc->chip->enable(irq); | 285 | desc->chip->enable(irq); |
265 | } | 286 | } else |
287 | /* Undo nested disables: */ | ||
288 | desc->depth = 1; | ||
266 | } | 289 | } |
267 | spin_unlock_irqrestore(&desc->lock, flags); | 290 | spin_unlock_irqrestore(&desc->lock, flags); |
268 | 291 | ||