关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
2014-12-09 16:44
375 查看
disable_irq关闭中断并等待中断处理完后返回, 而disable_irq_nosync立即返回. 那么在中断处理程序中应该使用哪一个函数来关闭中断呢?
在<linux设备驱动开发详解>中的按键驱动中, 使用disable_irq来关闭中断, 但是我在测试时进入中断后系统会死在中断处理程序, 而改为disable_irq_nosync则能正常退出中断处理程序.下面从内核代码来找一下原因:
先看一下disable_irq_nosync,内核代码中是这样解释的:
关闭中断后程序返回, 如果在中断处理程序中, 那么会继续将中断处理程序执行完.
关闭中断并等待中断处理完后返回.从代码中可以看到, disable_irq先是调用了disable_irq_nosync, 然后检测desc->action是否为1. 在中断处理程序中, action是置1的, 所以进入synchronize_irq函数中.
注释中说明该函数是在等待中断处理程序的结束, 这也是disable_irq与disable_irq_nosync不同的主要所在. 但是在中断处理函数中调用会发生什么情况呢? 进入中断处理函数前IRQ_INPROGRESS会被__setup_irq设置, 所以程序会一直陷在while循环中, 而此时内核以经被独占, 这就导致系统死掉.
总结:
由于在disable_irq中会调用synchronize_irq函数等待中断返回, 所以在中断处理程序中不能使用disable_irq, 否则会导致cpu被synchronize_irq独占而发生系统崩溃.
最近在三星的s5pv210芯片上调试intersil isl29028 light sensor驱动,驱动是在https://github.com/kernelzilla/android-kernel/blob/fe21dc28c3ccfdd0e1f059e3d896b1b989a7ea44/drivers/input/misc/isl29030.c找上,是motorola做的驱动,使用是在中断处理函数中,使用到了disable_irq函数来屏蔽中断,但每次对isl29028通过IIC总线设置其“配置寄存器”后,想再设置“中断寄存器”时就会卡住,后面发现是中断处理函数使用到disable_irq,而不是disable_irq_nosync函数造成的,但此时对于“配置寄存器”我设置的ALS和PROX功能都是对Enable位置为不使能的,但中断还是发来了,可是驱动是在系统启动过程加载的,此时很多中断CPU都不可能处理的,就出现了卡死现象,但isl29028又没有使能运行,不知道是不是light
sensor芯片的问题,先这样处理了。
对于disable_irq屏蔽中断是会等待CPU处理,对CPU是独占的方式,而disable_irq_nosync则是马上返回,不等待处理,故出现上面的情况。
在<linux设备驱动开发详解>中的按键驱动中, 使用disable_irq来关闭中断, 但是我在测试时进入中断后系统会死在中断处理程序, 而改为disable_irq_nosync则能正常退出中断处理程序.下面从内核代码来找一下原因:
先看一下disable_irq_nosync,内核代码中是这样解释的:
/** * disable_irq_nosync - disable an irq without waiting * @irq: Interrupt to disable * * Disable the selected interrupt line. Disables and Enables are * nested. * Unlike disable_irq(), this function does not ensure existing * instances of the IRQ handler have completed before returning. * * This function may be called from IRQ context. */ void disable_irq_nosync(unsigned int irq) { struct irq_desc *desc = irq_to_desc(irq); unsigned long flags; if (!desc) return; chip_bus_lock(irq, desc); spin_lock_irqsave(&desc->lock, flags); __disable_irq(desc, irq, false); spin_unlock_irqrestore(&desc->lock, flags); chip_bus_sync_unlock(irq, desc); } |
/** * disable_irq - disable an irq and wait for completion * @irq: Interrupt to disable * * Disable the selected interrupt line. Enables and Disables are * nested. * This function waits for any pending IRQ handlers for this interrupt * to complete before returning. If you use this function while * holding a resource the IRQ handler may need you will deadlock. * * This function may be called - with care - from IRQ context. */ void disable_irq(unsigned int irq) { struct irq_desc *desc = irq_desc + irq; if (irq >= NR_IRQS) return; disable_irq_nosync(irq); if (desc->action) synchronize_irq(irq); } |
/** * synchronize_irq - wait for pending IRQ handlers (on other CPUs) * @irq: interrupt number to wait for * * This function waits for any pending IRQ handlers for this interrupt * to complete before returning. If you use this function while * holding a resource the IRQ handler may need you will deadlock. * * This function may be called - with care - from IRQ context. */ void synchronize_irq(unsigned int irq) { struct irq_desc *desc = irq_to_desc(irq); unsigned int status; if (!desc) return; do { unsigned long flags; /* * Wait until we're out of the critical section. This might * give the wrong answer due to the lack of memory barriers. */ while (desc->status & IRQ_INPROGRESS) cpu_relax(); /* Ok, that indicated we're done: double-check carefully. */ spin_lock_irqsave(&desc->lock, flags); status = desc->status; spin_unlock_irqrestore(&desc->lock, flags); /* Oops, that failed? */ } while (status & IRQ_INPROGRESS); /* * We made sure that no hardirq handler is running. Now verify * that no threaded handlers are active. */ wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active)); } |
总结:
由于在disable_irq中会调用synchronize_irq函数等待中断返回, 所以在中断处理程序中不能使用disable_irq, 否则会导致cpu被synchronize_irq独占而发生系统崩溃.
最近在三星的s5pv210芯片上调试intersil isl29028 light sensor驱动,驱动是在https://github.com/kernelzilla/android-kernel/blob/fe21dc28c3ccfdd0e1f059e3d896b1b989a7ea44/drivers/input/misc/isl29030.c找上,是motorola做的驱动,使用是在中断处理函数中,使用到了disable_irq函数来屏蔽中断,但每次对isl29028通过IIC总线设置其“配置寄存器”后,想再设置“中断寄存器”时就会卡住,后面发现是中断处理函数使用到disable_irq,而不是disable_irq_nosync函数造成的,但此时对于“配置寄存器”我设置的ALS和PROX功能都是对Enable位置为不使能的,但中断还是发来了,可是驱动是在系统启动过程加载的,此时很多中断CPU都不可能处理的,就出现了卡死现象,但isl29028又没有使能运行,不知道是不是light
sensor芯片的问题,先这样处理了。
对于disable_irq屏蔽中断是会等待CPU处理,对CPU是独占的方式,而disable_irq_nosync则是马上返回,不等待处理,故出现上面的情况。
相关文章推荐
- 关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 关于中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 中断处理程序中的关中断函数disable_irq和disable_irq_nosync
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因【转】
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 【转】中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而用disable_irq_nosync原因
- 中断处理函数中不用disable_irq而…
- 中断处理函数中不用disable_irq而…