aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2017-08-17 20:53:31 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-08-18 05:21:41 -0400
commit7703b08cc93b3586f9eb733f3a2b10bed634a5cf (patch)
tree1d471cb1c2cbcbdf36606031da386beb97a1b3e5
parent65efd9a49af8174b2283fd5b27e9edf30e4483d0 (diff)
genirq: Add handle_fasteoi_{level,edge}_irq flow handlers
Follow-on patch for gpio-thunderx uses a irqdomain hierarchy which requires slightly different flow handlers, add them to chip.c which contains most of the other flow handlers. Make these conditionally compiled based on CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS. Signed-off-by: David Daney <david.daney@cavium.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Alexandre Courbot <gnurou@gmail.com> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: linux-gpio@vger.kernel.org Link: http://lkml.kernel.org/r/1503017616-3252-3-git-send-email-david.daney@cavium.com
-rw-r--r--include/linux/irq.h2
-rw-r--r--kernel/irq/Kconfig4
-rw-r--r--kernel/irq/chip.c106
3 files changed, 112 insertions, 0 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index d2d543794093..d4728bf6a537 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -568,6 +568,8 @@ extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
568extern int irq_chip_pm_get(struct irq_data *data); 568extern int irq_chip_pm_get(struct irq_data *data);
569extern int irq_chip_pm_put(struct irq_data *data); 569extern int irq_chip_pm_put(struct irq_data *data);
570#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 570#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
571extern void handle_fasteoi_ack_irq(struct irq_desc *desc);
572extern void handle_fasteoi_mask_irq(struct irq_desc *desc);
571extern void irq_chip_enable_parent(struct irq_data *data); 573extern void irq_chip_enable_parent(struct irq_data *data);
572extern void irq_chip_disable_parent(struct irq_data *data); 574extern void irq_chip_disable_parent(struct irq_data *data);
573extern void irq_chip_ack_parent(struct irq_data *data); 575extern void irq_chip_ack_parent(struct irq_data *data);
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 1d06af787932..a117adf7084b 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -73,6 +73,10 @@ config IRQ_DOMAIN_HIERARCHY
73 bool 73 bool
74 select IRQ_DOMAIN 74 select IRQ_DOMAIN
75 75
76# Support for hierarchical fasteoi+edge and fasteoi+level handlers
77config IRQ_FASTEOI_HIERARCHY_HANDLERS
78 bool
79
76# Generic IRQ IPI support 80# Generic IRQ IPI support
77config GENERIC_IRQ_IPI 81config GENERIC_IRQ_IPI
78 bool 82 bool
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 6514f07acaad..23958980189d 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -1092,6 +1092,112 @@ void irq_cpu_offline(void)
1092} 1092}
1093 1093
1094#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 1094#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
1095
1096#ifdef CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS
1097/**
1098 * handle_fasteoi_ack_irq - irq handler for edge hierarchy
1099 * stacked on transparent controllers
1100 *
1101 * @desc: the interrupt description structure for this irq
1102 *
1103 * Like handle_fasteoi_irq(), but for use with hierarchy where
1104 * the irq_chip also needs to have its ->irq_ack() function
1105 * called.
1106 */
1107void handle_fasteoi_ack_irq(struct irq_desc *desc)
1108{
1109 struct irq_chip *chip = desc->irq_data.chip;
1110
1111 raw_spin_lock(&desc->lock);
1112
1113 if (!irq_may_run(desc))
1114 goto out;
1115
1116 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
1117
1118 /*
1119 * If its disabled or no action available
1120 * then mask it and get out of here:
1121 */
1122 if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
1123 desc->istate |= IRQS_PENDING;
1124 mask_irq(desc);
1125 goto out;
1126 }
1127
1128 kstat_incr_irqs_this_cpu(desc);
1129 if (desc->istate & IRQS_ONESHOT)
1130 mask_irq(desc);
1131
1132 /* Start handling the irq */
1133 desc->irq_data.chip->irq_ack(&desc->irq_data);
1134
1135 preflow_handler(desc);
1136 handle_irq_event(desc);
1137
1138 cond_unmask_eoi_irq(desc, chip);
1139
1140 raw_spin_unlock(&desc->lock);
1141 return;
1142out:
1143 if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
1144 chip->irq_eoi(&desc->irq_data);
1145 raw_spin_unlock(&desc->lock);
1146}
1147EXPORT_SYMBOL_GPL(handle_fasteoi_ack_irq);
1148
1149/**
1150 * handle_fasteoi_mask_irq - irq handler for level hierarchy
1151 * stacked on transparent controllers
1152 *
1153 * @desc: the interrupt description structure for this irq
1154 *
1155 * Like handle_fasteoi_irq(), but for use with hierarchy where
1156 * the irq_chip also needs to have its ->irq_mask_ack() function
1157 * called.
1158 */
1159void handle_fasteoi_mask_irq(struct irq_desc *desc)
1160{
1161 struct irq_chip *chip = desc->irq_data.chip;
1162
1163 raw_spin_lock(&desc->lock);
1164 mask_ack_irq(desc);
1165
1166 if (!irq_may_run(desc))
1167 goto out;
1168
1169 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
1170
1171 /*
1172 * If its disabled or no action available
1173 * then mask it and get out of here:
1174 */
1175 if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
1176 desc->istate |= IRQS_PENDING;
1177 mask_irq(desc);
1178 goto out;
1179 }
1180
1181 kstat_incr_irqs_this_cpu(desc);
1182 if (desc->istate & IRQS_ONESHOT)
1183 mask_irq(desc);
1184
1185 preflow_handler(desc);
1186 handle_irq_event(desc);
1187
1188 cond_unmask_eoi_irq(desc, chip);
1189
1190 raw_spin_unlock(&desc->lock);
1191 return;
1192out:
1193 if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
1194 chip->irq_eoi(&desc->irq_data);
1195 raw_spin_unlock(&desc->lock);
1196}
1197EXPORT_SYMBOL_GPL(handle_fasteoi_mask_irq);
1198
1199#endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */
1200
1095/** 1201/**
1096 * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if 1202 * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if
1097 * NULL) 1203 * NULL)