Re: About irq_create_affinity_masks() for a platform device driver

From: John Garry
Date: Mon Feb 03 2020 - 10:00:46 EST


Hi Thomas,


pirqs = kzalloc(*count * sizeof(int), GFP_KERNEL);
if (!pirqs)
return -ENOMEM;

dev->desc = irq_create_affinity_masks(*count, affd);
if (!dev->desc) {
kfree(irqs);

pirqs I assume and this also leaks the affinity masks and the pointer in
dev.

Right


return -ENOMEM;
}

for (i = 0; i < *count; i++) {
pirqs[i] = platform_get_irq(dev, i);
if (irqs[i] < 0) {
kfree(dev->desc);
kfree(irqs);
return -ENOMEM;

That's obviously broken as well :)

Right, again


}
}

*irqs = pirqs;

return 0;
}
EXPORT_SYMBOL_GPL(platform_get_irqs_affinity);

[...]


I wouldn't mind to expose a function which allows you to switch the
allocated interrupts to managed. The reason why we do it in one go in
the PCI code is that we get automatically the irq descriptors allocated
on the correct node. So if the node aware allocation is not a
showstopper

I wouldn't say so for now.

for this then your function would do:

...
for (i = 0; i < count; i++) {
pirqs[i] = platform_get_irq(dev, i);

irq_update_affinity_desc(pirqs[i], affdescs + i);

}

int irq_update_affinity_desc(unsigned int irq, irq_affinity_desc *affinity)
{
unsigned long flags;
struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);

if (!desc)
return -EINVAL;

if (affinity->is_managed) {
irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);

Are these correct? I assume we want to follow alloc_descs() here.

}
cpumask_copy(desc->irq_common_data.affinity, affinity);
return 0;
}

I see. So I made a couple of changes and it did work:

int irq_update_affinity_desc(unsigned int irq, struct irq_affinity_desc *affinity)
{
unsigned long flags;
struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);

if (!desc)
return -EINVAL;

if (affinity->is_managed) {
irqd_set(&desc->irq_data, IRQD_AFFINITY_MANAGED);
irqd_set(&desc->irq_data, IRQD_MANAGED_SHUTDOWN);
}

cpumask_copy(desc->irq_common_data.affinity, &affinity->mask);
irq_put_desc_unlock(desc, flags);
return 0;
}

And if we were to go this way, then we don't need to add the pointer in struct platform_device to hold affinity mask descriptors as we're using them immediately. Or even have a single function to do it all in the irq code (create the masks and update the affinity desc).

And since we're just updating the masks, I figure we shouldn't need to add acpi_irq_get_count(), which I invented to get the irq count (without creating the IRQ mapping).

Thanks,
John