Skip to content

Commit b06730a

Browse files
jhovoldMarc Zyngier
authored andcommitted
irqdomain: Fix association race
The sanity check for an already mapped virq is done outside of the irq_domain_mutex-protected section which means that an (unlikely) racing association may not be detected. Fix this by factoring out the association implementation, which will also be used in a follow-on change to fix a shared-interrupt mapping race. Fixes: ddaf144 ("irqdomain: Refactor irq_domain_associate_many()") Cc: [email protected] # 3.11 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 5dc4c99 commit b06730a

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

kernel/irq/irqdomain.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,8 @@ static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
559559
irq_domain_clear_mapping(domain, hwirq);
560560
}
561561

562-
int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
563-
irq_hw_number_t hwirq)
562+
static int irq_domain_associate_locked(struct irq_domain *domain, unsigned int virq,
563+
irq_hw_number_t hwirq)
564564
{
565565
struct irq_data *irq_data = irq_get_irq_data(virq);
566566
int ret;
@@ -573,7 +573,6 @@ int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
573573
if (WARN(irq_data->domain, "error: virq%i is already associated", virq))
574574
return -EINVAL;
575575

576-
mutex_lock(&irq_domain_mutex);
577576
irq_data->hwirq = hwirq;
578577
irq_data->domain = domain;
579578
if (domain->ops->map) {
@@ -590,7 +589,6 @@ int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
590589
}
591590
irq_data->domain = NULL;
592591
irq_data->hwirq = 0;
593-
mutex_unlock(&irq_domain_mutex);
594592
return ret;
595593
}
596594

@@ -601,12 +599,23 @@ int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
601599

602600
domain->mapcount++;
603601
irq_domain_set_mapping(domain, hwirq, irq_data);
604-
mutex_unlock(&irq_domain_mutex);
605602

606603
irq_clear_status_flags(virq, IRQ_NOREQUEST);
607604

608605
return 0;
609606
}
607+
608+
int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
609+
irq_hw_number_t hwirq)
610+
{
611+
int ret;
612+
613+
mutex_lock(&irq_domain_mutex);
614+
ret = irq_domain_associate_locked(domain, virq, hwirq);
615+
mutex_unlock(&irq_domain_mutex);
616+
617+
return ret;
618+
}
610619
EXPORT_SYMBOL_GPL(irq_domain_associate);
611620

612621
void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,

0 commit comments

Comments
 (0)