Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / kernel / irq / autoprobe.c
1 /*
2  * linux/kernel/irq/autoprobe.c
3  *
4  * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
5  *
6  * This file contains the interrupt probing code and driver APIs.
7  */
8
9 #include <linux/irq.h>
10 #include <linux/module.h>
11 #include <linux/interrupt.h>
12 #include <linux/delay.h>
13 #include <linux/async.h>
14
15 #include "internals.h"
16
17 /*
18  * Autodetection depends on the fact that any interrupt that
19  * comes in on to an unassigned handler will get stuck with
20  * "IRQ_WAITING" cleared and the interrupt disabled.
21  */
22 static DEFINE_MUTEX(probing_active);
23
24 /**
25  *      probe_irq_on    - begin an interrupt autodetect
26  *
27  *      Commence probing for an interrupt. The interrupts are scanned
28  *      and a mask of potential interrupt lines is returned.
29  *
30  */
31 unsigned long probe_irq_on(void)
32 {
33         struct irq_desc *desc;
34         unsigned long mask = 0;
35         unsigned int status;
36         int i;
37
38         /*
39          * quiesce the kernel, or at least the asynchronous portion
40          */
41         async_synchronize_full();
42         mutex_lock(&probing_active);
43         /*
44          * something may have generated an irq long ago and we want to
45          * flush such a longstanding irq before considering it as spurious.
46          */
47         for_each_irq_desc_reverse(i, desc) {
48                 spin_lock_irq(&desc->lock);
49                 if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
50                         /*
51                          * An old-style architecture might still have
52                          * the handle_bad_irq handler there:
53                          */
54                         compat_irq_chip_set_default_handler(desc);
55
56                         /*
57                          * Some chips need to know about probing in
58                          * progress:
59                          */
60                         if (desc->chip->set_type)
61                                 desc->chip->set_type(i, IRQ_TYPE_PROBE);
62                         desc->chip->startup(i);
63                 }
64                 spin_unlock_irq(&desc->lock);
65         }
66
67         /* Wait for longstanding interrupts to trigger. */
68         msleep(20);
69
70         /*
71          * enable any unassigned irqs
72          * (we must startup again here because if a longstanding irq
73          * happened in the previous stage, it may have masked itself)
74          */
75         for_each_irq_desc_reverse(i, desc) {
76                 spin_lock_irq(&desc->lock);
77                 if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
78                         desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
79                         if (desc->chip->startup(i))
80                                 desc->status |= IRQ_PENDING;
81                 }
82                 spin_unlock_irq(&desc->lock);
83         }
84
85         /*
86          * Wait for spurious interrupts to trigger
87          */
88         msleep(100);
89
90         /*
91          * Now filter out any obviously spurious interrupts
92          */
93         for_each_irq_desc(i, desc) {
94                 spin_lock_irq(&desc->lock);
95                 status = desc->status;
96
97                 if (status & IRQ_AUTODETECT) {
98                         /* It triggered already - consider it spurious. */
99                         if (!(status & IRQ_WAITING)) {
100                                 desc->status = status & ~IRQ_AUTODETECT;
101                                 desc->chip->shutdown(i);
102                         } else
103                                 if (i < 32)
104                                         mask |= 1 << i;
105                 }
106                 spin_unlock_irq(&desc->lock);
107         }
108
109         return mask;
110 }
111 EXPORT_SYMBOL(probe_irq_on);
112
113 /**
114  *      probe_irq_mask - scan a bitmap of interrupt lines
115  *      @val:   mask of interrupts to consider
116  *
117  *      Scan the interrupt lines and return a bitmap of active
118  *      autodetect interrupts. The interrupt probe logic state
119  *      is then returned to its previous value.
120  *
121  *      Note: we need to scan all the irq's even though we will
122  *      only return autodetect irq numbers - just so that we reset
123  *      them all to a known state.
124  */
125 unsigned int probe_irq_mask(unsigned long val)
126 {
127         unsigned int status, mask = 0;
128         struct irq_desc *desc;
129         int i;
130
131         for_each_irq_desc(i, desc) {
132                 spin_lock_irq(&desc->lock);
133                 status = desc->status;
134
135                 if (status & IRQ_AUTODETECT) {
136                         if (i < 16 && !(status & IRQ_WAITING))
137                                 mask |= 1 << i;
138
139                         desc->status = status & ~IRQ_AUTODETECT;
140                         desc->chip->shutdown(i);
141                 }
142                 spin_unlock_irq(&desc->lock);
143         }
144         mutex_unlock(&probing_active);
145
146         return mask & val;
147 }
148 EXPORT_SYMBOL(probe_irq_mask);
149
150 /**
151  *      probe_irq_off   - end an interrupt autodetect
152  *      @val: mask of potential interrupts (unused)
153  *
154  *      Scans the unused interrupt lines and returns the line which
155  *      appears to have triggered the interrupt. If no interrupt was
156  *      found then zero is returned. If more than one interrupt is
157  *      found then minus the first candidate is returned to indicate
158  *      their is doubt.
159  *
160  *      The interrupt probe logic state is returned to its previous
161  *      value.
162  *
163  *      BUGS: When used in a module (which arguably shouldn't happen)
164  *      nothing prevents two IRQ probe callers from overlapping. The
165  *      results of this are non-optimal.
166  */
167 int probe_irq_off(unsigned long val)
168 {
169         int i, irq_found = 0, nr_of_irqs = 0;
170         struct irq_desc *desc;
171         unsigned int status;
172
173         for_each_irq_desc(i, desc) {
174                 spin_lock_irq(&desc->lock);
175                 status = desc->status;
176
177                 if (status & IRQ_AUTODETECT) {
178                         if (!(status & IRQ_WAITING)) {
179                                 if (!nr_of_irqs)
180                                         irq_found = i;
181                                 nr_of_irqs++;
182                         }
183                         desc->status = status & ~IRQ_AUTODETECT;
184                         desc->chip->shutdown(i);
185                 }
186                 spin_unlock_irq(&desc->lock);
187         }
188         mutex_unlock(&probing_active);
189
190         if (nr_of_irqs > 1)
191                 irq_found = -irq_found;
192
193         return irq_found;
194 }
195 EXPORT_SYMBOL(probe_irq_off);
196