*参照元 [#eacb05be] *参照元 [#q62dac76] #backlinks *説明 [#x2e8d7ab] -[[linux-2.6.33/request_irq()]] を見てください。 *説明 [#v672a222] -パス: [[linux-2.6.33/kernel/irq/manage.c]] -FIXME: これは何? --説明 *コメント [#r0ce7163] **引数 [#g21f2dad] -unsigned int irq -- -irq_handler_t handler -- -irq_handler_t thread_fn -- -unsigned long irqflags -- -const char *devname -- -void *dev_id -- **返り値 [#e22af99e] -int -- **参考 [#kc4cfa75] *実装 [#s2912c53] /** * 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_DISABLED Disable local interrupts while processing * 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; - --[[linux-2.6.33/irqaction]] struct irq_desc *desc; - --[[linux-2.6.33/irq_desc]] int retval; /* * handle_IRQ_event() always ignores IRQF_DISABLED except for * the _first_ irqaction (sigh). That can cause oopsing, but * the behavior is classified as "will not fix" so we need to * start nudging drivers away from using that idiom. */ if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) == (IRQF_SHARED|IRQF_DISABLED)) { pr_warning( "IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs\n", irq, devname); } - --[[linux-2.6.33/pr_warning()]] #ifdef CONFIG_LOCKDEP /* * Lockdep wants atomic interrupt handlers: */ irqflags |= IRQF_DISABLED; #endif /* * 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) return -EINVAL; desc = irq_to_desc(irq); if (!desc) return -EINVAL; - --[[linux-2.6.33/irq_to_desc()]] if (desc->status & IRQ_NOREQUEST) return -EINVAL; if (!handler) { if (!thread_fn) return -EINVAL; handler = irq_default_primary_handler; } - --[[linux-2.6.33/irq_default_primary_handler()]] action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; - --[[linux-2.6.33/kzalloc()]] action->handler = handler; action->thread_fn = thread_fn; action->flags = irqflags; action->name = devname; action->dev_id = dev_id; chip_bus_lock(irq, desc); - --[[linux-2.6.33/chip_bus_lock()]] retval = __setup_irq(irq, desc, action); - --[[linux-2.6.33/__setup_irq()]] chip_bus_sync_unlock(irq, desc); - --[[linux-2.6.33/chip_bus_sync_unlock()]] if (retval) kfree(action); - --[[linux-2.6.33/kfree()]] #ifdef CONFIG_DEBUG_SHIRQ 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); - --[[linux-2.6.33/disable_irq()]] --[[linux-2.6.33/local_irq_save()]] handler(irq, dev_id); local_irq_restore(flags); enable_irq(irq); - --[[linux-2.6.33/local_irq_restore()]] --[[linux-2.6.33/enable_irq()]] } #endif return retval; } EXPORT_SYMBOL(request_threaded_irq); - --[[linux-2.6.33/EXPORT_SYMBOL()]] *コメント [#l70c6c83]