irqdomain: Look for existing mapping only once
[ Upstream commit6e6f75c9c9] 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:b62b2cf575("irqdomain: Fix handling of type settings for existing mappings") Cc: stable@vger.kernel.org # 4.8 Tested-by: Hsin-Yi Wang <hsinyi@chromium.org> Tested-by: Mark-PK Tsai <mark-pk.tsai@mediatek.com> Signed-off-by: Johan Hovold <johan+linaro@kernel.org> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20230213104302.17307-5-johan+linaro@kernel.org Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
6414597815
commit
ff762cdbf0
+40
-34
@@ -637,44 +637,15 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
|
EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
|
||||||
|
|
||||||
/**
|
static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
|
||||||
* irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
|
irq_hw_number_t hwirq,
|
||||||
* @domain: domain owning this hardware interrupt or NULL for default domain
|
const struct irq_affinity_desc *affinity)
|
||||||
* @hwirq: hardware irq number in that domain space
|
|
||||||
* @affinity: irq affinity
|
|
||||||
*
|
|
||||||
* Only one mapping per hardware interrupt is permitted. Returns a linux
|
|
||||||
* irq number.
|
|
||||||
* If the sense/trigger is to be specified, set_irq_type() should be called
|
|
||||||
* on the number returned from that call.
|
|
||||||
*/
|
|
||||||
unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
|
|
||||||
irq_hw_number_t hwirq,
|
|
||||||
const struct irq_affinity_desc *affinity)
|
|
||||||
{
|
{
|
||||||
struct device_node *of_node;
|
struct device_node *of_node = irq_domain_get_of_node(domain);
|
||||||
int virq;
|
int virq;
|
||||||
|
|
||||||
pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
|
pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
|
||||||
|
|
||||||
/* Look for default domain if necessary */
|
|
||||||
if (domain == NULL)
|
|
||||||
domain = irq_default_domain;
|
|
||||||
if (domain == NULL) {
|
|
||||||
WARN(1, "%s(, %lx) called with NULL domain\n", __func__, hwirq);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pr_debug("-> using domain @%p\n", domain);
|
|
||||||
|
|
||||||
of_node = irq_domain_get_of_node(domain);
|
|
||||||
|
|
||||||
/* Check if mapping already exists */
|
|
||||||
virq = irq_find_mapping(domain, hwirq);
|
|
||||||
if (virq) {
|
|
||||||
pr_debug("-> existing mapping on virq %d\n", virq);
|
|
||||||
return virq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate a virtual interrupt number */
|
/* Allocate a virtual interrupt number */
|
||||||
virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
|
virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
|
||||||
affinity);
|
affinity);
|
||||||
@@ -693,6 +664,41 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
|
|||||||
|
|
||||||
return virq;
|
return virq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
|
||||||
|
* @domain: domain owning this hardware interrupt or NULL for default domain
|
||||||
|
* @hwirq: hardware irq number in that domain space
|
||||||
|
* @affinity: irq affinity
|
||||||
|
*
|
||||||
|
* Only one mapping per hardware interrupt is permitted. Returns a linux
|
||||||
|
* irq number.
|
||||||
|
* If the sense/trigger is to be specified, set_irq_type() should be called
|
||||||
|
* on the number returned from that call.
|
||||||
|
*/
|
||||||
|
unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
|
||||||
|
irq_hw_number_t hwirq,
|
||||||
|
const struct irq_affinity_desc *affinity)
|
||||||
|
{
|
||||||
|
int virq;
|
||||||
|
|
||||||
|
/* Look for default domain if necessary */
|
||||||
|
if (domain == NULL)
|
||||||
|
domain = irq_default_domain;
|
||||||
|
if (domain == NULL) {
|
||||||
|
WARN(1, "%s(, %lx) called with NULL domain\n", __func__, hwirq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if mapping already exists */
|
||||||
|
virq = irq_find_mapping(domain, hwirq);
|
||||||
|
if (virq) {
|
||||||
|
pr_debug("existing mapping on virq %d\n", virq);
|
||||||
|
return virq;
|
||||||
|
}
|
||||||
|
|
||||||
|
return __irq_create_mapping_affinity(domain, hwirq, affinity);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
|
EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -831,7 +837,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* Create mapping */
|
/* Create mapping */
|
||||||
virq = irq_create_mapping(domain, hwirq);
|
virq = __irq_create_mapping_affinity(domain, hwirq, NULL);
|
||||||
if (!virq)
|
if (!virq)
|
||||||
return virq;
|
return virq;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user