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_get(struct irq_data *data);
|
||||||
extern int irq_chip_pm_put(struct irq_data *data);
|
extern int irq_chip_pm_put(struct irq_data *data);
|
||||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
#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_enable_parent(struct irq_data *data);
|
||||||
extern void irq_chip_disable_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);
|
extern void irq_chip_ack_parent(struct irq_data *data);
|
||||||
|
|
|
@ -73,6 +73,10 @@ config IRQ_DOMAIN_HIERARCHY
|
||||||
bool
|
bool
|
||||||
select IRQ_DOMAIN
|
select IRQ_DOMAIN
|
||||||
|
|
||||||
|
# Support for hierarchical fasteoi+edge and fasteoi+level handlers
|
||||||
|
config IRQ_FASTEOI_HIERARCHY_HANDLERS
|
||||||
|
bool
|
||||||
|
|
||||||
# Generic IRQ IPI support
|
# Generic IRQ IPI support
|
||||||
config GENERIC_IRQ_IPI
|
config GENERIC_IRQ_IPI
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -1092,6 +1092,112 @@ void irq_cpu_offline(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
#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
|
* irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if
|
||||||
* NULL)
|
* NULL)
|
||||||
|
|
Loading…
Reference in New Issue