| From a5214f58a7b1bd8881d0b99b2bf728149ece07df Mon Sep 17 00:00:00 2001 |
| From: Rob Herring <rob.herring@calxeda.com> |
| Date: Fri, 30 Sep 2011 10:48:38 -0500 |
| Subject: irq: support domains with non-zero hwirq base |
| |
| Interrupt controllers can have non-zero starting value for h/w irq numbers. |
| Adding support in irq_domain allows the domain hwirq numbering to match |
| the interrupt controllers' numbering. |
| |
| As this makes looping over irqs for a domain more complicated, add loop |
| iterators to iterate over all hwirqs and irqs for a domain. |
| |
| Signed-off-by: Rob Herring <rob.herring@calxeda.com> |
| Reviewed-by: Jamie Iles <jamie@jamieiles.com> |
| Tested-by: Thomas Abraham <thomas.abraham@linaro.org> |
| Acked-by: Grant Likely <grant.likely@secretlab.ca> |
| Acked-by: Thomas Gleixner <tglx@linutronix.de> |
| (cherry picked from commit 6d274309d0e64bdbdb6c50945ca2964596e8fa5a) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| include/linux/irqdomain.h | 16 +++++++++++++++- |
| kernel/irq/irqdomain.c | 12 ++++++------ |
| 2 files changed, 21 insertions(+), 7 deletions(-) |
| |
| diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h |
| index 3ad553e..99834e58 100644 |
| --- a/include/linux/irqdomain.h |
| +++ b/include/linux/irqdomain.h |
| @@ -47,6 +47,7 @@ struct irq_domain_ops { |
| * of the irq_domain is responsible for allocating the array of |
| * irq_desc structures. |
| * @nr_irq: Number of irqs managed by the irq domain |
| + * @hwirq_base: Starting number for hwirqs managed by the irq domain |
| * @ops: pointer to irq_domain methods |
| * @priv: private data pointer for use by owner. Not touched by irq_domain |
| * core code. |
| @@ -57,6 +58,7 @@ struct irq_domain { |
| struct list_head list; |
| unsigned int irq_base; |
| unsigned int nr_irq; |
| + unsigned int hwirq_base; |
| const struct irq_domain_ops *ops; |
| void *priv; |
| struct device_node *of_node; |
| @@ -72,9 +74,21 @@ struct irq_domain { |
| static inline unsigned int irq_domain_to_irq(struct irq_domain *d, |
| unsigned long hwirq) |
| { |
| - return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq; |
| + if (d->ops->to_irq) |
| + return d->ops->to_irq(d, hwirq); |
| + if (WARN_ON(hwirq < d->hwirq_base)) |
| + return 0; |
| + return d->irq_base + hwirq - d->hwirq_base; |
| } |
| |
| +#define irq_domain_for_each_hwirq(d, hw) \ |
| + for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++) |
| + |
| +#define irq_domain_for_each_irq(d, hw, irq) \ |
| + for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \ |
| + hw < d->hwirq_base + d->nr_irq; \ |
| + hw++, irq = irq_domain_to_irq(d, hw)) |
| + |
| extern void irq_domain_add(struct irq_domain *domain); |
| extern void irq_domain_del(struct irq_domain *domain); |
| #endif /* CONFIG_IRQ_DOMAIN */ |
| diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c |
| index b57a377..200ce83 100644 |
| --- a/kernel/irq/irqdomain.c |
| +++ b/kernel/irq/irqdomain.c |
| @@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex); |
| void irq_domain_add(struct irq_domain *domain) |
| { |
| struct irq_data *d; |
| - int hwirq; |
| + int hwirq, irq; |
| |
| /* |
| * This assumes that the irq_domain owner has already allocated |
| * the irq_descs. This block will be removed when support for dynamic |
| * allocation of irq_descs is added to irq_domain. |
| */ |
| - for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { |
| - d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); |
| + irq_domain_for_each_irq(domain, hwirq, irq) { |
| + d = irq_get_irq_data(irq); |
| if (!d) { |
| WARN(1, "error: assigning domain to non existant irq_desc"); |
| return; |
| @@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain) |
| void irq_domain_del(struct irq_domain *domain) |
| { |
| struct irq_data *d; |
| - int hwirq; |
| + int hwirq, irq; |
| |
| mutex_lock(&irq_domain_mutex); |
| list_del(&domain->list); |
| mutex_unlock(&irq_domain_mutex); |
| |
| /* Clear the irq_domain assignments */ |
| - for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { |
| - d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); |
| + irq_domain_for_each_irq(domain, hwirq, irq) { |
| + d = irq_get_irq_data(irq); |
| d->domain = NULL; |
| } |
| } |
| -- |
| 1.7.10.2.565.gbd578b5 |
| |