Atheros AR9344中断处理流程

事由: 当我写irq chip的驱动的时候,我发现irq alloc descs这个函数可以不用,我就很奇怪,如果不分配空间创建irqdesc,哪接下来的irq set chip 以及irq set chip data等函数向哪里填充数据。
我继续查看irq set chip等函数,kernel/kernel/irq
struct irq_desc *desc=irq_get_desc_lock(irq,&flags)//通过irq来查找desc
desc->irq_Data.chip=chip;

那么这个desc肯定是有什么地方创建了

initIRQ->machine_descinit_irq->rkxx_init_irq->gic_init->gic_dist_init->

early_irq_init-> early_irq_init通过arch_probe_nr_irqs获得NR_IRQS,然后分配irq descs

首先站在系统的最高层来看看,系统中申请了那些中断。

/proc# cat interrupts

          CPU0      

 2:             dummy_cctv  wifi0

 3:       537           MIPS  ehci_hcd:usb1

 4:       534           MIPS  eth0

 6:                   MIPS  cascade_cctv

 7:     27152           MIPS  timer

 18:          ath_misc_cctv_suiyuan cascade_cctv

 19:      1189  ath_misc_cctv_suiyuan serial

 64:           ath_pci_cctv  wifi1

第一列显示的是中断号,

第二列显示的是中断的次数,

第三列为:此中断对应的structirq_chip结构中的name,因为每一个irq于一个特定的structirq_chip相联系。

第四列为:申请此中断时的名称。

重要的一个数据结构,硬件中断描述符。

struct irq_chip {

      const char   *name;

      unsignedint      (*startup)(unsigned int irq);

      void             (*shutdown)(unsigned int irq);

      void             (*enable)(unsigned int irq);

      void             (*disable)(unsigned int irq);

 

      void             (*ack)(unsigned int irq);

      void             (*mask)(unsigned int irq);

      void             (*mask_ack)(unsigned int irq);

      void             (*unmask)(unsigned int irq);

      void             (*eoi)(unsigned int irq);

 

      void             (*end)(unsigned int irq);

      int         (*set_affinity)(unsigned int irq,

                                  const struct cpumask *dest);

      int         (*retrigger)(unsigned int irq);

      int         (*set_type)(unsigned int irq, unsigned int flow_type);

      int         (*set_wake)(unsigned int irq, unsigned int on);

 

      

#ifdefCONFIG_IRQ_RELEASE_METHOD

      void             (*release)(unsigned int irq, void *dev_id);

#endif

      

      const char   *typename;

};

 

Handle.c(z:\wlan\src\linux\kernels\mips-linux-2.6.31\kernel\irq)   

Irq.c(z:\wlan\src\linux\kernels\mips-linux-2.6.31\arch\mips\kernel)     

 

asmlinkage void __initstart_kernel(void)

{

early_irq_init();

init_IRQ();//用来初始化中断相关的代码。

}

struct irq_desc irq_desc[NR_IRQS]__cacheline_aligned_in_smp = {

      [0 ... NR_IRQS-1] = {

             .status = IRQ_DISABLED,

             .chip = &no_irq_chip,

             .handle_irq = handle_bad_irq,

             .depth = 1,

             .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),

      }

};

static unsigned intkstat_irqs_all[NR_IRQS][NR_CPUS];

int __initearly_irq_init(void)

{

      struct irq_desc *desc;

      int count;

      int i;

      init_irq_default_affinity();

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

      desc = irq_desc;

      count = ARRAY_SIZE(irq_desc);

      for (i = 0; i < count; i++) {

             desc[i].irq = i;

             alloc_desc_masks(&desc[i], 0, true);

             init_desc_masks(&desc[i]);

             desc[i].kstat_irqs = kstat_irqs_all[i];

      }

      return arch_early_irq_init();

}

 

void __initinit_IRQ(void)

{

      int i;

#ifdef CONFIG_KGDB

      if (kgdb_early_setup)

             return;

#endif

      for (i = 0; i < NR_IRQS; i++){

             set_irq_noprobe(i);

      }

      printk("cctv: %s: line:%d\n", __FUNCTION__,__LINE__);

      arch_init_irq();

 

#ifdef CONFIG_KGDB

      if (!kgdb_early_setup)

             kgdb_early_setup = 1;

#endif

}

 

Irq.c(z:\wlan\src\linux\kernels\mips-linux-2.6.31\arch\mips\atheros)

void__init arch_init_irq(void) //主要对AR9344平台的中断进行初始化。

