genirq: Factor-in percpu irqaction creation

Move the code creating a per-cpu irqaction into its own helper, so that
future changes to this code can be kept localised.

At the same time, fix the documentation which appears to say the wrong
thing when it comes to interrupts being automatically enabled
(percpu_devid interrupts never are).

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Will Deacon <will@kernel.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20251020122944.3074811-14-maz@kernel.org
pull/1354/merge
Marc Zyngier 2025-10-20 13:29:30 +01:00 committed by Thomas Gleixner
parent 5c2b2cc472
commit 9047a39daa
1 changed files with 24 additions and 16 deletions

View File

@ -2442,6 +2442,24 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
return retval; return retval;
} }
static
struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long flags,
const char *devname, void __percpu *dev_id)
{
struct irqaction *action;
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
return NULL;
action->handler = handler;
action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
action->name = devname;
action->percpu_dev_id = dev_id;
return action;
}
/** /**
* __request_percpu_irq - allocate a percpu interrupt line * __request_percpu_irq - allocate a percpu interrupt line
* @irq: Interrupt line to allocate * @irq: Interrupt line to allocate
@ -2450,9 +2468,9 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
* @devname: An ascii name for the claiming device * @devname: An ascii name for the claiming device
* @dev_id: A percpu cookie passed back to the handler function * @dev_id: A percpu cookie passed back to the handler function
* *
* This call allocates interrupt resources and enables the interrupt on the * This call allocates interrupt resources, but doesn't enable the interrupt
* local CPU. If the interrupt is supposed to be enabled on other CPUs, it * on any CPU, as all percpu-devid interrupts are flagged with IRQ_NOAUTOEN.
* has to be done on each CPU using enable_percpu_irq(). * It has to be done on each CPU using enable_percpu_irq().
* *
* @dev_id must be globally unique. It is a per-cpu variable, and * @dev_id must be globally unique. It is a per-cpu variable, and
* the handler gets called with the interrupted CPU's instance of * the handler gets called with the interrupted CPU's instance of
@ -2477,15 +2495,10 @@ int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
if (flags && flags != IRQF_TIMER) if (flags && flags != IRQF_TIMER)
return -EINVAL; return -EINVAL;
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); action = create_percpu_irqaction(handler, flags, devname, dev_id);
if (!action) if (!action)
return -ENOMEM; return -ENOMEM;
action->handler = handler;
action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
action->name = devname;
action->percpu_dev_id = dev_id;
retval = irq_chip_pm_get(&desc->irq_data); retval = irq_chip_pm_get(&desc->irq_data);
if (retval < 0) { if (retval < 0) {
kfree(action); kfree(action);
@ -2546,16 +2559,11 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
if (irq_is_nmi(desc)) if (irq_is_nmi(desc))
return -EINVAL; return -EINVAL;
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); action = create_percpu_irqaction(handler, IRQF_NO_THREAD | IRQF_NOBALANCING,
name, dev_id);
if (!action) if (!action)
return -ENOMEM; return -ENOMEM;
action->handler = handler;
action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND | IRQF_NO_THREAD
| IRQF_NOBALANCING;
action->name = name;
action->percpu_dev_id = dev_id;
retval = irq_chip_pm_get(&desc->irq_data); retval = irq_chip_pm_get(&desc->irq_data);
if (retval < 0) if (retval < 0)
goto err_out; goto err_out;