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 不能被申请)