下面我们看一看irq_desc的部分定义:
struct irq_data { unsigned intirq; unsigned longhwirq; unsigned intnode; unsigned intstate_use_accessors; struct irq_chip*chip; struct irq_domain*domain; void*handler_data; void*chip_data; struct msi_desc*msi_desc; #ifdef CONFIG_SMP cpumask_var_taffinity; #endif }; struct irq_desc { struct irq_datairq_data; unsigned int __percpu*kstat_irqs; irq_flow_handler_thandle_irq; #ifdef CONFIG_IRQ_PREFLOW_FASTEOI irq_preflow_handler_tpreflow_handler; #endif struct irqaction*action;/* IRQ action list */ unsigned intstatus_use_accessors; unsigned intdepth;/* nested irq disables */ unsigned intwake_depth;/* nested wake enables */ unsigned intirq_count;/* For detecting broken IRQs */ raw_spinlock_tlock; struct cpumask*percpu_enabled; #ifdef CONFIG_SMP const struct cpumask*affinity_hint; struct irq_affinity_notify *affinity_notify; #ifdef CONFIG_GENERIC_PENDING_IRQ cpumask_var_tpending_mask; #endif #endif wait_queue_head_t wait_for_threads; const char*name; } ____cacheline_internodealigned_in_smp;对于irq_desc中的主要字段做一个解释:irq_data 这个内嵌结构在2.6.37版本引入,之前的内核版本的做法是直接把这个结构中的字段直接放置在irq_desc结构体中,然后在调用硬件封装层的chip->xxx()回调中传入IRQ编号作为参数,但是底层的函数经常需要访问->handler_data,->chip_data,->msi_desc等字段,这需要利用irq_to_desc(irq)来获得irq_desc结构的指针,然后才能访问上述字段,者带来了性能的降低,尤其在配置为sparse irq的系统中更是如此,因为这意味着基数树的搜索操作。为了解决这一问题,内核开发者把几个低层函数需要使用的字段单独封装为一个结构,调用时的参数则改为传入该结构的指针。实现同样的目的,那为什么不直接传入irq_desc结构指针?因为这会破坏层次的封装性,我们不希望低层代码可以看到不应该看到的部分,仅此而已。
kstat_irqs 用于irq的一些统计信息,这些统计信息可以从proc文件系统中查询。
action 中断响应链表,当一个irq被触发时,内核会遍历该链表,调用action结构中的回调handler或者激活其中的中断线程,之所以实现为一个链表,是为了实现中断的共享,多个设备共享同一个irq,这在设备中是普遍存在的。
status_use_accessors记录该irq的状态信息,内核提供了一系列irq_settings_xxx的辅助函数访问该字段,详细请查看kernel/irq/settings.h
depth 用于管理enable_irq()/disable_irq()这两个API的嵌套深度管理,每次enable_irq时该减去1,每次disable_irq时该加1,只有depth==0时才真正向硬件封装层发出关闭irq的调用,只有depth==1时才会向硬件封装层发出打开irq的调用。disable的嵌套次数可以比enable的次数多,此时depth的大于1,随着enable的不断调用,当depth的为1时,在向硬件封装层发出打开irq的调用后,depth减去1后,此时depth为0,此时处于一个平衡状态,我们只能调用disable_irq,如果此时enable_irq被调用,内核会报告一个irq失衡的警告,提醒驱动程序的开发人员检查自己的代码。
lock 用于保护irq_desc结构本身的自旋锁。
affinity_hit 用于提示用户空间,作为优化irq和cpu之间的亲缘关系的依据。
pending_mask 用于调整irq在各个cpu之间的平衡。
wait_for_threads 用于synchronize_irq(),等待该irq所有线程完成。
irq_data结构中的各字段:
irq 该结构所对应的IRQ编号。
hwirq 硬件irq编号,它不同于上面的irq;
node 通常用于hwirq和irq之间的映射操作;
state_use_accessors 硬件封装层需要使用的状态信息,不要直接访问该字段,内核定义了一组函数用于访问该字段:irqd_xxxx(),参见include/linux/irq.h。
chip 指向该irq所属的中断控制器的irq_chip结构指针
handler_data 每个irq的私有数据指针,该字段由硬件封转层使用,例如用作底层硬件的多路复用中断。
chip_data 中断控制器的私有数据,该字段由硬件封转层使用。
msi_desc 用于PCIe总线的MSI或MSI-X中断机制。
affinity 记录该irq与cpu之间的亲缘关系,它其实是一个bit-mask,每一个bit代表一个cpu,置位后代表该cpu可能处理该irq。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-5465-3.html
明天我就叫几个兄弟去你家提亲