本文简介
- 这里列举了 与 irq_of_parse_and_map 类似的几个函数
- 以 irq-gic-v3.c 为例 ,本篇主要是讲 irq_of_parse_and_map 和 request_irq
irq_of_parse_and_map
hierarchy
irq_of_parse_and_map
of_irq_parse_one // 将 interrupt 属性填充到这里
irq_create_of_mapping
of_phandle_args_to_fwspec // 将 interrupt 属性填充到 fwspec
irq_create_fwspec_mapping
irq_find_matching_fwspec
// 处理已经映射的问题
irq_domain_translate(domain, fwspec, &hwirq, &type) // 将 fwspec 转换 到 hwirq
domain->ops->translate
virq = irq_find_mapping(domain, hwirq)
if (virq) // 如果已经映射,则 。。。
// 处理还未映射的问题
virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);/__irq_domain_alloc_irqs
// 1. irq & descs
virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node,affinity);
__irq_alloc_descs
bitmap_find_next_zero_area
alloc_descs->alloc_desc->desc_set_defaults
desc->irq_data.irq = irq;
// 2. delwith parent_data in irq_data TODO
// Documentation/core-api/irq/irq-domain.rst Line 233
irq_domain_alloc_irq_data(domain, virq, nr_irqs)
irq_data->domain = domain;
irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg);
domain->ops->alloc/gic_irq_domain_alloc
domain->ops->translate 获取硬件中断号
gic_irq_domain_map
irq_domain_set_info
irq_domain_set_hwirq_and_chip
// 3. map
// 因为 irq_domain_alloc_irqs 不可以将 hwirq 作为参数,所以只能在 alloc 中填充 hwirq
// 为什么这么设计?
// 大概率是中断控制器的参数越来越多了???
// 很有可能是 具体irq相关代码(alloc) 需要 interrupts 属性所有的信息来做一些动作.
// 即使传了hwirq,还是要做一次translate来获取其所有信息.
irq_data->hwirq = hwirq;
// 4. chip
irq_data->chip = chip ? chip : &no_irq_chip;
// 6. chip data
irq_data->chip_data = chip_data;
// gicv3 驱动 使用了 host_data : private data pointer for use by owner
// 它把 struct gic_chip_data 作为了 host_data
__irq_set_handler/__irq_do_set_handler
// 5.handle
desc->handle_irq = handle;
irq_set_handler_data(virq, handler_data);
desc->irq_common_data.handler_data = data;
// per irq and chip data passed down to chip functions
// 好像是用来判定是不是 a cascading interrupt
// 对于这个gic_irq_domain_alloc 实例来说 为 NULL
// 7. irq status
irq_set_probe(irq);
// 更新 desc.status_use_accessors
// 表示 Interrupt can be probed by autoprobing : 可以 该 irq 已经被 设置好了
irqd_set_single_target(irqd);
// 更新 desc.irq_data->common.state_use_accessors
// 表示 IRQ allows only a single affinity target
irq_data = irq_get_irq_data(virq);
if (!irq_data) irq_domain_free_irqs(virq, 1);
irq_domain_free_irqs_hierarchy
domain->ops->free
irqd_set_trigger_type(irq_data, type);
// 更新 desc.irq_data->common.state_use_accessors
// 表示设置 trigger type
request_irq
hierarchy
request_irq
request_threaded_irq
__setup_irq
irq_activate
irq_domain_activate_irq
__irq_domain_activate_irq
domain->ops->activate
gicv3 的 irq_domain_ops 实现
static const struct irq_domain_ops gic_irq_domain_ops = {
.translate = gic_irq_domain_translate,
.alloc = gic_irq_domain_alloc,
.free = gic_irq_domain_free,
.select = gic_irq_domain_select,
};