Linux中断导读之一–注册部分3

前面介绍了中断的初始化代码,稍带着执行流程也过的差不多了

这里看下我们经常碰到的中断的注册,看看和前面是怎么关联起来的,

也就是request_irq函数;

相关阅读:

Linux中断导读之一–初始化<1>

Linux中断导读之一–初始化<2>

Linux中断导读之一–处理流程<4>

#include/linux/interrupt.h中,

static inline int __must_checkrequest_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);}

参数为中断号,中断处理函数,,标志,

#在kernel/irq/manage.c中,

/*** request_threaded_irq – allocate an interrupt line* @irq: Interrupt line to allocate* @handler: Function to be called when the IRQ occurs.* Primary handler for threaded interrupts* If NULL and thread_fn != NULL the default* primary handler is installed* @thread_fn: Function called from the irq handler thread* If NULL, no irq thread is created* @irqflags: Interrupt type flags* @devname: An ascii name for the claiming device* @dev_id: A cookie passed back to the handler function** This call allocates interrupt resources and enables the* interrupt line and IRQ handling. From the point this* call is made your handler function may be invoked. Since* your handler function must clear any interrupt the board* raises, you must take care both to initialise your hardware* and to set up the interrupt handler in the right order.** If you want to set up a threaded irq handler for your device* then you need to supply @handler and @thread_fn. @handler ist* still called in hard interrupt context and has to check* whether the interrupt originates from the device. If yes it* needs to disable the interrupt on the device and return* IRQ_WAKE_THREAD which will wake up the handler thread and run* @thread_fn. This split handler design is necessary to support* shared interrupts.** Dev_id must be globally unique. Normally the address of the* device data structure is used as the cookie. Since the handler* receives this value it makes sense to use it.** If your interrupt is shared you must pass a non NULL dev_id* as this is required when freeing the interrupt.** Flags:** IRQF_SHARED Interrupt is shared* IRQF_SAMPLE_RANDOM The interrupt can be used for entropy* IRQF_TRIGGER_* Specify active edge(s) or level**/int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, const char *devname, void *dev_id){ struct irqaction *action; struct irq_desc *desc; int retval; /* * Sanity-check: shared interrupts must pass in a real dev-ID, * otherwise we’ll have trouble later trying to figure out * which interrupt is which (messes up the interrupt freeing * logic etc). */ if ((irqflags & IRQF_SHARED) && !dev_id) //如果是shared那么需要dev_id用于区分 return -EINVAL; desc = irq_to_desc(irq); //得到描述结构 if (!desc) return -EINVAL; if (!irq_settings_can_request(desc) || WARN_ON(irq_settings_is_per_cpu_devid(desc))) return -EINVAL; if (!handler) { if (!thread_fn) return -EINVAL; handler = irq_default_primary_handler; } action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); //分配一个action结构 if (!action) return -ENOMEM; action->handler = handler; action->thread_fn = thread_fn; action->flags = irqflags; action->name = devname; action->dev_id = dev_id; chip_bus_lock(desc); retval = __setup_irq(irq, desc, action); //******** chip_bus_sync_unlock(desc); if (retval) kfree(action);#ifdef CONFIG_DEBUG_SHIRQ_FIXME if (!retval && (irqflags & IRQF_SHARED)) { /* * It’s a shared IRQ — the driver ought to be prepared for it * to happen immediately, so let’s make sure…. * We disable the irq to make sure that a ‘real’ IRQ doesn’t * run in parallel with our fake. */ unsigned long flags; disable_irq(irq); local_irq_save(flags); handler(irq, dev_id); local_irq_restore(flags); enable_irq(irq); }#endif return retval;}EXPORT_SYMBOL(request_threaded_irq);

当眼泪流尽的时候,留下的应该是坚强。

Linux中断导读之一–注册部分3

相关文章:

你感兴趣的文章:

标签云: