Skip to content

Commit 6e6f75c

Browse files
jhovoldMarc Zyngier
authored andcommitted
irqdomain: Look for existing mapping only once
Avoid looking for an existing mapping twice when creating a new mapping using irq_create_fwspec_mapping() by factoring out the actual allocation which is shared with irq_create_mapping_affinity(). The new helper function will also 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 e3b7ab0 commit 6e6f75c

File tree

1 file changed

+33
-27
lines changed

1 file changed

+33
-27
lines changed

kernel/irq/irqdomain.c

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,34 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
682682
EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
683683
#endif
684684

685+
static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
686+
irq_hw_number_t hwirq,
687+
const struct irq_affinity_desc *affinity)
688+
{
689+
struct device_node *of_node = irq_domain_get_of_node(domain);
690+
int virq;
691+
692+
pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
693+
694+
/* Allocate a virtual interrupt number */
695+
virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
696+
affinity);
697+
if (virq <= 0) {
698+
pr_debug("-> virq allocation failed\n");
699+
return 0;
700+
}
701+
702+
if (irq_domain_associate(domain, virq, hwirq)) {
703+
irq_free_desc(virq);
704+
return 0;
705+
}
706+
707+
pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
708+
hwirq, of_node_full_name(of_node), virq);
709+
710+
return virq;
711+
}
712+
685713
/**
686714
* irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
687715
* @domain: domain owning this hardware interrupt or NULL for default domain
@@ -694,49 +722,27 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
694722
* on the number returned from that call.
695723
*/
696724
unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
697-
irq_hw_number_t hwirq,
698-
const struct irq_affinity_desc *affinity)
725+
irq_hw_number_t hwirq,
726+
const struct irq_affinity_desc *affinity)
699727
{
700-
struct device_node *of_node;
701728
int virq;
702729

703-
pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
704-
705730
/* Look for default domain if necessary */
706731
if (domain == NULL)
707732
domain = irq_default_domain;
708733
if (domain == NULL) {
709734
WARN(1, "%s(, %lx) called with NULL domain\n", __func__, hwirq);
710735
return 0;
711736
}
712-
pr_debug("-> using domain @%p\n", domain);
713-
714-
of_node = irq_domain_get_of_node(domain);
715737

716738
/* Check if mapping already exists */
717739
virq = irq_find_mapping(domain, hwirq);
718740
if (virq) {
719-
pr_debug("-> existing mapping on virq %d\n", virq);
741+
pr_debug("existing mapping on virq %d\n", virq);
720742
return virq;
721743
}
722744

723-
/* Allocate a virtual interrupt number */
724-
virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
725-
affinity);
726-
if (virq <= 0) {
727-
pr_debug("-> virq allocation failed\n");
728-
return 0;
729-
}
730-
731-
if (irq_domain_associate(domain, virq, hwirq)) {
732-
irq_free_desc(virq);
733-
return 0;
734-
}
735-
736-
pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
737-
hwirq, of_node_full_name(of_node), virq);
738-
739-
return virq;
745+
return __irq_create_mapping_affinity(domain, hwirq, affinity);
740746
}
741747
EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
742748

@@ -841,7 +847,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
841847
return 0;
842848
} else {
843849
/* Create mapping */
844-
virq = irq_create_mapping(domain, hwirq);
850+
virq = __irq_create_mapping_affinity(domain, hwirq, NULL);
845851
if (!virq)
846852
return virq;
847853
}

0 commit comments

Comments
 (0)