diff options
author | Julien Thierry <julien.thierry@arm.com> | 2019-01-31 09:54:00 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2019-02-05 09:37:01 -0500 |
commit | 2dcf1fbcad352baaa5f47b17e57c5743c8eedbad (patch) | |
tree | 5c7185ba1ab99bbffe19c5ad10c2f81b310a2dab | |
parent | 4b078c3f1a26487c39363089ba0d5c6b09f2a89f (diff) |
genirq: Provide NMI handlers
Provide flow handlers that are NMI safe for interrupts and percpu_devid
interrupts.
Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r-- | include/linux/irq.h | 3 | ||||
-rw-r--r-- | kernel/irq/chip.c | 54 |
2 files changed, 57 insertions, 0 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index a7298e4998c8..5e91f6bcaacd 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -601,6 +601,9 @@ extern void handle_percpu_devid_irq(struct irq_desc *desc); | |||
601 | extern void handle_bad_irq(struct irq_desc *desc); | 601 | extern void handle_bad_irq(struct irq_desc *desc); |
602 | extern void handle_nested_irq(unsigned int irq); | 602 | extern void handle_nested_irq(unsigned int irq); |
603 | 603 | ||
604 | extern void handle_fasteoi_nmi(struct irq_desc *desc); | ||
605 | extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc); | ||
606 | |||
604 | extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); | 607 | extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); |
605 | extern int irq_chip_pm_get(struct irq_data *data); | 608 | extern int irq_chip_pm_get(struct irq_data *data); |
606 | extern int irq_chip_pm_put(struct irq_data *data); | 609 | extern int irq_chip_pm_put(struct irq_data *data); |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 34e969069488..c32d5f386f68 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -730,6 +730,37 @@ out: | |||
730 | EXPORT_SYMBOL_GPL(handle_fasteoi_irq); | 730 | EXPORT_SYMBOL_GPL(handle_fasteoi_irq); |
731 | 731 | ||
732 | /** | 732 | /** |
733 | * handle_fasteoi_nmi - irq handler for NMI interrupt lines | ||
734 | * @desc: the interrupt description structure for this irq | ||
735 | * | ||
736 | * A simple NMI-safe handler, considering the restrictions | ||
737 | * from request_nmi. | ||
738 | * | ||
739 | * Only a single callback will be issued to the chip: an ->eoi() | ||
740 | * call when the interrupt has been serviced. This enables support | ||
741 | * for modern forms of interrupt handlers, which handle the flow | ||
742 | * details in hardware, transparently. | ||
743 | */ | ||
744 | void handle_fasteoi_nmi(struct irq_desc *desc) | ||
745 | { | ||
746 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
747 | struct irqaction *action = desc->action; | ||
748 | unsigned int irq = irq_desc_get_irq(desc); | ||
749 | irqreturn_t res; | ||
750 | |||
751 | trace_irq_handler_entry(irq, action); | ||
752 | /* | ||
753 | * NMIs cannot be shared, there is only one action. | ||
754 | */ | ||
755 | res = action->handler(irq, action->dev_id); | ||
756 | trace_irq_handler_exit(irq, action, res); | ||
757 | |||
758 | if (chip->irq_eoi) | ||
759 | chip->irq_eoi(&desc->irq_data); | ||
760 | } | ||
761 | EXPORT_SYMBOL_GPL(handle_fasteoi_nmi); | ||
762 | |||
763 | /** | ||
733 | * handle_edge_irq - edge type IRQ handler | 764 | * handle_edge_irq - edge type IRQ handler |
734 | * @desc: the interrupt description structure for this irq | 765 | * @desc: the interrupt description structure for this irq |
735 | * | 766 | * |
@@ -908,6 +939,29 @@ void handle_percpu_devid_irq(struct irq_desc *desc) | |||
908 | chip->irq_eoi(&desc->irq_data); | 939 | chip->irq_eoi(&desc->irq_data); |
909 | } | 940 | } |
910 | 941 | ||
942 | /** | ||
943 | * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu | ||
944 | * dev ids | ||
945 | * @desc: the interrupt description structure for this irq | ||
946 | * | ||
947 | * Similar to handle_fasteoi_nmi, but handling the dev_id cookie | ||
948 | * as a percpu pointer. | ||
949 | */ | ||
950 | void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc) | ||
951 | { | ||
952 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
953 | struct irqaction *action = desc->action; | ||
954 | unsigned int irq = irq_desc_get_irq(desc); | ||
955 | irqreturn_t res; | ||
956 | |||
957 | trace_irq_handler_entry(irq, action); | ||
958 | res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); | ||
959 | trace_irq_handler_exit(irq, action, res); | ||
960 | |||
961 | if (chip->irq_eoi) | ||
962 | chip->irq_eoi(&desc->irq_data); | ||
963 | } | ||
964 | |||
911 | static void | 965 | static void |
912 | __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, | 966 | __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, |
913 | int is_chained, const char *name) | 967 | int is_chained, const char *name) |