硬中断--初始化

liaocj 2024-12-03 09:02:56
Categories: Tags:

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();
}