Kernel 中断子系统(六):GPIO中断处理流程

    科技2026-01-18  14

    kernel version:4.9.186 software platform:Qualcomm android 10

    本文以一个GPIO中断源发生了中断为例分析一个GPIO中断处理流程。 中断会通过中断控制器级联关系逐层向上“汇报”,最终被某个processor响应。假设中断已经被某个processor响应。

    我们从GIC中断控制器的gic_handle_irq函数开始分析

    gic_handle_irq() handle_domain_irq() __handle_domain_irq() generic_handle_irq() generic_handle_irq_desc() desc->handle_irq(desc) // msm_gpio_irq_handler

    在GPIO中断控制的分析中得知desc->handle_irq在msm_gpio_init过程中被设置为msm_gpio_irq_handler函数

    static void msm_gpio_irq_handler(struct irq_desc *desc) { struct gpio_chip *gc = irq_desc_get_handler_data(desc); const struct msm_pingroup *g; struct msm_pinctrl *pctrl = gpiochip_get_data(gc); struct irq_chip *chip = irq_desc_get_chip(desc); int irq_pin; int handled = 0; u32 val; int i; chained_irq_enter(chip, desc); /* * Each pin has it's own IRQ status register, so use * enabled_irq bitmap to limit the number of reads. */ for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) { g = &pctrl->soc->groups[i]; val = readl(pctrl->regs + g->intr_status_reg);//读取gpio相关控制确定具体发生中断的gpio源 if (val & BIT(g->intr_status_bit)) { irq_pin = irq_find_mapping(gc->irqdomain, i); //查找gpio中断控制的irq_domain, //取出对应的virq generic_handle_irq(irq_pin);//继续执行中断处理流程 handled++; } } /* No interrupts were flagged */ if (handled == 0) handle_bad_irq(desc); chained_irq_exit(chip, desc); } generic_handle_irq() generic_handle_irq_desc() desc->handle_irq(desc);

    在gpio中断控制的domain->ops-alloc函数,即msm_gpio_domain_alloc函数中,desc->handle_irq被设置为handle_fasteoi_irq

    handle_fasteoi_irq() handle_irq_event() handle_irq_event_percpu() __handle_irq_event_percpu() res = action->handler(irq, action->dev_id); //执行action->handler函数 __irq_wake_thread(desc, action); //唤醒相关的中断线程,执行中断下半部处理

    中断下半部线程被调度执行

    irq_thread() irq_thread_fn() ret = action->thread_fn(action->irq, action->dev_id);//执行action->thread_fn函数
    Processed: 0.031, SQL: 9