This used to be a fair API comparison. Today it is also a version trap: setup_irq() appears in old BSPs, but it is absent from current mainline. That changes what a driver author should copy.
The difference at a glance
setup_irq(): older kernels accepted a caller-owned
struct irqactionfor static setup.request_irq(): the public driver API accepts a handler, flags, name, and identity cookie.
Ownership: setup_irq callers supplied persistent action storage; request APIs allocate and manage it internally.
Cleanup: pair
request_irq()withfree_irq(); device-managed requests follow device lifetime.Current status: mainline documents request_irq but no longer contains setup_irq.
Why old kernels had setup_irq
static struct irqaction timer_action = {
.handler = timer_interrupt,
.flags = IRQF_TIMER,
.name = "platform-timer",
};
ret = setup_irq(timer_irq, &timer_action);Historical context—not a template for a new driver.
What the static action implied
struct irqactionis the IRQ core action descriptor, not merely a callback.Static storage remains valid for the registration lifetime; stack storage would be invalid.
IRQF_TIMERcarries timer-specific behavior in kernels that define it.Linux 4.9 GPL-exported setup_irq, but ordinary drivers were still expected to use request APIs.
What request_irq does today
request_irq(irq, handler, flags, name, dev_id)
-> request_threaded_irq(irq, handler, NULL,
flags | IRQF_COND_ONESHOT,
name, dev_id);The wrapper carries real semantics
irqis a Linux IRQ number resolved through bus or firmware resources.handlerruns in hard-interrupt context and must not sleep.dev_idreturns to the handler and identifies an action on a shared line.Handling may begin immediately after success, so driver state must already be safe.
A current platform-driver pattern
static irqreturn_t example_irq(int irq, void *data)
{
struct example_dev *priv = data;
u32 status = readl(priv->base + STATUS_REG);
if (!(status & IRQ_PENDING))
return IRQ_NONE;
writel(status, priv->base + STATUS_REG);
return IRQ_HANDLED;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
return devm_request_irq(&pdev->dev, irq, example_irq, 0,
dev_name(&pdev->dev), priv);Why this fits probe lifetime
platform_get_irq()resolves the resource and propagates errors.devm_request_irq()releases registration during probe rollback or detach.IRQ_NONEmatters when the device did not raise a shared interrupt.Acknowledgement order is hardware-specific and must follow the datasheet.
When the handler needs to sleep
ret = devm_request_threaded_irq(dev, irq,
example_irq_top, example_irq_thread,
IRQF_ONESHOT, dev_name(dev), priv);
static irqreturn_t example_irq_top(int irq, void *data)
{
return IRQ_WAKE_THREAD;
}Separate the execution contexts
The primary handler runs in hard-IRQ context and returns
IRQ_WAKE_THREAD.The threaded function runs in process context and may use sleepable operations.
IRQF_ONESHOTkeeps the line masked while the thread runs when required.A NULL primary is supported when a thread function is supplied.
Manual ownership and teardown
ret = request_irq(irq, example_irq, IRQF_SHARED,
"example", priv);
if (ret)
return ret;
/* Quiesce the device first, then: */
free_irq(irq, priv);The cookie is contractual
Shared IRQ actions require a unique, non-NULL
dev_id.Pass the identical cookie to
free_irq().free_irq()waits for active handlers and cannot run in interrupt context.Disable the device interrupt source before freeing its handler.
Mistakes that survive code review
Copying setup_irq: it may be absent or unexported in the target kernel.
Sleeping in a hard handler: move blocking work to a threaded IRQ.
Enabling hardware too early: an interrupt can arrive immediately after registration.
Freeing before quiescing: hardware can call into released state.
Confusing IRQs with vectors: irqdomains translate hardware specifiers into Linux IRQs.
Verify the exact source tree
git grep -n setup_irq -- include kernel arch drivers
git grep -n 'request_irq(' -- include/linux/interrupt.h
git log -Ssetup_irq -- kernel/irq/manage.c include/linux/interrupt.hinclude/linux/interrupt.h:... request_irq(...)
# Current mainline may return no setup_irq matches.Source history beats memory
git grepchecks the selected kernel, including vendor changes.git log -Straces addition or removal of the exact token.A vendor tree can retain an API after upstream removal.
These commands are read-only.
References
Generic IRQ documentation defines the supported high-level API.
Current interrupt.h shows request wrappers.
Linux 4.9 IRQ source preserves historical setup_irq.
Comments and corrections