diff options
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/manage.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 80692373abd6..8e669051759d 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -571,6 +571,17 @@ int can_request_irq(unsigned int irq, unsigned long irqflags) return canrequest; } +int __irq_set_nmi_routing(struct irq_desc *desc, unsigned int irq, + unsigned int nmi) +{ + struct irq_chip *chip = desc->irq_data.chip; + + if (!chip || !chip->irq_set_nmi_routing) + return -EINVAL; + + return chip->irq_set_nmi_routing(&desc->irq_data, nmi); +} + int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, unsigned long flags) { @@ -1058,11 +1069,12 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) * the same type (level, edge, polarity). So both flag * fields must have IRQF_SHARED set and the bits which * set the trigger type must match. Also all must - * agree on ONESHOT. + * agree on ONESHOT and NMI */ if (!((old->flags & new->flags) & IRQF_SHARED) || ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) || - ((old->flags ^ new->flags) & IRQF_ONESHOT)) + ((old->flags ^ new->flags) & IRQF_ONESHOT) || + ((old->flags ^ new->flags) & __IRQF_NMI)) goto mismatch; /* All handlers must agree on per-cpuness */ @@ -1153,6 +1165,19 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) init_waitqueue_head(&desc->wait_for_threads); + if (new->flags & __IRQF_NMI) { + ret = __irq_set_nmi_routing(desc, irq, true); + if (ret != 1) + goto out_mask; + } else { + ret = __irq_set_nmi_routing(desc, irq, false); + if (ret == 1) { + pr_err("Failed to disable NMI routing for irq %d\n", + irq); + goto out_mask; + } + } + /* Setup the type (level, edge polarity) if configured: */ if (new->flags & IRQF_TRIGGER_MASK) { ret = __irq_set_trigger(desc, irq, |