Skip to content

Commit d55f7f4

Browse files
jhovoldMarc Zyngier
authored andcommitted
irqdomain: Refactor __irq_domain_alloc_irqs()
Refactor __irq_domain_alloc_irqs() so that it can be called internally while holding the irq_domain_mutex. This will be used to fix a shared-interrupt mapping race, hence the Fixes tag. Fixes: b62b2cf ("irqdomain: Fix handling of type settings for existing mappings") Cc: [email protected] # 4.8 Tested-by: Hsin-Yi Wang <[email protected]> Tested-by: Mark-PK Tsai <[email protected]> Signed-off-by: Johan Hovold <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 6e6f75c commit d55f7f4

File tree

1 file changed

+48
-40
lines changed

1 file changed

+48
-40
lines changed

kernel/irq/irqdomain.c

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,40 +1441,12 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,
14411441
return domain->ops->alloc(domain, irq_base, nr_irqs, arg);
14421442
}
14431443

1444-
/**
1445-
* __irq_domain_alloc_irqs - Allocate IRQs from domain
1446-
* @domain: domain to allocate from
1447-
* @irq_base: allocate specified IRQ number if irq_base >= 0
1448-
* @nr_irqs: number of IRQs to allocate
1449-
* @node: NUMA node id for memory allocation
1450-
* @arg: domain specific argument
1451-
* @realloc: IRQ descriptors have already been allocated if true
1452-
* @affinity: Optional irq affinity mask for multiqueue devices
1453-
*
1454-
* Allocate IRQ numbers and initialized all data structures to support
1455-
* hierarchy IRQ domains.
1456-
* Parameter @realloc is mainly to support legacy IRQs.
1457-
* Returns error code or allocated IRQ number
1458-
*
1459-
* The whole process to setup an IRQ has been split into two steps.
1460-
* The first step, __irq_domain_alloc_irqs(), is to allocate IRQ
1461-
* descriptor and required hardware resources. The second step,
1462-
* irq_domain_activate_irq(), is to program the hardware with preallocated
1463-
* resources. In this way, it's easier to rollback when failing to
1464-
* allocate resources.
1465-
*/
1466-
int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
1467-
unsigned int nr_irqs, int node, void *arg,
1468-
bool realloc, const struct irq_affinity_desc *affinity)
1444+
static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base,
1445+
unsigned int nr_irqs, int node, void *arg,
1446+
bool realloc, const struct irq_affinity_desc *affinity)
14691447
{
14701448
int i, ret, virq;
14711449

1472-
if (domain == NULL) {
1473-
domain = irq_default_domain;
1474-
if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n"))
1475-
return -EINVAL;
1476-
}
1477-
14781450
if (realloc && irq_base >= 0) {
14791451
virq = irq_base;
14801452
} else {
@@ -1493,24 +1465,18 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
14931465
goto out_free_desc;
14941466
}
14951467

1496-
mutex_lock(&irq_domain_mutex);
14971468
ret = irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg);
1498-
if (ret < 0) {
1499-
mutex_unlock(&irq_domain_mutex);
1469+
if (ret < 0)
15001470
goto out_free_irq_data;
1501-
}
15021471

15031472
for (i = 0; i < nr_irqs; i++) {
15041473
ret = irq_domain_trim_hierarchy(virq + i);
1505-
if (ret) {
1506-
mutex_unlock(&irq_domain_mutex);
1474+
if (ret)
15071475
goto out_free_irq_data;
1508-
}
15091476
}
1510-
1477+
15111478
for (i = 0; i < nr_irqs; i++)
15121479
irq_domain_insert_irq(virq + i);
1513-
mutex_unlock(&irq_domain_mutex);
15141480

15151481
return virq;
15161482

@@ -1520,6 +1486,48 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
15201486
irq_free_descs(virq, nr_irqs);
15211487
return ret;
15221488
}
1489+
1490+
/**
1491+
* __irq_domain_alloc_irqs - Allocate IRQs from domain
1492+
* @domain: domain to allocate from
1493+
* @irq_base: allocate specified IRQ number if irq_base >= 0
1494+
* @nr_irqs: number of IRQs to allocate
1495+
* @node: NUMA node id for memory allocation
1496+
* @arg: domain specific argument
1497+
* @realloc: IRQ descriptors have already been allocated if true
1498+
* @affinity: Optional irq affinity mask for multiqueue devices
1499+
*
1500+
* Allocate IRQ numbers and initialized all data structures to support
1501+
* hierarchy IRQ domains.
1502+
* Parameter @realloc is mainly to support legacy IRQs.
1503+
* Returns error code or allocated IRQ number
1504+
*
1505+
* The whole process to setup an IRQ has been split into two steps.
1506+
* The first step, __irq_domain_alloc_irqs(), is to allocate IRQ
1507+
* descriptor and required hardware resources. The second step,
1508+
* irq_domain_activate_irq(), is to program the hardware with preallocated
1509+
* resources. In this way, it's easier to rollback when failing to
1510+
* allocate resources.
1511+
*/
1512+
int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
1513+
unsigned int nr_irqs, int node, void *arg,
1514+
bool realloc, const struct irq_affinity_desc *affinity)
1515+
{
1516+
int ret;
1517+
1518+
if (domain == NULL) {
1519+
domain = irq_default_domain;
1520+
if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n"))
1521+
return -EINVAL;
1522+
}
1523+
1524+
mutex_lock(&irq_domain_mutex);
1525+
ret = irq_domain_alloc_irqs_locked(domain, irq_base, nr_irqs, node, arg,
1526+
realloc, affinity);
1527+
mutex_unlock(&irq_domain_mutex);
1528+
1529+
return ret;
1530+
}
15231531
EXPORT_SYMBOL_GPL(__irq_domain_alloc_irqs);
15241532

15251533
/* The irq_data was moved, fix the revmap to refer to the new location */

0 commit comments

Comments
 (0)