写驱动时的中断处理:handler 与 threaded IRQ
设备一响 IRQ,驱动要尽快「确认并收尾」,再把重活挪走。硬件中断上下文不能睡,这是写 handler 时最硬的约束。
request_irq 基本形状
static irqreturn_t foo_irq(int irq, void *dev_id)
{
struct foo_dev *d = dev_id;
if (!foo_pending(d))
return IRQ_NONE; /* 共享中断时很重要 */
foo_ack(d); /* 清状态,避免一直打断 */
return IRQ_HANDLED;
}
request_irq(irq, foo_irq, IRQF_SHARED, "foo", d);
上半部尽量短
- 读状态、清中断、必要时 wake 后面的处理
- 不做大块拷贝、不调用可能睡眠的 API
- 共享中断必须能判断「是不是我的设备」并返回
IRQ_NONE
threaded IRQ
若处理逻辑较长,可用 request_threaded_irq():硬中断里快速 ack,线程里做其余工作(线程上下文可以睡)。很多 I2C / 传感器驱动走这条路。
request_threaded_irq(irq, foo_hard, foo_thread,
IRQF_ONESHOT, "foo", d);
IRQF_ONESHOT 会在线程跑完前屏蔽该线,避免硬中断风暴冲刷未处理完的状态。
调试
cat /proc/interrupts
grep foo /proc/interrupts
计数不涨说明没进 handler 或 IRQ 号绑错;涨得离谱却没有业务进展,多半是没有正确 ack,或共享中断误报。
← index