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
This commit is contained in:
parent
65efd9a49a
commit
7703b08cc9
|
@ -568,6 +568,8 @@ extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
|
|||
extern int irq_chip_pm_get(struct irq_data *data);
|
||||
extern int irq_chip_pm_put(struct irq_data *data);
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
extern void handle_fasteoi_ack_irq(struct irq_desc *desc);
|
||||
extern void handle_fasteoi_mask_irq(struct irq_desc *desc);
|
||||
extern void irq_chip_enable_parent(struct irq_data *data);
|
||||
extern void irq_chip_disable_parent(struct irq_data *data);
|
||||
extern void irq_chip_ack_parent(struct irq_data *data);
|
||||
|
|
|
@ -73,6 +73,10 @@ config IRQ_DOMAIN_HIERARCHY
|
|||
bool
|
||||
select IRQ_DOMAIN
|
||||
|
||||
# Support for hierarchical fasteoi+edge and fasteoi+level handlers
|
||||
config IRQ_FASTEOI_HIERARCHY_HANDLERS
|
||||
bool
|
||||
|
||||
# Generic IRQ IPI support
|
||||
config GENERIC_IRQ_IPI
|
||||
bool
|
||||
|
|
|
@ -1092,6 +1092,112 @@ void irq_cpu_offline(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
|
||||
#ifdef CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS
|
||||
/**
|
||||
* handle_fasteoi_ack_irq - irq handler for edge hierarchy
|
||||
* stacked on transparent controllers
|
||||
*
|
||||
* @desc: the interrupt description structure for this irq
|
||||
*
|
||||
* Like handle_fasteoi_irq(), but for use with hierarchy where
|
||||
* the irq_chip also needs to have its ->irq_ack() function
|
||||
* called.
|
||||
*/
|
||||
void handle_fasteoi_ack_irq(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = desc->irq_data.chip;
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
|
||||
if (!irq_may_run(desc))
|
||||
goto out;
|
||||
|
||||
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
|
||||
|
||||
/*
|
||||
* If its disabled or no action available
|
||||
* then mask it and get out of here:
|
||||
*/
|
||||
if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
|
||||
desc->istate |= IRQS_PENDING;
|
||||
mask_irq(desc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
kstat_incr_irqs_this_cpu(desc);
|
||||
if (desc->istate & IRQS_ONESHOT)
|
||||
mask_irq(desc);
|
||||
|
||||
/* Start handling the irq */
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
|
||||
preflow_handler(desc);
|
||||
handle_irq_event(desc);
|
||||
|
||||
cond_unmask_eoi_irq(desc, chip);
|
||||
|
||||
raw_spin_unlock(&desc->lock);
|
||||
return;
|
||||
out:
|
||||
if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(handle_fasteoi_ack_irq);
|
||||
|
||||
/**
|
||||
* handle_fasteoi_mask_irq - irq handler for level hierarchy
|
||||
* stacked on transparent controllers
|
||||
*
|
||||
* @desc: the interrupt description structure for this irq
|
||||
*
|
||||
* Like handle_fasteoi_irq(), but for use with hierarchy where
|
||||
* the irq_chip also needs to have its ->irq_mask_ack() function
|
||||
* called.
|
||||
*/
|
||||
void handle_fasteoi_mask_irq(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = desc->irq_data.chip;
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
mask_ack_irq(desc);
|
||||
|
||||
if (!irq_may_run(desc))
|
||||
goto out;
|
||||
|
||||
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
|
||||
|
||||
/*
|
||||
* If its disabled or no action available
|
||||
* then mask it and get out of here:
|
||||
*/
|
||||
if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
|
||||
desc->istate |= IRQS_PENDING;
|
||||
mask_irq(desc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
kstat_incr_irqs_this_cpu(desc);
|
||||
if (desc->istate & IRQS_ONESHOT)
|
||||
mask_irq(desc);
|
||||
|
||||
preflow_handler(desc);
|
||||
handle_irq_event(desc);
|
||||
|
||||
cond_unmask_eoi_irq(desc, chip);
|
||||
|
||||
raw_spin_unlock(&desc->lock);
|
||||
return;
|
||||
out:
|
||||
if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(handle_fasteoi_mask_irq);
|
||||
|
||||
#endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */
|
||||
|
||||
/**
|
||||
* irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if
|
||||
* NULL)
|
||||
|
|
Loading…
Reference in New Issue