前面学习了一下linux中断子系统的中断处理过程,看到中断最终由
desc->handle_irq(irq, desc)处理。linux系统最早调用与中断相关的函数是early_trap_init(),他主要工作是把我们定义好的中断向量表拷贝到CPU的中断地址。然后linux调用early_irq_init()初始化linux中断系统的核心数据,下面我们就从中断模型的核心数据开始来继续学习linux的中断系统。
linux中断机制的核心数据结构 irq_desc, 它完整地描述了一条中断线 (或称为 “中断通道” )。其中irq_desc 结构在 include/linux/irqdesc.h 中定义:
struct irq_desc {
struct irq_data irq_data;
unsigned int __percpu *kstat_irqs;
irq_flow_handler_t handle_irq;/* 高层次的中断事件处理函数 */
#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
irq_preflow_handler_t preflow_handler;
#endif
struct irqaction *action; /* 行为链表IRQ action list */
unsigned int status_use_accessors;
unsigned int core_internal_state__do_not_mess_with_it;
unsigned int depth; /* 关中断次数nested irq disables */
unsigned int wake_depth; /* 唤醒次数nested wake enables */
unsigned int irq_count; /* 发生的中断次数For detecting broken IRQs */
unsigned long last_unhandled; /* 滞留时间Aging timer for unhandled count */
unsigned int irqs_unhandled;
raw_spinlock_t lock;/*自旋锁*/
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_t pending_mask;
#endif
#endif
unsigned long threads_oneshot;
atomic_t threads_active;
wait_queue_head_t wait_for_threads;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *dir;
#endif
struct module *owner;
const char *name;
} ____cacheline_internodealigned_in_smp;
其中irq_data 结构在 include/linux/irq.h 中定义:
struct irq_data {
unsigned int irq;
unsigned long hwirq;
unsigned int node;
unsigned int state_use_accessors;
struct irq_chip *chip; /* 低层次的硬件操作 */
struct irq_domain *domain;
void *handler_data;/* chip 方法使用的数据*/
void *chip_data; /* chip 私有数据 */
struct msi_desc *msi_desc;
cpumask_var_t affinity;
};
其中irq_desc 结构在 include/linux/irqdesc.