Linux 卸载驱动时,提示:Trying to free already-free IRQ

一、背景

一个简单的字符设备驱动程序,程序里面需要实现IO 口的下降沿中断。驱动程序编译正常,注册正常,也能正常识别出IO中断,并响应中断处理函数。在卸载驱动程序时,提示如下:

WARNING: CPU: 0 PID: 100 at kernel/irq/manage.c:1346 __free_irq+0xa4/0x1ec()
Trying to free already-free IRQ 46

二、问题分析、解决

1. 中断相关的函数原型与程序中的调用方法

申请中断

request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
            const char *name, void *dev);
request_irq( g_key.irq_num, key_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
            "key_irq", &g_key );

释放中断

void free_irq(unsigned int irq, void *dev_id);
free_irq( g_key.irq_num, 0 );

2. 怀疑与疑问

如上所示,free_irq 第二个参数填入的是0,并没有填入 dev_id 。释放中断不是直接根据中断号就能释放了吗?跟dev_id 有关?

3. 查阅 free_irq 的源码

3.1 free_irq

free_irq 定义在文件 linux_kernel/kernel/irq/manage.c

void free_irq(unsigned int irq, void *dev_id)
{
  struct irq_desc *desc = irq_to_desc(irq);

  if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
    return;

#ifdef CONFIG_SMP
  if (WARN_ON(desc->affinity_notify))
    desc->affinity_notify = NULL;
#endif

  chip_bus_lock(desc);
  kfree(__free_irq(irq, dev_id));
  chip_bus_sync_unlock(desc);
}

从上可以看到,释放中断的主要操作是在函数 __free_irq 中实现,dev_id 参数也是传进 __free_irq 中使用。所以需要查看 __free_irq 函数的实现。

3.2 查阅 __free_irq 的源码实现

  static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
  {
   ...
  
  for (;;) {
    action = *action_ptr;

    if (!action) {
      WARN(1, "Trying to free already-free IRQ %d\n", irq);
      raw_spin_unlock_irqrestore(&desc->lock, flags);

      return NULL;
    }

    if (action->dev_id == dev_id)
      break;
    action_ptr = &action->next;
  }
  ...
  
  }

上面源码,略去了前后部分代码。源码中,会判断request_irq 填入的 dev_id free_irq dev_id (也就是第二个参数),如果一致,才会退出循环。

4. 问题解决

free_irq 调用改成如下所示:

free_irq( g_key.irq_num, &g_key );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gdut_llkkyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值