irq: nobody cared (try booting with the “irqpoll” option)

你好!这里是风筝的博客,
欢迎和我一起交流。

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

猜你喜欢

转载自blog.csdn.net/Guet_Kite/article/details/106689126
try
今日推荐