深入分析request_irq的dev_i…

来源:互联网 发布:java获取12时间戳 编辑:程序博客网 时间:2024/05/23 14:46
原文地址:深入分析request_irq的dev_id参数作用(转)作者:joee33
request_irq的作用是申请使用IRQ并注册中断处理程序。
request_irq()函数的原型如下:

int request_irq(
unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char *devname,
void *dev_id );

我们知道,当使用内核共享中断时,request_irq必须要提供dev_id参数,并且dev_id的值必须唯一。那么这里提供唯一的dev_id值的究竟是做什么用的?

起先我以为dev_id的值是提供给kernel进行判断共享中断线上的哪一个设备产生了中断(即哪个irqaction产生中断),然后执行相应的中断处理函数(irqaction->handler)。实际上不是的,我们来看看《Linux KernelDevelopment – Second Edition》第六章中SharedHandlers这一节,其中有段总结性的文字如下:

When the kernel receives an interrupt, it invokes sequentially eachregistered handler on the line. Therefore, it is important that thehandler be capable of distinguishing whether it generated a giveninterrupt. The handler must quickly exit if its associated devicedid not generate the interrupt. This requires the hardware deviceto have a status register (or similar mechanism) that the handlercan check. Most hardware does indeed have such a feature.

这段话的大概意思是,发生中断时,内核并不判断究竟是共享中断线上的哪个设备产生了中断,它会循环执行所有该中断线上注册的中断处理函数(即irqaction->handler函数)。因此irqaction->handler函数有责任识别出是否是自己的硬件设备产生了中断,然后再执行该中断处理函数。通常是通过读取该硬件设备提供的中断flag标志位进行判断。

那既然kernel循环执行该中断线上注册的所有irqaction->handler函数,把识别究竟是哪个硬件设备产生了中断这件事交给中断处理函数本身去做,那request_irq的dev_id参数究竟是做什么用的?

我总结了一下,实际上dev_id作用主要有两点:
一.在中断处理程序释放时使用到dev_id:
When your driver unloads, you need to unregister your interrupthandler and potentially disable the interrupt line. To do this,call
void free_irq(unsigned int irq, void *dev_id)
……
The fifth parameter, dev_id, is used primarily for shared interruptlines. When an interrupt handler is freed (discussed later), dev_idprovides a unique cookie to allow the removal of only the desiredinterrupt handler from the interrupt line. Without this parameter,it would be impossible for the kernel to know which handler toremove on a given interrupt line.

这里《LKD2》讲了很清楚,当调用free_irq注销中断处理函数时(通常卸载驱动时其中断处理函数也会被注销掉),因为dev_id是唯一的,所以可以通过它来判断从共享中断线上的多个中断处理程序中删除指定的一个。如果没有这个参数,那么kernel不可能知道给定的中断线上到底要删除哪一个处理程序。

下面我们来看一下free_irq的代码:
void free_irq(unsigned int irq, void *dev_id)
{
struct irq_desc *desc;
struct irqaction **p;
unsigned long flags;
WARN_ON(in_interrupt());
if (irq >= NR_IRQS)
return;
desc = irq_desc + irq;
spin_lock_irqsave(&desc->lock,flags);
p = &desc->action;
for (;;) {
struct irqaction *action = *p;
if (action) {
struct irqaction **pp = p;
p = &action->next;
if (action->dev_id != dev_id)
continue;

*pp = action->next;

#ifdef CONFIG_IRQ_RELEASE_METHOD
if (desc->chip->release)
desc->chip->release(irq,dev_id);
#endif
if (!desc->action) {
desc->status |= IRQ_DISABLED;
if (desc->chip->shutdown)
desc->chip->shutdown(irq);
else
desc->chip->disable(irq);
}
recalculate_desc_flags(desc);
spin_unlock_irqrestore(&desc->lock,flags);
unregister_handler_proc(irq, action);

synchronize_irq(irq);
kfree(action);
return;
}
printk(KERN_ERR "Trying to free already-free IRQ %dn", irq);
spin_unlock_irqrestore(&desc->lock,flags);
return;
}
}

二.将使用该中断处理程序的设备结构体传递给该中断处理程序:
首先看两个基础条件:
1) 内核中的各个设备结构体肯定是唯一的,因此满足dev_id唯一这个要求
2) dev_id参数会在发生中断时传递给该中断的服务程序。
典型的中断服务程序定义如下:

static irqreturn_t intr_handler(int irq, void *dev_id, structpt_regs *regs);

即request_irq的dev_id参数会传递给该中断服务程序的dev_id。因此也可以将驱动程序的设备结构体通过dev_id传递给中断服务程序。
这样做作用主要有两个:
1) 中断服务程序可能使用到设备结构体中的信息
如s3c2410的iis音频驱动,它是将DMA Channel结构体通过dev_id传递给中断服务程序

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大学错过了选课怎么办 大学忘记选课了怎么办 火车网上购票儿童票怎么办 售票厅看见小偷怎么办 没赶上火车火车票怎么办 重庆到韩国签证怎么办 重庆去韩国签证怎么办 重庆办韩国签证怎么办 故宫网上预定后怎么办 坐游轮如果晕船怎么办 听听力反应慢怎么办? 毕业证照片丢了怎么办 离线网盘有违规内容怎么办 手机不能向下拉怎么办 cad运行不了插件怎么办 ai中缺少文字怎么办 电脑被格式化了怎么办 迷你世界地图下载失败怎么办 网页上广告太多怎么办 网页打开广告太多怎么办 PS界面图标小怎么办 百度地图反应慢怎么办 汽车导航不播报怎么办 wps菜单栏隐藏了怎么办 手机导航声音小怎么办 手机导航不好用怎么办 手机导航箭头不准怎么办 手机处于离线状态怎么办 穷人让人看不起怎么办 非洲人口过多怎么办啊 鼻子上长白头怎么办 高铁查到违禁品怎么办 青岛涂料备案证怎么办 淘宝集运不能寄怎么办 防静电指数过高怎么办 手机玻璃上裂痕怎么办 车辆环保检测不合格怎么办 眼镜被擦破镜片怎么办 手机边框有刮痕怎么办 手机金属壳磨损怎么办 手机后面凹下去怎么办