简介
irq_desc数据结构用于描述一个irq对应的各种信息,主要有以下方面:
irq_data,描述该irq的irq number,irq chip,irq domain,处理器亲和力等等
handle_irq,highlevel irq-events handler,流处理函数
irq_action,一个链表,每个成员包含该irq中断处理函数等信息
depth,中断嵌套深度
name,cat /proc/interrupts时显示的名称
等等
每个irq对应一个irq_desc,kernel中管理irq_descs有两种方式:
1、如果定义 CONFIG_SPARSE_IRQ,则所有irq_descs以radix tree的形式管理
2、否则所有irq_descs放在一个全局数组中,并对某些成员进行初始化,如下
260 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
261 [0 ... NR_IRQS-1] = {
262 .handle_irq = handle_bad_irq,
263 .depth = 1,
264 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
265 }
266 };
系统启动时初始化irq_descs
1、early_irq_init
1.1 Radix tree形式
只对系统的16个legacy中断进行irq_desc的初始化
229 int __init early_irq_init(void)
230 {
231 int i, initcnt, node = first_online_node;
232 struct irq_desc *desc;
233
234 init_irq_default_affinity(); //默认的中断亲和力是所有CPU,如果想绑定cpu到某个cpu上该怎么做?http://blog.youkuaiyun.com/kingmax26/article/details/5788732
235
236 /* Let arch update nr_irqs and return the nr of preallocated irqs */
237 initcnt = arch_probe_nr_irqs(); //不同架构的preallocated irq数目不同,x86是16
~ 238 printk(KERN_ERR "yin_test NR_IRQS:%d nr_irqs:%d initcnt %d\n",
+ 239 NR_IRQS, nr_irqs, initcnt);
240
241 if (WARN_ON(nr_irqs > IRQ_BITMAP_BITS))
242 nr_irqs = IRQ_BITMAP_BITS;
243
244 if (WARN_ON(initcnt > IRQ_BITMAP_BITS))
245 initcnt = IRQ_BITMAP_BITS;
246
247 if (initcnt > nr_irqs)
248 nr_irqs = initcnt;
249
250 for (i = 0; i < initcnt; i++) { //对以上的16个irq进行irq_desc的初始化
251 desc = alloc_desc(i, node, NULL); //分配irq_desc并对其中某些成员进行初始化
252 set_bit(i, allocated_irqs); //set bit in allocated_irqs
253 irq_insert_desc(i, desc); //插入到radix tree中
254 }
255 return arch_early_irq_init(); //设置以上16个legacy irq的chip_data,void类型
256 }
1.2 全局数组
260 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
261 [0 ... NR_IRQS-1] = {
262 .handle_irq = handle_bad_irq,
263 .depth = 1,
264 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
265 }
266 };
267
268 int __init early_irq_init(void)
269 {
270 int count, i, node = first_online_node;
271 struct irq_desc *desc;
272
273 init_irq_default_affinity();
274
~ 275 printk(KERN_INFO "NR_IRQS:%d, adasda\n", NR_IRQS);
+ 276 13131
277
278 desc = irq_desc;
279 count = ARRAY_SIZE(irq_desc);
280
281 for (i = 0; i < count; i++) { //遍历数组,对成员进行初始化
282 desc[i].kstat_irqs = alloc_percpu(unsigned int);
283 alloc_masks(&desc[i], GFP_KERNEL, node);
284 raw_spin_lock_init(&desc[i].lock);
285 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
286 desc_set_defaults(i, &desc[i], node, NULL);
287 }
288 return arch_early_irq_init();
289 }
可以看到,这种方法就比较简单粗暴了,直接静态定义,然后依次对数组元素初始化。
2.init_IRQ
init_IRQ不仅对IDT进行初始化,也对irq_desc进行了初始化
85 void __init init_IRQ(void)
86 {
87 int i;
88
89 /*
90 * We probably need a better place for this, but it works for
91 * now ...
92 */