Skip to content

Commit

Permalink
Merge branch 'irq/for-gpio' into irq/core
Browse files Browse the repository at this point in the history
Merge the flow handlers and irq domain extensions which are in a separate
branch so they can be consumed by the gpio folks.
  • Loading branch information
Thomas Gleixner committed Aug 18, 2017
2 parents 5009121 + 495c38d commit 6629695
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 30 deletions.
2 changes: 2 additions & 0 deletions include/linux/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions include/linux/irqdomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,9 @@ extern void irq_domain_free_irqs_common(struct irq_domain *domain,
extern void irq_domain_free_irqs_top(struct irq_domain *domain,
unsigned int virq, unsigned int nr_irqs);

extern int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg);
extern int irq_domain_pop_irq(struct irq_domain *domain, int virq);

extern int irq_domain_alloc_irqs_parent(struct irq_domain *domain,
unsigned int irq_base,
unsigned int nr_irqs, void *arg);
Expand Down
4 changes: 4 additions & 0 deletions kernel/irq/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
109 changes: 109 additions & 0 deletions kernel/irq/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -1105,6 +1211,7 @@ void irq_chip_enable_parent(struct irq_data *data)
else
data->chip->irq_unmask(data);
}
EXPORT_SYMBOL_GPL(irq_chip_enable_parent);

/**
* irq_chip_disable_parent - Disable the parent interrupt (defaults to mask if
Expand All @@ -1119,6 +1226,7 @@ void irq_chip_disable_parent(struct irq_data *data)
else
data->chip->irq_mask(data);
}
EXPORT_SYMBOL_GPL(irq_chip_disable_parent);

/**
* irq_chip_ack_parent - Acknowledge the parent interrupt
Expand Down Expand Up @@ -1181,6 +1289,7 @@ int irq_chip_set_affinity_parent(struct irq_data *data,

return -ENOSYS;
}
EXPORT_SYMBOL_GPL(irq_chip_set_affinity_parent);

/**
* irq_chip_set_type_parent - Set IRQ type on the parent interrupt
Expand Down
Loading

0 comments on commit 6629695

Please sign in to comment.