前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >disable_irq/enable_irq使用不匹配

disable_irq/enable_irq使用不匹配

作者头像
DragonKingZhu
发布2022-05-08 16:44:57
7250
发布2022-05-08 16:44:57
举报

最近在一次稳定性测试中,发现Kernel Log中出现了如下的Warring,如下:

代码语言:javascript
复制
WARNING: CPU: 4 PID: 2956 at /space/builder/repo/sprdroid6.0_trunk_k318_dev/kernel/kernel/irq/manage.c:444 __enable_irq+0x50/0x94()
Unbalanced enable for IRQ 227

Call trace:
c4 [<ffffffc00008b480>] dump_backtrace+0x0/0x164
c4 [<ffffffc00008b600>] show_stack+0x1c/0x28
c4 [<ffffffc0009ceefc>] dump_stack+0x74/0xb8
c4 [<ffffffc0000bb340>] warn_slowpath_common+0x98/0xc0
c4 [<ffffffc0000bb3dc>] warn_slowpath_fmt+0x74/0x88
c4 [<ffffffc00010eb50>] __enable_irq+0x4c/0x94
c4 [<ffffffc00010ebd8>] enable_irq+0x40/0x80
c4 [<ffffffc000630a38>] spidev_ioctl+0x6e4/0xbc0
c4 [<ffffffc0002016f0>] do_vfs_ioctl+0x374/0x5b8
c4 [<ffffffc0002019c0>] SyS_ioctl+0x8c/0xa4
c4 ---[ end trace 3e8cbdaab32a5c30 ]---

根据Kernel log的提示,在内核源码中找到出错的地方:

代码语言:javascript
复制
<kernel/irq/manage.c>
--------------------------------------------------------
void __enable_irq(struct irq_desc *desc, unsigned int irq)
{
    switch (desc->depth) {
    case 0:
 err_out:
        WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
        break;
    case 1: {
        if (desc->istate & IRQS_SUSPENDED)
            goto err_out;
        /* Prevent probing on this irq: */
        irq_settings_set_noprobe(desc);
        irq_enable(desc);
        check_irq_resend(desc, irq);
        /* fall-through */
    }
    default:
        desc->depth--;
    }
}

可以看到当desc->depth等于0的时候,就会出现上述的log。

而出现此问题的原因是什么? 或者是谁导致出现了这种情况?

通过栈调用关系可以看出,应用程序通过ioctl命令去操作底层的指纹识别的过程出现的。 SyS_ioct->do_vfs_ioctl->spidev_ioctl->enable_irq->__enable_irq

从调用关系看,最后调用__enable_irq的时候desc->depth=0,出现了“Unbalanced enable for IRQ”, 而根据字面意思是“使能不匹配的IRQ”。

根据提示猜想,是不是enable_irq需要与disable_irq成对的匹配调用。

基于此猜想,可以通过disable_irq与enable_irq的源代码验证猜想。

先看disable_irq的代码:

代码语言:javascript
复制
<kernel/irq/manage.c>
---------------------------------------------------------------------
void __disable_irq(struct irq_desc *desc, unsigned int irq)
{
    if (!desc->depth++)
        irq_disable(desc);
}

从代码可以看出disable_irq的时候,对desc->depth做++操作。

代码语言:javascript
复制
<kernel/irq/manage.c>
---------------------------------------------------------------------
void __enable_irq(struct irq_desc *desc, unsigned int irq)
{
    switch (desc->depth) {
    case 0:
 err_out:
        WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
        break;
    case 1: {
        if (desc->istate & IRQS_SUSPENDED)
            goto err_out;
        /* Prevent probing on this irq: */
        irq_settings_set_noprobe(desc);
        irq_enable(desc);
        check_irq_resend(desc, irq);
        /* fall-through */
    }
    default:
        desc->depth--;
    }
}

而__enable_irq代码是对desc->depth做–操作了。

根据一个做++操作,一个做–操作。可以得出disable_irq与enable_irq需要成对的使用。

而出现上述的原因就是在没有调用disable_irq的前提下,直接调用enable_irq,那时候desc->depth等于0,这时候enable_irq就会出现Warring, 也就是说这次的enable_irq没有起作用的。

假设驱动中先disable_irq,这时候desc->depth++了, desc->depth就等于1, 而这时候再次enable_irq就会走进case 1的分支中去。 然后desc->depth–了,最后desc->depth等于0

所以根据分析,出现上述的原因就是enable_irq与disable_irq在驱动中没有匹配使用导致的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档