你好!这里是风筝的博客,
欢迎和我一起交流。
irq 286: nobody cared (try booting with the “irqpoll” option)
之前看到这个一个warning,我看网上其他人写的有点奇怪,手痒特此记录一下:
通过grep查找代码,可以发现这行语句在:__report_bad_irq函数:
static inline int bad_action_ret(irqreturn_t action_ret)
{
if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD)))
return 0;
return 1;
}
static void __report_bad_irq(struct irq_desc *desc, irqreturn_t action_ret)
{
unsigned int irq = irq_desc_get_irq(desc);
struct irqaction *action;
unsigned long flags;
if (bad_action_ret(action_ret)) {
printk(KERN_ERR "irq event %d: bogus return value %x\n",
irq, action_ret);
} else {
printk(KERN_ERR "irq %d: nobody cared (try booting with "
"the \"irqpoll\" option)\n", irq);
}
......
}
当bad_action_ret函数返回0的时候,也就是action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD)的时候,就会有这条打印。
那action_ret 参数是哪里传进来的呢?继续往上看:
void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret)
{
unsigned int irq;
if (desc->istate & IRQS_POLL_INPROGRESS ||
irq_settings_is_polled(desc))
return;
if (bad_action_ret(action_ret)) {//一般不会为1,为1的话是不会打印nobody cared这个log的
report_bad_irq(desc, action_ret);
return;
}
......
if (unlikely(action_ret == IRQ_NONE)) {
/*
* If we are seeing only the odd spurious IRQ caused by
* bus asynchronicity then don't eventually trigger an error,
* otherwise the counter becomes a doomsday timer for otherwise
* working systems
*/
if (time_after(jiffies, desc->last_unhandled + HZ/10))
desc->irqs_unhandled = 1;
else
desc->irqs_unhandled++;
desc->last_unhandled = jiffies;
}
......
if (unlikely(desc->irqs_unhandled > 99900)) {
/*
* The interrupt is stuck
*/
__report_bad_irq(desc, action_ret);//在这里调用
/*
* Now kill the IRQ
*/
printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
desc->istate |= IRQS_SPURIOUS_DISABLED;
desc->depth++;
irq_disable(desc);
mod_timer(&poll_spurious_irq_timer,
jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
}
desc->irqs_unhandled = 0;
}
note_interrupt函数省略了一些不重要的代码。
函数里面可以看出,当action_ret 参数为IRQ_NONE时,irqs_unhandled会一直累计计数,irqs_unhandled大于99900时,就会调用__report_bad_irq函数,就有可能会打印log:irq xx: nobody cared (try booting with the “irqpoll” option)
这里我们还是没有搞清楚action_ret 从哪里来,继续往上看:
有两个函数可能调用了note_interrupt函数,一个是:handle_nested_irq(desc, action_ret),另一个是:handle_irq_event_percpu(desc, retval)。
仔细看可以发现,不管是哪个函数,都应该可以知道,action_ret就是我们在写驱动时,注册中断的回调函数。
而且IRQ_NONE是<= (IRQ_HANDLED | IRQ_WAKE_THREAD)的,所以必定会显示出那个log:irq xx: nobody cared (try booting with the “irqpoll” option)
所以我们可以得出结论:驱动代码里注册的中断回调里返回了IRQ_NONE,且中断被触发了99900次,就会有这条log打印
事实也是如此,根据oops里面的堆栈信息,找到对应驱动里的中断函数,确实发现是因为返回了IRQ_NONE
更多推荐
irq: nobody cared (try booting with the “irqpoll” option)
发布评论