linux kernel 工程师
全部博文(99)
分类: LINUX
2014-02-08 14:45:42
irq的注册分为两个层次,
1. __irq_set_handler
2. request_irq (通常我们接触的层次是request_irq, 是因为系统启动时bsp已经通过__irq_set_handler把每一个中断的desc->handle_irq设置好了)
struct irq_desc {
struct irq_data irq_data;
unsigned int __percpu *kstat_irqs;
irq_flow_handler_t handle_irq; /* __irq_set_handler安装的是这个函数 */
#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
irq_preflow_handler_t preflow_handler;
#endif
struct irqaction *action; /* IRQ action list */ /* request_irq安装的是action->handler以及action->thread_fn */
unsigned int status_use_accessors;
.....
} ____cacheline_internodealigned_in_smp;
-------------------------华丽的分割线----------------------------------------
在early_irq_init函数里会有一个对desc的简单初始化。
/* 在CONFIG_SPARSE_IRQ 没有配置的情况下, irq_desc实际上就是个数组,
如果使能了CONFIG_SPARSE_IRQ, irq_desc就会使用radix tree, 情况稍微复杂些,
为简单起见,这里以CONFIG_SPARSE_IRQ 没有配置的情况,对irq_desc有一个粗略印象 */
struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
[0 ... NR_IRQS-1] = {
.handle_irq = handle_bad_irq,
.depth = 1,
.lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
}
};
int __init early_irq_init(void)
{
int count, i, node = first_online_node;
struct irq_desc *desc;
init_irq_default_affinity();
printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
desc = irq_desc;
count = ARRAY_SIZE(irq_desc);
for (i = 0; i < count; i++) {
desc[i].kstat_irqs = alloc_percpu(unsigned int);
alloc_masks(&desc[i], GFP_KERNEL, node);
raw_spin_lock_init(&desc[i].lock);
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
desc_set_defaults(i, &desc[i], node, NULL);
}
return arch_early_irq_init();
}
struct irq_desc *irq_to_desc(unsigned int irq)
{
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
}
EXPORT_SYMBOL_GPL(irq_to_desc);