irq-gic-v3.c之set_handle_irq 分析

时间:2022-03-24 04:13:42
在gic_of_init的时候会调用 set_handle_irq(gic_handle_irq);来设置中断的回调函数
 45 void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
 46 {
 47         if (handle_arch_irq)
 48                 return;
 49 
 50         handle_arch_irq = handle_irq;
 51 }
code很简单就是把gic_handle_irq 赋给handle_arch_irq 。这样当中断发生是就会调用handle_arch_irq ,如下code所示.
arch/arm/kernel/entry-armv.S
 41         .macro  irq_handler
 42 #ifdef CONFIG_MULTI_IRQ_HANDLER
 43         ldr     r1, =handle_arch_irq
 44         mov     r0, sp
 45         badr    lr, 9997f
 46         ldr     pc, [r1]
 47 #else
 48         arch_irq_handler_default
 49 #endif


我们看看gic_handle_irq 具体做了什么。
asmlinkage 表示用堆栈来传递参数而不是用寄存器.
267 static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
268 {
269         u64 irqnr;
270 
271         do {
272                 irqnr = gic_read_iar();
273 
274                 if (likely(irqnr > 15 && irqnr < 1020)) {
275                         int err;
276                         err = handle_domain_irq(gic_data.domain, irqnr, regs);
277                         if (err) {
278                                 WARN_ONCE(true, "Unexpected SPI received!\n");
279                                 gic_write_eoir(irqnr);
280                         }
281                         continue;
282                 }
283                 if (irqnr < 16) {
284                         gic_write_eoir(irqnr);
285 #ifdef CONFIG_SMP
286                         handle_IPI(irqnr, regs);
287 #else
288                         WARN_ONCE(true, "Unexpected SGI received!\n");
289 #endif
290                         continue;
291                 }
292         } while (irqnr != ICC_IAR1_EL1_SPURIOUS);
293 }
这个函数做了两件事
272行读取发生中断的irq number.


如果irq number在15 到 1020之间,则调用handle_domain_irq 处理
irq number 如果小于15的话,则属于cpu之间的中断,而不是hw发送过来的中断,调用handle_ipi处理.
handle_domain_irq ->__handle_domain_irq ->generic_handle_irq->generic_handle_irq_desc
145 static inline void generic_handle_irq_desc(struct irq_desc *desc)
146 {
147         desc->handle_irq(desc);
148 }
但这个handle_irq 具体在哪里赋值的呢?
在初始的时候会调用gic_irq_domain_map
588 static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
589                               irq_hw_number_t hw)
590 {
591         /* SGIs are private to the core kernel */
592         if (hw < 16)
593                 return -EPERM;
594         /* PPIs */
595         if (hw < 32) {
596                 irq_set_percpu_devid(irq);
597                 irq_set_chip_and_handler(irq, &gic_chip,
598                                          handle_percpu_devid_irq);
599                 set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
600         }
601         /* SPIs */
602         if (hw >= 32 && hw < gic_data.irq_nr) {
603                 irq_set_chip_and_handler(irq, &gic_chip,
604                                          handle_fasteoi_irq);
605                 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
606         }
607         irq_set_chip_data(irq, d->host_data);
608         return 0;
609 }
我们看irq_set_chip_and_handler实现
526 static inline void irq_set_chip_and_handler(unsigned int irq, struct irq_chip *chip,
527                                             irq_flow_handler_t handle)
528 {
529         irq_set_chip_and_handler_name(irq, chip, handle, NULL);
530 }
继续往下
821 irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
822                               irq_flow_handler_t handle, const char *name)
823 {
824         irq_set_chip(irq, chip);
825         __irq_set_handler(irq, handle, 0, name);
826 }
继续往下
789 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
790                   const char *name)
791 {
792         unsigned long flags;
793         struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
794 
795         if (!desc)
796                 return;
797 
798         __irq_do_set_handler(desc, handle, is_chained, name);
799         irq_put_desc_busunlock(desc, flags);
800 }
继续往下,看到__irq_do_set_handler的776 行注册handle_irq,而此时的handle是在gic_irq_domain_map 中赋值的,如果irq number <32 ,则handle=handle_percpu_devid_irq,否则handle=handle_fasteoi_irq
733 void
734 __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
735                      int is_chained, const char *name)
736 {
776         desc->handle_irq = handle;
777         desc->name = name;
我们继续看看handle_fasteoi_irq的实现
 handle_fasteoi_irq-> handle_irq_event->handle_irq_event_percpu
handle_irq_event_percpu 的实现如下,145行看到调用handler了吧,
135 irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
136 {
137         irqreturn_t retval = IRQ_NONE;
138         unsigned int flags = 0, irq = desc->irq_data.irq;
139         struct irqaction *action;
140 
141         for_each_action_of_desc(desc, action) {
142                 irqreturn_t res;
143 
144                 trace_irq_handler_entry(irq, action);
145                 res = action->handler(irq, action->dev_id);
146                 trace_irq_handler_exit(irq, action, res);
147 
182 }
这个handler就是就用request_irq时候的第二个参数。
144 request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
145             const char *name, void *dev)
146 {
147         return request_threaded_irq(irq, handler, NULL, flags, name, dev);
148 }
哈哈终于调到自己注册的函数了