对中断的理解handle_level_irq【原创】

内容预览:

     如下为本人原创,在解决问题的过程中的一点心得,如果有描述不准确的地方还请各位指出,非常感谢

    Linux内核版本:linux-4.9.18

    曾有一次调试触摸屏的时候遇到如下的问题

    /startup/modules #
    
    [
    233.370296] irq 44: nobody cared (try booting with the "irqpoll" option)
    [
    233.376983] CPU: 0 PID: 0 Comm: swapper Tainted: G O 4.9.18 #8
    [
    233.383912] Hardware name: Broadcom Cygnus SoC
    [
    233.388378] [<c010cbfc>] (unwind_backtrace) from [<c010a5fc>] (show_stack+0x10/0x14)
    [
    233.396103] [<c010a5fc>] (show_stack) from [<c0145d38>] (__report_bad_irq+0x24/0xa4)
    [
    233.403821]
    [
    <c0145d38>] (__report_bad_irq) from [<c0145fdc>] (note_interrupt+0x1c8/0x274)
    [
    233.412052]
    [
    <c0145fdc>] (note_interrupt) from [<c014400c>] (handle_irq_event_percpu+0x44/0x50)
    [
    233.420715]
    [
    <c014400c>] (handle_irq_event_percpu) from [<c0144040>] (handle_irq_event+0x28/0x3c)
    [
    233.429550]
    [
    <c0144040>] (handle_irq_event) from [<c0146574>] (handle_simple_irq+0x70/0x78)
    [
    233.437868]
    [
    <c0146574>] (handle_simple_irq) from [<c01438d8>] (generic_handle_irq+0x18/0x28)
    [
    233.446366]
    [
    <c01438d8>] (generic_handle_irq) from [<c02adb3c>] (iproc_gpio_irq_handler+0xd0/0x11c)
    [
    233.455376]
    [
    <c02adb3c>] (iproc_gpio_irq_handler) from [<c01438d8>] (generic_handle_irq+0x18/0x28)
    [
    233.464297]
    [
    <c01438d8>] (generic_handle_irq) from [<c0143980>] (__handle_domain_irq+0x80/0xa4)
    [
    233.472959]
    [
    <c0143980>] (__handle_domain_irq) from [<c01013d0>] (gic_handle_irq+0x50/0x84)
    [
    233.481275] [<c01013d0>] (gic_handle_irq) from [<c010b02c>] (__irq_svc+0x6c/0x90)
    [
    233.488723] Exception stack(0xc0901f60 to 0xc0901fa8)
    [
    233.493754] 1f60: c0112900 c0717028 c0901fb8 00000000 c093af4c 00000000 00000335 c0826220
    [
    233.501896] 1f80: 00000001 414fc091 df9eab80 00000000 c0900038 c0901fb0 c010843c c0108440
    [
    233.510034] 1fa0: 60000013 ffffffff
    [
    233.513514] [<c010b02c>] (__irq_svc) from [<c0108440>] (arch_cpu_idle+0x2c/0x38)
    [
    233.520887] [<c0108440>] (arch_cpu_idle) from [<c013a6ec>] (cpu_startup_entry+0x50/0xc0)
    [
    233.528956] [<c013a6ec>] (cpu_startup_entry) from [<c0800d70>] (start_kernel+0x414/0x4b0)
    [
    233.537097] handlers:
    [
    233.539363]
    [
    <c014408c>] irq_default_primary_handler threaded [<bf03ff68>] synaptics_rmi4_irq [synaptics_dsx]
    [
    233.549300] Disabling IRQ #44

    首先我们顺着错误跟踪linux内核来看下

    kernel/irq/spurious.c

    因此有提示的log信息可以看出,是走的else的分支,bad_action_ret(action_ret)返回为0

    通过此函数的dump_stack的信息,可以追溯到调用者

     

    drivers/pinctrl/bcm/pinctrl-iproc-gpio.c

     

     

    kernel/irq/chip.c

    handle_level_irq

    ===> handle_irq_event  (kernel/irq/handle.c)

    ===> handle_irq_event_percpu   (kernel/irq/handle.c)

    ===>__handle_irq_event_percpu  (kernel/irq/handle.c)

     

    根据log,我们可以在下图看到note_interrupt,即说明noirqdebug=0

    Kernel/irq/handle.c

     

    因为上面我们已经分析过bad_action_ret(action_ret)返回为0

    因此在note_interrupt函数里面只会从如下分支进去

    Kernel/irq/spurious.c

    从上图可以看出,如果想出现那样的错误,必须满足条件

    desc->irqs_unhandled > 99900 为真

    如要要满足如上条件的话,那么只有如下地方会让irqs_unhandled++

    Kernel/irq/spurious.c

    通过上图,我们可以看到,必须满足条件:

    action_ret == IRQ_NONE为真

    再继续看回如下图,action_ret就是retval

     

    res即为action_ret

    而 action->handler的回调函数是

    request_threaded_irq线程化注册中断的第2个参数

     

    kernel/irq/manage.c

    因为handler为NULL,所以handler = irq_default_primary_handler

     

    action_ret = IRQ_WAKE_THREAD

    Kernel/irq/spurious.c

     

    经过如上图,我们可以发现action_ret = IRQ_NONE

     

    那么我们接下来看看到底是怎么被调用到这里的,一个中断的产生又是怎样的?

    首先handle_level_irq这个函数是在这里注册到kernel中的

    drivers/pinctrl/bcm/pinctrl-iproc-gpio.c

    static int iproc_gpio_probe(struct platform_device *pdev)

    ===> gpiochip_irqchip_add

    Include/linux/gpio/driver.h

    typedef    void (*irq_flow_handler_t)(struct irq_desc *desc);

    这里即gpiochip->irq_handler = handle_level_irq

    struct irqaction *action

     

    一个中断开始的时候

    arch/arm/kernel/entry-armv.S

    这里有一个全局的handle_arch_irq

     

    这个全局的handle_arch_irq会在如下地方被赋值

    arch/arm/kernel/setup.c

    void __init setup_arch(char **cmdline_p)

    ===> handle_arch_irq被赋值

    那么接下来我们就要找到mdesc->handle_irq又是在哪里被赋值了呢?

     

    drivers/irqchip/irq-gic.c

    这里有这样的函数set_handle_irq

     

    接下来我们看下这个函数的实现就知道了

    arch/arm/kernel/irq.c

     

    那么这个set_handle_irq又是在哪里被调用的呢?

    针对内核版本Linux-4.9.18

    drivers/irqchip/irq-gic.c

    gic_of_init

    ===>__gic_init_bases

    ===>set_handle_irq

    Include/linux/irqchip.h

    Include/linux/of.h

     

    Include/linux/of.h

    因此我们得出一个结论:

    handle_arch_irq = gic_handle_irq

    一个中断开始后,从entry-armv.S中进入

     

    handle_domain_irq

    ===> __handle_domain_irq

    ===>generic_handle_irq

    ===>generic_handle_irq_desc

     

    这里的desc->handle_irq 其实就是handle_level_irq

    这里是如何转换过去的呢?

    drivers/pinctrl/bcm/pinctrl-iproc-gpio.c

    gpiochip_set_chained_irqchip

    ===> irq_set_chained_handler_and_data

    ===> __irq_do_set_handler

    Kernel/irq/chip.c

     

    Kernel/irq/manage.c

    Irq_thread

     

    这个函数的作用是检查是否有中断嵌套

     

     

     

     

    参考:

    http://www.wowotech.net/irq_subsystem/request_threaded_irq.html

    http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html

    https://blog.csdn.net/tiantao2012/article/details/78062621

    https://blog.csdn.net/tiantao2012/article/details/78094691

    https://blog.csdn.net/zhao2272062978/article/details/70599978

    https://blog.csdn.net/droidphone/article/details/7467436

    https://blog.csdn.net/droidphone/article/details/7445825

    https://blog.csdn.net/droidphone/article/category/1118447

    https://blog.csdn.net/phenix_lord/article/details/45116259

    https://blog.csdn.net/phenix_lord/article/details/45116595

    https://blog.csdn.net/phenix_lord/article/details/45116689

     

    以上就是:对中断的理解handle_level_irq【原创】 的全部内容。

    本站部分内容来源于互联网和用户投稿,如有侵权请联系我们删除,谢谢。
    Email:[email protected]


    0 条回复 A 作者 M 管理员
      所有的伟大,都源于一个勇敢的开始!
    欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论