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函数