Linux 中断学习之小试牛刀篇(10)

6>.dev_id: 对应于request_irq()函数中所传递的第五个参数,可取任意值,但必须唯一能够代表发出中断请求的设备,通常取描述该设备的结构体。 共享中断时所用。

现在继续迭代深入 request_threaded_irq()内部是如何实现的。

1049int request_threaded_irq(unsigned int irq, irq_handler_t handler,  
1050                         irq_handler_t thread_fn, unsigned long irqflags,  
1051                         const char *devname, void *dev_id)  
1052{  
1053        struct irqaction *action;  
1054        struct irq_desc *desc;  
1055        int retval;  
1056  
1057        /* 
1058         * Sanity-check: shared interrupts must pass in a real dev-ID, 
1059         * otherwise we'll have trouble later trying to figure out 
1060         * which interrupt is which (messes up the interrupt freeing 
1061         * logic etc). 
1062         */ 
1063        if ((irqflags & IRQF_SHARED) && !dev_id)  
1064                return -EINVAL;  
1065  
1066        desc = irq_to_desc(irq);  
1067        if (!desc)  
1068                return -EINVAL;  
1069  
1070        if (desc->status & IRQ_NOREQUEST)  
1071                return -EINVAL;  
1072  
1073        if (!handler) {  
1074                if (!thread_fn)  
1075                        return -EINVAL;  
1076                handler = irq_default_primary_handler;  
1077        }  
1078  
1079        action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);  
1080        if (!action)  
1081                return -ENOMEM;  
1082  
1083        action->handler = handler;  
1084        action->thread_fn = thread_fn;  
1085        action->flags = irqflags;  
1086        action->name = devname;  
1087        action->dev_id = dev_id;  
1088  
1089        chip_bus_lock(irq, desc);  
1090        retval = __setup_irq(irq, desc, action);  
1091        chip_bus_sync_unlock(irq, desc);  
1092  
1093        if (retval)  
1094                kfree(action);  
1095  
1096#ifdef CONFIG_DEBUG_SHIRQ  
1097        if (!retval && (irqflags & IRQF_SHARED)) {  
1098                /* 
1099                 * It's a shared IRQ -- the driver ought to be prepared for it 
1100                 * to happen immediately, so let's make sure.... 
1101                 * We disable the irq to make sure that a 'real' IRQ doesn't 
1102                 * run in parallel with our fake. 
1103                 */ 
1104                unsigned long flags;  
1105  
1106                disable_irq(irq);  
1107                local_irq_save(flags);  
1108  
1109                handler(irq, dev_id);  
1110  
1111                local_irq_restore(flags);  
1112                enable_irq(irq);  
1113        }  
1114#endif  
1115        return retval;  
1116} 
1049int request_threaded_irq(unsigned int irq, irq_handler_t handler,
1050                         irq_handler_t thread_fn, unsigned long irqflags,
1051                         const char *devname, void *dev_id)
1052{
1053        struct irqaction *action;
1054        struct irq_desc *desc;
1055        int retval;
1056
1057        /*
1058         * Sanity-check: shared interrupts must pass in a real dev-ID,
1059         * otherwise we'll have trouble later trying to figure out
1060         * which interrupt is which (messes up the interrupt freeing
1061         * logic etc).
1062         */
1063        if ((irqflags & IRQF_SHARED) && !dev_id)
1064                return -EINVAL;
1065
1066        desc = irq_to_desc(irq);
1067        if (!desc)
1068                return -EINVAL;
1069
1070        if (desc->status & IRQ_NOREQUEST)
1071                return -EINVAL;
1072
1073        if (!handler) {
1074                if (!thread_fn)
1075                        return -EINVAL;
1076                handler = irq_default_primary_handler;
1077        }
1078
1079        action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
1080        if (!action)
1081                return -ENOMEM;
1082
1083        action->handler = handler;
1084        action->thread_fn = thread_fn;
1085        action->flags = irqflags;
1086        action->name = devname;
1087        action->dev_id = dev_id;
1088
1089        chip_bus_lock(irq, desc);
1090        retval = __setup_irq(irq, desc, action);
1091        chip_bus_sync_unlock(irq, desc);
1092
1093        if (retval)
1094                kfree(action);
1095
1096#ifdef CONFIG_DEBUG_SHIRQ
1097        if (!retval && (irqflags & IRQF_SHARED)) {
1098                /*
1099                 * It's a shared IRQ -- the driver ought to be prepared for it
1100                 * to happen immediately, so let's make sure....
1101                 * We disable the irq to make sure that a 'real' IRQ doesn't
1102                 * run in parallel with our fake.
1103                 */
1104                unsigned long flags;
1105
1106                disable_irq(irq);
1107                local_irq_save(flags);
1108
1109                handler(irq, dev_id);
1110
1111                local_irq_restore(flags);
1112                enable_irq(irq);
1113        }
1114#endif
1115        return retval;
1116}

程序的第一行和第二行分别定义了:

(1) struct irqaction *action;

(2)2struct irq_desc *desc;

两个指针action和desc,它们分别指向了结构体irqaction和 irq_desc。

(3)    if ((irqflags & IRQF_SHARED) && !dev_id)
              return -EINVAL;

作用是:判断中断标志位,如果是共享中断的话就必须要有一个唯一的dev_id,否则返回一个错误。

(4)      desc = irq_to_desc(irq);

irq_to_desc(irq):根据中断号irq在 irq_desc[NR_IRQS]数组中 返回一个具体的irq_desc。即根据irq找到它的中断处理程序。

(5)    if (!desc)

return -EINVAL;

当返回一个空值时返回一个错误。说明申请中断号失败。

(6)if (desc->status & IRQ_NOREQUEST)
               return -EINVAL;

判断中断线的状态,若为IRQ_NOREQUEST时( IRQ_NOREQUEST表示 IRQ 不能被申请)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwszfw.html