[color=rgba(0, 0, 0, 0.9)]machine_desc->init_irq() 完成对中断控制器的初始化,为每个irq_desc结构安装合适的流控handler,为每个irq_desc结构安装irq_chip指针,使他指向正确的中断控制器所对应的irq_chip结构的实例,同时,如果该平台中的中断线有多路复用(多个中断公用一个irq中断线)的情况,还应该初始化irq_desc中相应的字段和标志,以便实现中断控制器的级联。 [color=rgba(0, 0, 0, 0.9)]这里初始化的时候回调用到具体的芯片相关的中断初始化的地方。 [color=rgba(0, 0, 0, 0.9)]例如: int __init s5p_init_irq_eint(void)
{
int irq;
for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++)
irq_set_chip(irq, &s5p_irq_vic_eint);
for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) {
irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
}
irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
return 0;
}
[color=rgba(0, 0, 0, 0.9)]而在这些里面,都回去调用类似于: void
irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
irq_flow_handler_t handle, const char *name);
irq_set_handler(unsigned int irq, irq_flow_handler_t handle)
{
__irq_set_handler(irq, handle, 0, NULL);
}
static inline void
irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
{
__irq_set_handler(irq, handle, 1, NULL);
}
void
irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
void *data);
[color=rgba(0, 0, 0, 0.9)]这些函数定义在 include/linux/irq.h 文件。是对芯片初始化的时候可见的 APIs,用于指定中断“流控”中的 : [color=rgba(0, 0, 0, 0.9)]irq_flow_handler_t handle [color=rgba(0, 0, 0, 0.9)]也就是中断来的时候,最后那个函数调用。 [color=rgba(0, 0, 0, 0.9)]中断流控函数,分几种,电平触发的中断,边沿触发的,等: /*
* Built-in IRQ handlers for various IRQ types,
* callable via desc->handle_irq()
*/
extern void handle_level_irq(struct irq_desc *desc);
extern void handle_fasteoi_irq(struct irq_desc *desc);
extern void handle_edge_irq(struct irq_desc *desc);
extern void handle_edge_eoi_irq(struct irq_desc *desc);
extern void handle_simple_irq(struct irq_desc *desc);
extern void handle_untracked_irq(struct irq_desc *desc);
extern void handle_percpu_irq(struct irq_desc *desc);
extern void handle_percpu_devid_irq(struct irq_desc *desc);
extern void handle_bad_irq(struct irq_desc *desc);
extern void handle_nested_irq(unsigned int irq);
[color=rgba(0, 0, 0, 0.9)]而在这些处理函数里,会去调用到 :handle_irq_event [color=rgba(0, 0, 0, 0.9)]比如: /**
* handle_level_irq - Level type irq handler
* @desc: the interrupt description structure for this irq
*
* Level type interrupts are active as long as the hardware line has
* the active level. This may require to mask the interrupt and unmask
* it after the associated handler has acknowledged the device, so the
* interrupt line is back to inactive.
*/
void handle_level_irq(struct irq_desc *desc)
{
raw_spin_lock(&desc->lock);
mask_ack_irq(desc);
if (!irq_may_run(desc))
goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
/*
* If its disabled or no action available
* keep it masked and get out of here
*/
if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
desc->istate |= IRQS_PENDING;
goto out_unlock;
}
kstat_incr_irqs_this_cpu(desc);
handle_irq_event(desc);
cond_unmask_irq(desc);
out_unlock:
raw_spin_unlock(&desc->lock);
}
[color=rgba(0, 0, 0, 0.9)]而这个 handle_irq_event 则是调用了处理,handle_irq_event_percpu: irqreturn_t handle_irq_event(struct irq_desc *desc)
{
irqreturn_t ret;
desc->istate &= ~IRQS_PENDING;
irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
raw_spin_unlock(&desc->lock);
ret = handle_irq_event_percpu(desc);
raw_spin_lock(&desc->lock);
irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
return ret;
}
[color=rgba(0, 0, 0, 0.9)]handle_irq_event_percpu->__handle_irq_event_percpu-> 【action->handler()】 [color=rgba(0, 0, 0, 0.9)]这里终于看到了调用 的地方了,就是咱们通过 request_irq 注册进去的函数 7. /proc/interrupts [color=rgba(0, 0, 0, 0.9)]这个 proc 下放置了对应中断号的中断次数和对应的 dev-name。 文章来源于网络,版权归原作者所有,如有侵权,请联系删除。
|