Linux字符设备驱动--No.2

分析中断注册函数:request_irq

 1 int butsOpen(struct inode *p, struct file *f)
 2 {
 3     
 4         int irq;
 5     int i;
 6     int err = 0;
 7     printk(KERN_EMERG"butsOpen\r\n");
 8     for (i = 0; i < ARRAY_SIZE(buttons); i++) {
 9         if (!buttons[i].gpio)
10             continue;
11 
12         irq = gpio_to_irq(buttons[i].gpio);
13         err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, 
14                 buttons[i].name, (void *)&buttons[i]);
15         if (err)
16             break;
17     }
18 
19     if (err) {
20         i--;
21         for (; i >= 0; i--) {
22             if (!buttons[i].gpio)
23                 continue;
24 
25             irq = gpio_to_irq(buttons[i].gpio);
26             disable_irq(irq);
27             free_irq(irq, (void *)&buttons[i]);
28         }
29 
30         return -EBUSY;
31     }
32     return 0;
33 }
1 request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
2         const char *name, void *dev)
3 {
4     return request_threaded_irq(irq, handler, NULL, flags, name, dev);
5 }
  1 /**
  2  *    request_threaded_irq - 分配中断线路函数
  3  *    @irq: Interrupt line to allocate
  4  *    @handler: Function to be called when the IRQ occurs.
  5  *          Primary handler for threaded interrupts
  6  *          If NULL and thread_fn != NULL the default
  7  *          primary handler is installed
  8  *    @thread_fn: Function called from the irq handler thread
  9  *            If NULL, no irq thread is created
 10  *    @irqflags: Interrupt type flags
 11  *    @devname: An ascii name for the claiming device
 12  *    @dev_id: A cookie passed back to the handler function//作为hanler的一个参数
 13  *
 14  *    This call allocates interrupt resources and enables the
 15  *    interrupt line and IRQ handling. From the point this
 16  *    call is made your handler function may be invoked. Since
 17  *    your handler function must clear any interrupt the board
 18  *    raises, you must take care both to initialise your hardware
 19  *    and to set up the interrupt handler in the right order.
 20  *
 21  *    If you want to set up a threaded irq handler for your device
 22  *    then you need to supply @handler and @thread_fn. @handler ist
 23  *    still called in hard interrupt context and has to check
 24  *    whether the interrupt originates from the device. If yes it
 25  *    needs to disable the interrupt on the device and return
 26  *    IRQ_WAKE_THREAD which will wake up the handler thread and run
 27  *    @thread_fn. This split handler design is necessary to support
 28  *    shared interrupts.
 29  *
 30  *    Dev_id must be globally unique. Normally the address of the
 31  *    device data structure is used as the cookie. Since the handler
 32  *    receives this value it makes sense to use it.
 33  *
 34  *    If your interrupt is shared you must pass a non NULL dev_id
 35  *    as this is required when freeing the interrupt.
 36  *
 37  *    Flags:
 38  *
 39  *    IRQF_SHARED        Interrupt is shared
 40  *    IRQF_SAMPLE_RANDOM    The interrupt can be used for entropy
 41  *    IRQF_TRIGGER_*        Specify active edge(s) or level
 42  *
 43  */ 
 1 struct irqaction {
 2     irq_handler_t handler;
 3     unsigned long flags;
 4     void *dev_id;
 5     struct irqaction *next;
 6     int irq;
 7     irq_handler_t thread_fn;
 8     struct task_struct *thread;
 9     unsigned long thread_flags;
10     unsigned long thread_mask;
11     const char *name;
12     struct proc_dir_entry *dir;
13 } ____cacheline_internodealigned_in_smp;
struct irqaction
 1 /**
 2  * struct irq_desc - interrupt descriptor
 3  * @irq_data:        per irq and chip data passed down to chip functions
 4  * @timer_rand_state:    pointer to timer rand state struct
 5  * @kstat_irqs:        irq stats per cpu
 6  * @handle_irq:        highlevel irq-events handler
 7  * @preflow_handler:    handler called before the flow handler (currently used by sparc)
 8  * @action:        the irq action chain
 9  * @status:        status information
10  * @core_internal_state__do_not_mess_with_it: core internal status information
11  * @depth:        disable-depth, for nested irq_disable() calls
12  * @wake_depth:        enable depth, for multiple irq_set_irq_wake() callers
13  * @irq_count:        stats field to detect stalled irqs
14  * @last_unhandled:    aging timer for unhandled count
15  * @irqs_unhandled:    stats field for spurious unhandled interrupts
16  * @lock:        locking for SMP
17  * @affinity_hint:    hint to user space for preferred irq affinity
18  * @affinity_notify:    context for notification of affinity changes
19  * @pending_mask:    pending rebalanced interrupts
20  * @threads_oneshot:    bitfield to handle shared oneshot threads
21  * @threads_active:    number of irqaction threads currently running
22  * @wait_for_threads:    wait queue for sync_irq to wait for threaded handlers
23  * @dir:        /proc/irq/ procfs entry
24  * @name:        flow handler name for /proc/interrupts output
25  */
26 struct irq_desc {
27     struct irq_data        irq_data;
28     struct timer_rand_state *timer_rand_state;
29     unsigned int __percpu    *kstat_irqs;
30     irq_flow_handler_t    handle_irq;
31 #ifdef CONFIG_IRQ_PREFLOW_FASTEOI
32     irq_preflow_handler_t    preflow_handler;
33 #endif
34     struct irqaction    *action;    /* IRQ action list */
35     unsigned int        status_use_accessors;
36     unsigned int        core_internal_state__do_not_mess_with_it;
37     unsigned int        depth;        /* nested irq disables */
38     unsigned int        wake_depth;    /* nested wake enables */
39     unsigned int        irq_count;    /* For detecting broken IRQs */
40     unsigned long        last_unhandled;    /* Aging timer for unhandled count */
41     unsigned int        irqs_unhandled;
42     raw_spinlock_t        lock;
43 #ifdef CONFIG_SMP
44     const struct cpumask    *affinity_hint;
45     struct irq_affinity_notify *affinity_notify;
46 #ifdef CONFIG_GENERIC_PENDING_IRQ
47     cpumask_var_t        pending_mask;
48 #endif
49 #endif
50     unsigned long        threads_oneshot;
51     atomic_t        threads_active;
52     wait_queue_head_t       wait_for_threads;
53 #ifdef CONFIG_PROC_FS
54     struct proc_dir_entry    *dir;
55 #endif
56     const char        *name;
57 } ____cacheline_internodealigned_in_smp;
struct irq_desc
 44 int request_threaded_irq(unsigned int irq, irq_handler_t handler,
 45              irq_handler_t thread_fn, unsigned long irqflags,
 46              const char *devname, void *dev_id)
 47 {
 48     struct irqaction *action;
 49     struct irq_desc *desc;
 50     int retval;
 51 
 52     /*
 53      * Sanity-check: shared interrupts must pass in a real dev-ID,
 54      * otherwise we'll have trouble later trying to figure out
 55      * which interrupt is which (messes up the interrupt freeing
 56      * logic etc).
 57      */
 58     if ((irqflags & IRQF_SHARED) && !dev_id)//若终端标志是共享中断,则设备号dev_id不允许为空
 59         return -EINVAL;
 60 
 61     desc = irq_to_desc(irq);
 62     if (!desc)
 63         return -EINVAL;
 64 
 65     if (!irq_settings_can_request(desc))
 66         return -EINVAL;
 67 
 68     if (!handler) {
 69         if (!thread_fn)
 70             return -EINVAL;
 71         handler = irq_default_primary_handler;
 72     }
 73 
 74     action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
 75     if (!action)
 76         return -ENOMEM;
 77 
 78     action->handler = handler;
 79     action->thread_fn = thread_fn;
 80     action->flags = irqflags;
 81     action->name = devname;
 82     action->dev_id = dev_id;
 83 
 84     chip_bus_lock(desc);
 85     retval = __setup_irq(irq, desc, action);
 86     chip_bus_sync_unlock(desc);
 87 
 88     if (retval)
 89         kfree(action);
 90 
 91 #ifdef CONFIG_DEBUG_SHIRQ_FIXME
 92     if (!retval && (irqflags & IRQF_SHARED)) {
 93         /*
 94          * It's a shared IRQ -- the driver ought to be prepared for it
 95          * to happen immediately, so let's make sure....
 96          * We disable the irq to make sure that a 'real' IRQ doesn't
 97          * run in parallel with our fake.
 98          */
 99         unsigned long flags;
100 
101         disable_irq(irq);
102         local_irq_save(flags);
103 
104         handler(irq, dev_id);
105 
106         local_irq_restore(flags);
107         enable_irq(irq);
108     }
109 #endif
110     return retval;
111 }
1 #define irq_to_desc(irq)    (&irq_desc[irq])

猜你喜欢

转载自www.cnblogs.com/embeded-linux/p/10692775.html
今日推荐