Skip to content

Commit 6d27430

Browse files
Rob Herringarndb
authored andcommitted
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 <[email protected]> Reviewed-by: Jamie Iles <[email protected]> Tested-by: Thomas Abraham <[email protected]> Acked-by: Grant Likely <[email protected]> Acked-by: Thomas Gleixner <[email protected]>
1 parent c71a54b commit 6d27430

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

include/linux/irqdomain.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct irq_domain_ops {
4747
* of the irq_domain is responsible for allocating the array of
4848
* irq_desc structures.
4949
* @nr_irq: Number of irqs managed by the irq domain
50+
* @hwirq_base: Starting number for hwirqs managed by the irq domain
5051
* @ops: pointer to irq_domain methods
5152
* @priv: private data pointer for use by owner. Not touched by irq_domain
5253
* core code.
@@ -57,6 +58,7 @@ struct irq_domain {
5758
struct list_head list;
5859
unsigned int irq_base;
5960
unsigned int nr_irq;
61+
unsigned int hwirq_base;
6062
const struct irq_domain_ops *ops;
6163
void *priv;
6264
struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
7274
static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
7375
unsigned long hwirq)
7476
{
75-
return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
77+
if (d->ops->to_irq)
78+
return d->ops->to_irq(d, hwirq);
79+
if (WARN_ON(hwirq < d->hwirq_base))
80+
return 0;
81+
return d->irq_base + hwirq - d->hwirq_base;
7682
}
7783

84+
#define irq_domain_for_each_hwirq(d, hw) \
85+
for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
86+
87+
#define irq_domain_for_each_irq(d, hw, irq) \
88+
for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
89+
hw < d->hwirq_base + d->nr_irq; \
90+
hw++, irq = irq_domain_to_irq(d, hw))
91+
7892
extern void irq_domain_add(struct irq_domain *domain);
7993
extern void irq_domain_del(struct irq_domain *domain);
8094
#endif /* CONFIG_IRQ_DOMAIN */

kernel/irq/irqdomain.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
2020
void irq_domain_add(struct irq_domain *domain)
2121
{
2222
struct irq_data *d;
23-
int hwirq;
23+
int hwirq, irq;
2424

2525
/*
2626
* This assumes that the irq_domain owner has already allocated
2727
* the irq_descs. This block will be removed when support for dynamic
2828
* allocation of irq_descs is added to irq_domain.
2929
*/
30-
for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
31-
d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
30+
irq_domain_for_each_irq(domain, hwirq, irq) {
31+
d = irq_get_irq_data(irq);
3232
if (!d) {
3333
WARN(1, "error: assigning domain to non existant irq_desc");
3434
return;
@@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
5454
void irq_domain_del(struct irq_domain *domain)
5555
{
5656
struct irq_data *d;
57-
int hwirq;
57+
int hwirq, irq;
5858

5959
mutex_lock(&irq_domain_mutex);
6060
list_del(&domain->list);
6161
mutex_unlock(&irq_domain_mutex);
6262

6363
/* Clear the irq_domain assignments */
64-
for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
65-
d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
64+
irq_domain_for_each_irq(domain, hwirq, irq) {
65+
d = irq_get_irq_data(irq);
6666
d->domain = NULL;
6767
}
6868
}

0 commit comments

Comments
 (0)