中断相关的数据结构
1. irq_desc
struct irq_desc {
structirq_data irq_data;
struct timer_rand_state*timer_rand_state;
unsigned int __percpu *kstat_irqs;
irq_flow_handler_t handle_irq;
#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
irq_preflow_handler_t preflow_handler;
#endif
structirqaction *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;
#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
const char *name;
}____cacheline_internodealigned_in_smp;
1) 这个数据结构是整个中断子系统里最主要的结构体,其中用红色标注的是重要的几个域。irq_data是包含每个irq和irq chip数据传递给irq_chip相关的函数,将在后面进行介绍。
2) handle_irq是体系结构的特定的函数指针,其类型为typedef void (*irq_flow_handler_t)(unsigned intirq,struct irq_desc *desc)。该函数负责使用chip中提供的特定于中断控制器的方法,进行处理中断所必需的一些底层操作。在ARM的GIC的的初始化函数gic_dist_init中通过irq_set_chip_and_handler(i,&gic_chip, handle_fasteoi_irq)语句设置为handle_fasteoi_irq。
3) action是一个链表,对应于共享中断所有的中断处理函数。
4) status_use_accessors是一个状态变量,用来指定中断一些特性。具体的取值有如下
/*
* Bit masks forirq_data.state
*
* IRQD_TRIGGER_MASK - Mask for the trigger type bits
* IRQD_SETAFFINITY_PENDING - Affinity setting is pending
* IRQD_NO_BALANCING - Balancing disabled for this IRQ
* IRQD_PER_CPU - Interrupt is per cpu
* IRQD_AFFINITY_SET - Interrupt affinity was set
* IRQD_LEVEL - Interrupt is level triggered
* IRQD_WAKEUP_STATE - Interrupt is configured for wakeup
* from suspend
* IRDQ_MOVE_PCNTXT - Interrupt can be moved in process
* context
* IRQD_IRQ_DISABLED - Disabled state of the interrupt
* IRQD_IRQ_MASKED - Masked state of the interrupt
* IRQD_IRQ_INPROGRESS - In progress state of theinterrupt
*/
enum {
IRQD_TRIGGER_MASK = 0xf,
IRQD_SETAFFINITY_PENDING = (1 << 8),
IRQD_NO_BALANCING = (1 << 10),
IRQD_PER_CPU = (1 << 11),
IRQD_AFFINITY_SET = (1 << 12),
IRQD_LEVEL = (1 << 13),
IRQD_WAKEUP_STATE = (1 << 14),
IRQD_MOVE_PCNTXT = (1 << 15),
IRQD_IRQ_DISABLED = (1 << 16),
IRQD_IRQ_MASKED = (1 << 17),
IRQD_IRQ_INPROGRESS = (1 << 18),
};
2. irq_data
/**
*struct irq_data - per irq and irq chip data passed down to chip functions
* @irq: interrupt number
* @node: node index useful for balancing
* @state_use_accessors:status information for irq chip functions.
* Use accessor functions to deal with it
* @chip: low level interrupt hardwareaccess
* @handler_data: per-IRQ data for the irq_chip methods
* @chip_data: platform-specific per-chip privatedata for the chip
* methods, to allow shared chip implementations
* @msi_desc: MSI descriptor
* @affinity: IRQ affinity on SMP
*
* The fields here need tooverlay the ones in irq_desc until we
* cleaned up the directreferences and switched everything over to
* irq_data.
*/
struct irq_data {
unsigned int irq;
unsigned int node;
unsigned int state_use_accessors;
structirq_chip *chip;
void *handler_data;//在哪里被使用????
void *chip_data;
struct msi_desc *msi_desc;
#ifdef CONFIG_SMP
cpumask_var_t affinity;
#endif
};
1) chip_data在gic_dist_init函数中通过irq_set_chip_data(i, gic)这个语句设置chip_data指向struct gic_chip_data结构变量,这个变量保存这个gic的地址信息及SPI中断的起始中断号。
2) chip是指向特定中断控制器的函数的指针,struct irq_chip将在下面进行介绍。
3. irq_chip
/**
* struct irq_chip - hardwareinterrupt chip descriptor
* @irq_mask: maskan interrupt source
* @irq_unmask: unmaskan interrupt source
* @irq_eoi: end of interrupt
*@irq_set_affinity: set the CPUaffinity on SMP machines
*@irq_retrigger: resend an IRQ to the CPU
*/
struct irq_chip {
const char *name;
void (*irq_mask)(struct irq_data *data);
void (*irq_unmask)(struct irq_data *data);
void (*irq_eoi)(struct irq_data *data);
int (*irq_set_affinity)(struct irq_data *data, const structcpumask *dest, bool force);
int (*irq_retrigger)(struct irq_data *data);
int (*irq_set_type)(struct irq_data *data, unsigned intflow_type);
…… …… …… …..
};
该结构是对IRQ控制器抽象,用于体系结构无关的代码。在实际使用时,通常不需要实现的函数。在这里定义的函数都是用于操作硬件IRQ控制器,函数的具体的实现是和体系结构紧密相关的,在ARM平台下该结构定义在gic.c。
4. irqaction
/**
* struct irqaction - perinterrupt action descriptor
* @handler: interrupt handler function
* @flags: flags (see IRQF_* above)
* @name: name of thedevice
* @dev_id: cookie to identify the device
* @next: pointer to the next irqaction for sharedinterrupts
* @irq: interrupt number
* @dir: pointer to the proc/irq/NN/name entry
* @thread_fn: interrupt handler function for threadedinterrupts
* @thread: thread pointer for threaded interrupts
* @thread_flags: flags related to @thread
* @thread_mask: bitmask for keeping track of @thread activity
*/
struct irqaction {
irq_handler_thandler;
unsignedlong flags;
void*dev_id;
structirqaction *next;
int irq;
irq_handler_t thread_fn;
struct task_struct *thread;
unsigned long thread_flags;
unsigned long thread_mask;
const char *name;
struct proc_dir_entry *dir;
}____cacheline_internodealigned_in_smp;
该结构与中断处理函数一一对应,但一个irq_desc结构可以对应多个irqaction(共享中断就是这种情况)。
1) handler,该结构对应的中断处理函数。
2) flags对应的中断标志位。
3) dev_id在共享中断中,唯一的标识一个中断。一般指向需要传递给中断处理函数的数据。
4) irq中断号。
上面的四个数据结构是Linux中断子系统的核心,下图是这几个数据结构的关系。
一个irq_chip对应于整个系统中的所有irq_desc,每个irq_desc对应一个或者多个irqaction结构。系统中的irq_chip管理者整个系统的所有中断,这些中断被抽象成为irq_desc。每一个中断又对应着一个或者多个中断处理函数。