@@ -663,7 +663,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
/* Check if mapping already exists */
virq = irq_find_mapping(domain, hwirq);
if (virq) {
+ desc = irq_to_desc(virq);
pr_debug("-> existing mapping on virq %d\n", virq);
+ kobject_get(&desc->kobj);
return virq;
}
@@ -762,6 +764,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
int virq;
+ struct irq_desc *desc;
if (fwspec->fwnode) {
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
@@ -798,8 +801,11 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
* current trigger type then we are done so return the
* interrupt number.
*/
- if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
+ if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq)) {
+ desc = irq_to_desc(virq);
+ kobject_get(&desc->kobj);
return virq;
+ }
/*
* If the trigger type has not been set yet, then set
@@ -811,6 +817,8 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
return 0;
irqd_set_trigger_type(irq_data, type);
+ desc = irq_to_desc(virq);
+ kobject_get(&desc->kobj);
return virq;
}
This references an irq_desc if already mapped interrupt requested to map again. This happends for PCI legacy interrupts where 4 interrupts are shared among all devices on the same PCI host bus adapter. From now on, the users shall call irq_dispose_mapping() for every irq_create_fwspec_mapping(). Most (all?) users do not bother with disposing though so it is not very likely to break many things. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> --- kernel/irq/irqdomain.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)