kernel/irq/irqdesc.c: early_trap_init
arch/arm/kernel/irq.c: init_IRQ
// 非稀疏irq
int __init early_irq_init(void)
{
int count, i, node = first_online_node;
struct irq_desc *desc;
/* 初始化 irq_default_affinity 变量, 此变量用于设置中断默认的 CPU 亲和力 */
init_irq_default_affinity();
printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
/* 指向中断描述符数组 irq_desc */
desc = irq_desc;
/* 获取中断描述符数组长度 */
count = ARRAY_SIZE(irq_desc);
for (i = 0; i < count; i++) {
/* 为 kstat_irqs 分配内存, 每个 CPU 有自己独有的 kstat_irqs 数据, 此数据用于统计 */
desc[i].kstat_irqs = alloc_percpu(unsigned int);
/* 为 desc->irq_data.affinity 和 desc->pending_mask 分配内存 */
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();
}
/* 描述符初始化 */
static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
struct module *owner)
{
int cpu;
/* 中断号 */
desc->irq_data.irq = irq;
/* 中断描述符的中断控制器芯片为 no_irq_chip */
desc->irq_data.chip = &no_irq_chip;
/* 中断控制器的私有数据为空 */
desc->irq_data.chip_data = NULL;
desc->irq_data.handler_data = NULL;
desc->irq_data.msi_desc = NULL;
/* 设置中断状态 desc->status_use_accessors 为初始化状态_IRQ_DEFAULT_INIT_FLAGS */
irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
/* 中断默认被禁止, 设置 desc->irq_data->state_use_accessors = IRQD_IRQ_DISABLED */
irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
/* 设置中断处理回调函数为 handle_bad_irq, handle_bad_irq 作为默认的回调函数, 此函数中基本上不做什么处理, 就是在屏幕上打印此中断信息, 并且 desc->kstat_irqs++ */
desc->handle_irq = handle_bad_irq;
/* 嵌套深度为 1, 表示被禁止 1 次 */
desc->depth = 1;
/* 初始化此中断发送次数为 0 */
desc->irq_count = 0;
/* 无法处理的中断次数为 0 */
desc->irqs_unhandled = 0;
/* 在/proc/interrupts 所显名字为空 */
desc->name = NULL;
/* owner 为空 */
desc->owner = owner;
/* 初始化 kstat_irqs 中每个 CPU 项都为 0 */
for_each_possible_cpu(cpu)
*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
/* SMP 系统才使用的初始化, 设置
* desc->irq_data.node = first_online_node
* desc->irq_data.affinity = irq_default_affinity
* 清除 desc->pending_mask
*/
desc_smp_init(desc, node);
}
static const struct irq_domain_ops x86_vector_domain_ops = {
.select = x86_vector_select,
.alloc = x86_vector_alloc_irqs,
.free = x86_vector_free_irqs,
.activate = x86_vector_activate,
.deactivate = x86_vector_deactivate,
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
.debug_show = x86_vector_debug_show,
#endif
};
//根据x86_vector_domain_ops 初始化domain_ops
int __init arch_early_irq_init(void)
{
struct fwnode_handle *fn;
fn = irq_domain_alloc_named_fwnode("VECTOR");
BUG_ON(!fn);
x86_vector_domain = irq_domain_create_tree(fn, &x86_vector_domain_ops,
NULL);
BUG_ON(x86_vector_domain == NULL);
irq_set_default_host(x86_vector_domain);
BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL));
/*
* Allocate the vector matrix allocator data structure and limit the
* search area.
*/
vector_matrix = irq_alloc_matrix(NR_VECTORS, FIRST_EXTERNAL_VECTOR,
FIRST_SYSTEM_VECTOR);
BUG_ON(!vector_matrix);
return arch_early_ioapic_init();
}