{

      

      printk("cctv: %s: line:%d\n", __FUNCTION__,__LINE__);

      mips_cpu_irq_init();

      ath_misc_irq_init(ATH_MISC_IRQ_BASE);

      ath_gpio_irq_init(ATH_GPIO_IRQ_BASE);

#ifdef CONFIG_PCI

      ath_pci_irq_init(ATH_PCI_IRQ_BASE);

#endif

      

      setup_irq(ATH_CPU_IRQ_MISC, &cascade);

      setup_irq(ATH_MISC_IRQ_GPIO, &cascade);

 

#ifdef CONFIG_PCI

      setup_irq(ATH_CPU_IRQ_PCI, &cascade);

#endif

      ath_arch_init_irq();

      set_c0_status(ST0_IM);

}

//先看看下面这个函数:给特定的中断号建立起一个特定的中断处理函数

Void set_irq_chip_and_handler(unsignedint irq, struct irq_chip *chip,

                     irq_flow_handler_t handle)

{//下面这俩个函数主要就是对irq对应的structirq_desc的成员进行赋值。

      set_irq_chip(irq, chip);

      __set_irq_handler(irq, handle, 0, NULL);

}

//下面这个函数是将一个特定的中断号于数据结构structirq_chip建立其联系,我们可以从函数的俩个参数看出来。

int set_irq_chip(unsigned int irq,struct irq_chip *chip)

{

      struct irq_desc *desc =irq_to_desc(irq);//根据irq号,取出irq_desc

      unsigned long flags;

      if (!desc) {

             WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n",irq);

             return -EINVAL;

      }

      if (!chip)

             chip = &no_irq_chip;

      spin_lock_irqsave(&desc->lock, flags);

      irq_chip_set_defaults(chip);

      desc->chip = chip; //将参数赋值给特定中断对应的chip。

      spin_unlock_irqrestore(&desc->lock, flags);

      return 0;

}

voidirq_chip_set_defaults(struct irq_chip *chip)

{//给struct irq_chip结构成员赋初始值。

      if(!chip->enable)

             chip->enable = default_enable;

      if (!chip->disable)

             chip->disable = default_disable;

      if (!chip->startup)

             chip->startup = default_startup;

      

      if (!chip->shutdown)

             chip->shutdown = chip->disable != default_disable?

                    chip->disable : default_shutdown;

      if (!chip->name)

             chip->name = chip->typename;

      if (!chip->end)

             chip->end = dummy_irq_chip.end;

}

#defineATH_CPU_IRQ_BASE        0x00

#defineATH_MISC_IRQ_BASE             0x10

#defineATH_GPIO_IRQ_BASE             0x20

#defineATH_MISC_IRQ_COUNT          14

下面的函数主要也就是对特定的中断号关联特定的handler。

static void ath_misc_irq_init(intirq_base)

{

      int i;

      for (i = irq_base; i < irq_base + ATH_MISC_IRQ_COUNT; i++){

             irq_desc[i].status = IRQ_DISABLED;

             irq_desc[i].action = NULL;

             irq_desc[i].depth = 1;

             set_irq_chip_and_handler(i,&ath_misc_irq_controller,

                                   handle_percpu_irq);

      }

}

int setup_irq(unsigned int irq,struct irqaction *act)

{

      struct irq_desc *desc = irq_to_desc(irq);

      return __setup_irq(irq, desc, act);

}

///

下面来看看驱动中对注册到系统的中断是如何申请和处理的。

static inline int__must_check

request_irq(unsigned int irq,irq_handler_t handler, unsigned long flags,

          const char*name, void *dev)

{//中断申请函数。

      return request_threaded_irq(irq, handler, NULL, flags, name,dev);

}

ret =request_irq(ATH_GPIO_IRQn(BUTTON_GPIO), ar9344buttons_interrupt,0,"ar9344 button", NULL);

 

 

函数中的主要完成的事情为:   

desc= irq_to_desc(irq);和retval =__setup_irq(irq, desc, action);

int request_threaded_irq(unsignedint irq, irq_handler_t handler,

                     irq_handler_t thread_fn, unsigned longirqflags,

                     const char *devname, void *dev_id){

      struct irqaction *action;

      struct irq_desc *desc;

      int retval;

      desc = irq_to_desc(irq);

      if (!desc)

             return -EINVAL;

      if (desc->status & IRQ_NOREQUEST)

             return -EINVAL;

      if (!handler)

             return -EINVAL;

      action = kzalloc(sizeof(structirqaction), GFP_KERNEL);

      if (!action)

             return -ENOMEM;

      action->handler = handler;

      action->thread_fn = thread_fn;

      action->flags = irqflags;

      action->name = devname;

      action->dev_id = dev_id;

      retval = __setup_irq(irq, desc, action);

}

原文:http://blog.csdn.net/suiyuan19840208/article/details/7654265
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值