[Q&A23103]调用 enable_irq() 函数提示 Unbalanced enable for IRQ

文章讨论了在调试红外驱动时遇到的UnbalancedenableforIRQ问题,通过分析IRQ相关代码发现,enable_irq和disable_irq的嵌套调用必须平衡,depth计数器用于跟踪。解决方法是确保disable_irq调用在enable_irq之前,移除不恰当的enable_irq调用后问题消失。
摘要由CSDN通过智能技术生成

[DESCRIPTION]

在调试红外驱动的过程中,发现在调用 enable_irq() 函数时 Linux 内核日志会打印出这样的信息:Unbalanced enable for IRQ。

request_irq(infrared_irq, infrared_interrut_handler, IRQF_TRIGGER_FALLING, "infrared", NULL));
enable_irq_wake(infrared_irq)

[SOLUTION]

(1)为了搞清楚这个现象的原因,分析了 IRQ 的相关代码,发现其中使用了 struct irq_desc 结构体的成员变量 depth 来记录 disable irq 的嵌套深度。也就是说,enable_irq() 和 disable_irq() 调用可以嵌套,但调用次数要匹配。disable_irq() 调用要在前面,否则就会提示:Unbalanced enable for IRQ。

// 中断描述符结构体
struct irq_desc {
    ... // 省略部分代码
	unsigned int depth;  /* nested irq disables */
    ... // 省略部分代码
};

// 使能中断 API
void enable_irq(unsigned int irq)
{
    ... // 省略部分代码
	__enable_irq(desc);
    ... // 省略部分代码
}

void __enable_irq(struct irq_desc *desc)
{
	switch (desc->depth) {
	case 0:
 err_out:
		WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", // [DESCRIPTION] 提到的内核日志
		     irq_desc_get_irq(desc));
		break;
	case 1: {	
		if (desc->istate & IRQS_SUSPENDED)
			goto err_out;
		/* Prevent probing on this irq: */
		irq_settings_set_noprobe(desc);
		/*
		 * Call irq_startup() not irq_enable() here because the
		 * interrupt might be marked NOAUTOEN. So irq_startup()
		 * needs to be invoked when it gets enabled the first
		 * time. If it was already started up, then irq_startup()
		 * will invoke irq_enable() under the hood.
		 */
		irq_startup(desc, IRQ_RESEND, IRQ_START_COND);
		break;
	}
	default:
		desc->depth--;
	}
}

// 禁用中断 API
void disable_irq(unsigned int irq)
{
	if (!__disable_irq_nosync(irq))
		synchronize_irq(irq);
}

static int __disable_irq_nosync(unsigned int irq)
{
    ... // 省略部分代码
	__disable_irq(desc);
    ... // 省略部分代码
}

void __disable_irq(struct irq_desc *desc)
{
	if (!desc->depth++) {
		irq_disable(desc);
	}
}

(2)去掉 enable_irq() 调用后,内核日志不再打印 Unbalanced enable for IRQ。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值