Linux内核中断相关的数据结构 (三)

中断相关的数据结构

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。每一个中断又对应着一个或者多个中断处理函数。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值