Part 7: Interrupt Handling
Interrupts allow hardware to signal the CPU that an event has occurred. Writing correct interrupt handlers is critical for responsive, stable drivers.
Interrupt Flow Overview
flowchart TB
subgraph Hardware
DEV[Device]
PIC[Interrupt Controller]
CPU[CPU]
end
subgraph Kernel["Linux Kernel"]
IDT[Interrupt Descriptor Table]
GIH[Generic IRQ Handler]
DRV[Your Driver Handler]
end
subgraph Response["Response"]
IMM[Immediate Work]
DEF[Deferred Work]
end
DEV -->|"Assert IRQ line"| PIC
PIC -->|"Signal CPU"| CPU
CPU -->|"Lookup handler"| IDT
IDT --> GIH
GIH -->|"Call registered handler"| DRV
DRV --> IMM
DRV -->|"Schedule"| DEF
style Hardware fill:#738f99,stroke:#0277bd
style Kernel fill:#8f8a73,stroke:#f9a825
style Response fill:#8f7392,stroke:#6a1b9a
Chapter Contents
| Chapter | Topic | Key Concepts |
|---|---|---|
| 7.1 | Interrupt Concepts | Hardware interrupts, IRQ numbers, contexts |
| 7.2 | Requesting IRQs | request_irq, devm_request_irq, free_irq |
| 7.3 | Interrupt Handlers | Handler structure, return values, context |
| 7.4 | Top and Bottom Halves | Splitting work, deferred execution |
| 7.5 | Tasklets | tasklet_struct, scheduling, usage |
| 7.6 | Threaded IRQs | request_threaded_irq, hard/thread handlers |
| 7.7 | Shared Interrupts | IRQF_SHARED, checking ownership |
| 7.8 | Interrupt Control | Enable/disable, IRQ affinity, edge vs level |
Key Concepts
The Interrupt Handling Model
sequenceDiagram
participant HW as Hardware
participant CPU as CPU
participant TOP as Top Half (hardirq)
participant BOT as Bottom Half
HW->>CPU: Interrupt signal
CPU->>CPU: Save context
CPU->>TOP: Call handler
Note over TOP: Runs with IRQs disabled
TOP->>TOP: Acknowledge interrupt
TOP->>TOP: Read/write urgent data
TOP->>BOT: Schedule deferred work
TOP->>CPU: Return IRQ_HANDLED
CPU->>CPU: Restore context
Note over BOT: Runs later with IRQs enabled
BOT->>BOT: Process data
BOT->>BOT: Wake waiters
Why Split Work?
Interrupt handlers run with interrupts disabled (or at least their own IRQ masked). Long handlers:
- Increase latency for other interrupts
- Block preemption on that CPU
- Can cause system instability if they take too long
The solution: Do minimal work in the handler, defer the rest.
Bottom Half Mechanisms
flowchart TB
IRQ[Interrupt Handler]
subgraph Mechanisms["Deferred Work Options"]
TL[Tasklet]
WQ[Workqueue]
TH[Threaded Handler]
ST[Softirq]
end
IRQ -->|"Atomic context"| TL
IRQ -->|"Can sleep"| WQ
IRQ -->|"Simple case"| TH
IRQ -->|"High perf"| ST
TL -->|"Softirq context"| Note1["Fast, can't sleep"]
WQ -->|"Process context"| Note2["Can sleep, mutex ok"]
TH -->|"Kernel thread"| Note3["Preferred for drivers"]
ST -->|"Direct softirq"| Note4["Reserved for core kernel"]
style IRQ fill:#8f6d72,stroke:#c62828
style TL fill:#8f8a73,stroke:#f9a825
style WQ fill:#7a8f73,stroke:#2e7d32
style TH fill:#738f99,stroke:#0277bd
style ST fill:#8f7392,stroke:#6a1b9a
Interrupt Handler Rules
What You CAN Do
- Read/write device registers
- Acknowledge the interrupt
- Schedule deferred work
- Wake up waiting processes
- Update statistics (atomic operations)
What You CANNOT Do
- Sleep or call functions that might sleep
- Allocate memory with GFP_KERNEL
- Acquire mutexes
- Call copy_to_user/copy_from_user
- Take a long time (keep it fast!)
Common Patterns
Simple Handler (No Deferred Work)
static irqreturn_t simple_handler(int irq, void *dev_id)
{
struct my_device *dev = dev_id;
/* Read status and acknowledge */
u32 status = readl(dev->regs + STATUS);
writel(status, dev->regs + STATUS); /* Clear interrupt */
return IRQ_HANDLED;
}
Handler with Threaded Work
/* Fast top half */
static irqreturn_t my_hardirq(int irq, void *dev_id)
{
struct my_device *dev = dev_id;
if (!device_generated_irq(dev))
return IRQ_NONE;
/* Acknowledge hardware */
writel(0, dev->regs + IRQ_ACK);
return IRQ_WAKE_THREAD; /* Run threaded handler */
}
/* Threaded bottom half - can sleep */
static irqreturn_t my_thread(int irq, void *dev_id)
{
struct my_device *dev = dev_id;
/* Process data, can sleep here */
process_data(dev);
wake_up_interruptible(&dev->waitq);
return IRQ_HANDLED;
}
Examples
This part includes working examples:
- irq-handler: Complete interrupt handling with threaded IRQ
Prerequisites
Before starting this part, ensure you understand:
- Device model and platform drivers (Part 6)
- Concurrency concepts (Part 4)
- Memory management (Part 5)
Further Reading
- IRQ Domain Documentation - IRQ subsystem guide
- Generic IRQ - Generic IRQ handling
Next
Start with Interrupt Concepts to understand how hardware interrupts work.