Skip to content

Commit 7703b08

Browse files
daviddaneyKAGA-KOKO
authored andcommitted
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
1 parent 65efd9a commit 7703b08

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

include/linux/irq.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
568568
extern int irq_chip_pm_get(struct irq_data *data);
569569
extern int irq_chip_pm_put(struct irq_data *data);
570570
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
571+
extern void handle_fasteoi_ack_irq(struct irq_desc *desc);
572+
extern void handle_fasteoi_mask_irq(struct irq_desc *desc);
571573
extern void irq_chip_enable_parent(struct irq_data *data);
572574
extern void irq_chip_disable_parent(struct irq_data *data);
573575
extern void irq_chip_ack_parent(struct irq_data *data);

kernel/irq/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ config IRQ_DOMAIN_HIERARCHY
7373
bool
7474
select IRQ_DOMAIN
7575

76+
# Support for hierarchical fasteoi+edge and fasteoi+level handlers
77+
config IRQ_FASTEOI_HIERARCHY_HANDLERS
78+
bool
79+
7680
# Generic IRQ IPI support
7781
config GENERIC_IRQ_IPI
7882
bool

kernel/irq/chip.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,112 @@ void irq_cpu_offline(void)
10921092
}
10931093

10941094
#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+
*/
1107+
void 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;
1142+
out:
1143+
if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
1144+
chip->irq_eoi(&desc->irq_data);
1145+
raw_spin_unlock(&desc->lock);
1146+
}
1147+
EXPORT_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+
*/
1159+
void 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;
1192+
out:
1193+
if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
1194+
chip->irq_eoi(&desc->irq_data);
1195+
raw_spin_unlock(&desc->lock);
1196+
}
1197+
EXPORT_SYMBOL_GPL(handle_fasteoi_mask_irq);
1198+
1199+
#endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */
1200+
10951201
/**
10961202
* irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if
10971203
* NULL)

0 commit comments

Comments
 (0)