- 追加された行はこの色です。
- 削除された行はこの色です。
*参照元 [#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]