kernel 中断分析之四——中断申请 [下]

前言

kernel 中断分析之四——中断申请 [上]中,request_irq、request_threaded_irq、setup_irq、setup_percpu_irq、request_percpu_irq最终都调用了__setup_irq,本篇对该API进行分析,由于代码比较长,分段分析。

请注意,在分析过程中,遇到一些拿捏不定的地方,以用粗体表示,如果有理解错误,欢迎指正。

__setup_irq——线程化处理

   895 /*
   896  * Internal function to register an irqaction - typically used to
   897  * allocate special interrupts that are part of the architecture.
   898  */
   899 static int
   900 __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
   901 {
   902     struct irqaction *old, **old_ptr;
   903     unsigned long flags, thread_mask = 0;
   904     int ret, nested, shared = 0;
   905     cpumask_var_t mask;
   906
   907     if (!desc)
   908         return -EINVAL;
   909
   910     if (desc->irq_data.chip == &no_irq_chip)
   911         return -ENOSYS;
   912     if (!try_module_get(desc->owner))
   913         return -ENODEV;
   914
   915     /*
   916      * Check whether the interrupt nests into another interrupt
   917      * thread.
   918      */
   919     nested = irq_settings_is_nested_thread(desc);    //判断是否是嵌套中断线程,关于中断嵌套的处理,在后续有分析
   920     if (nested) {
   921         if (!new->thread_fn) {    //嵌套中断不需要有handler,但是thread_fn要有的
   922             ret = -EINVAL;
   923             goto out_mput;
   924         }
   925         /*
   926          * Replace the primary handler which was provided from
   927          * the driver for non nested interrupt handling by the
   928          * dummy function which warns when called.
   929          */
   930         new->handler = irq_nested_primary_handler; //抛出一个警告,nested irq的调用时父中断的handler中处理的,而不是在这里
   931     } else {
   932         if (irq_settings_can_thread(desc))  //有的中断不允许线程化,设置了IRQ_NOTHREAD标志
   933             irq_setup_forced_threading(new); //强制线程化
   934     }

irq_setup_forced_threading

   879 static void irq_setup_forced_threading(struct irqaction *new)
   880 {
   881     if (!force_irqthreads)  //该全局变量用于表示系统是否允许中断线程化
   882         return;
   883     if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT)) //IRQF_NO_THREAD 或者percpu中断或者已经线程化的中断,直接返回
   884         return;
   885
   886     new->flags |= IRQF_ONESHOT;  //线程化中断需要设置IRQF_ONESHOT标志
   887//如果thread为NULL(那么handler必不为NULL),此时为了线程化,强制将handler赋给thread_fn,handler设置为irq_default_primary_handler
   888     if (!new->thread_fn) { 
   889         set_bit(IRQTF_FORCED_THREAD, &new->thread_flags); //thread_flags设置IRQTF_FORCED_THREAD,表示经过强制线程化
   890         new->thread_fn = new->handler;
   891         new->handler = irq_default_primary_handler;
   892     }
   893 }

我对上述代码的理解,不一定正确:目前的内核实现机制,非nested irq,且非IRQ_NOTHREAD,内核都会将其强制线程化。
以下是IRQF_ONESHOT 的注释:

 52  * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
 53  *                Used by threaded interrupts which need to keep the
 54  *                irq line disabled until the threaded handler has been run.

另外摘录upstream上IRQF_ONESHOT的commit message如下:

For threaded interrupt handlers we expect the hard interrupt handler
part to mask the interrupt on the originating device. The interrupt
line itself is reenabled after the hard interrupt handler has
executed.

This requires access to 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值