Chinaunix首页 | 论坛 | 博客
  • 博客访问: 419804
  • 博文数量: 99
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 1012
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-20 16:30
个人简介

linux kernel 工程师

文章分类

全部博文(99)

文章存档

2018年(5)

2017年(12)

2016年(27)

2015年(10)

2014年(43)

2012年(2)

我的朋友

分类: LINUX

2014-02-08 14:45:42

irq的注册分为两个层次,
1. __irq_set_handler

2. request_irq  (通常我们接触的层次是request_irq, 是因为系统启动时bsp已经通过__irq_set_handler把每一个中断的desc->handle_irq设置好了)

 

struct irq_desc {
 struct irq_data  irq_data;
 unsigned int __percpu *kstat_irqs;
 irq_flow_handler_t handle_irq;               /*  __irq_set_handler安装的是这个函数  */           
#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
 irq_preflow_handler_t preflow_handler;
#endif
 struct irqaction *action; /* IRQ action list */  /*  request_irq安装的是action->handler以及action->thread_fn */
 unsigned int  status_use_accessors;
.....
 } ____cacheline_internodealigned_in_smp;


-------------------------华丽的分割线----------------------------------------

在early_irq_init函数里会有一个对desc的简单初始化。


/* 在CONFIG_SPARSE_IRQ 没有配置的情况下, irq_desc实际上就是个数组,
    如果使能了CONFIG_SPARSE_IRQ, irq_desc就会使用radix tree, 情况稍微复杂些,
   为简单起见,这里以CONFIG_SPARSE_IRQ 没有配置的情况,对irq_desc有一个粗略印象 */

struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
 [0 ... NR_IRQS-1] = {
  .handle_irq = handle_bad_irq,
  .depth  = 1,
  .lock  = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
 }
};

int __init early_irq_init(void)
{
 int count, i, node = first_online_node;
 struct irq_desc *desc;

 init_irq_default_affinity();

 printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);

 desc = irq_desc;
 count = ARRAY_SIZE(irq_desc);

 for (i = 0; i < count; i++) {
  desc[i].kstat_irqs = alloc_percpu(unsigned int);
  alloc_masks(&desc[i], GFP_KERNEL, node);
  raw_spin_lock_init(&desc[i].lock);
  lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
  desc_set_defaults(i, &desc[i], node, NULL);
 }
 return arch_early_irq_init();
}

struct irq_desc *irq_to_desc(unsigned int irq)
{
 return (irq < NR_IRQS) ? irq_desc + irq : NULL;
}
EXPORT_SYMBOL_GPL(irq_to_desc);

阅读(989) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~