diff options
Diffstat (limited to 'kernel/irq/autoprobe.c')
-rw-r--r-- | kernel/irq/autoprobe.c | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c index 3467097ca61a..533068cfb607 100644 --- a/kernel/irq/autoprobe.c +++ b/kernel/irq/autoprobe.c | |||
@@ -11,12 +11,14 @@ | |||
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | 13 | ||
14 | #include "internals.h" | ||
15 | |||
14 | /* | 16 | /* |
15 | * Autodetection depends on the fact that any interrupt that | 17 | * Autodetection depends on the fact that any interrupt that |
16 | * comes in on to an unassigned handler will get stuck with | 18 | * comes in on to an unassigned handler will get stuck with |
17 | * "IRQ_WAITING" cleared and the interrupt disabled. | 19 | * "IRQ_WAITING" cleared and the interrupt disabled. |
18 | */ | 20 | */ |
19 | static DECLARE_MUTEX(probe_sem); | 21 | static DEFINE_MUTEX(probing_active); |
20 | 22 | ||
21 | /** | 23 | /** |
22 | * probe_irq_on - begin an interrupt autodetect | 24 | * probe_irq_on - begin an interrupt autodetect |
@@ -27,11 +29,11 @@ static DECLARE_MUTEX(probe_sem); | |||
27 | */ | 29 | */ |
28 | unsigned long probe_irq_on(void) | 30 | unsigned long probe_irq_on(void) |
29 | { | 31 | { |
30 | unsigned long val; | 32 | struct irq_desc *desc; |
31 | irq_desc_t *desc; | 33 | unsigned long mask; |
32 | unsigned int i; | 34 | unsigned int i; |
33 | 35 | ||
34 | down(&probe_sem); | 36 | mutex_lock(&probing_active); |
35 | /* | 37 | /* |
36 | * something may have generated an irq long ago and we want to | 38 | * something may have generated an irq long ago and we want to |
37 | * flush such a longstanding irq before considering it as spurious. | 39 | * flush such a longstanding irq before considering it as spurious. |
@@ -40,8 +42,21 @@ unsigned long probe_irq_on(void) | |||
40 | desc = irq_desc + i; | 42 | desc = irq_desc + i; |
41 | 43 | ||
42 | spin_lock_irq(&desc->lock); | 44 | spin_lock_irq(&desc->lock); |
43 | if (!irq_desc[i].action) | 45 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
44 | irq_desc[i].handler->startup(i); | 46 | /* |
47 | * An old-style architecture might still have | ||
48 | * the handle_bad_irq handler there: | ||
49 | */ | ||
50 | compat_irq_chip_set_default_handler(desc); | ||
51 | |||
52 | /* | ||
53 | * Some chips need to know about probing in | ||
54 | * progress: | ||
55 | */ | ||
56 | if (desc->chip->set_type) | ||
57 | desc->chip->set_type(i, IRQ_TYPE_PROBE); | ||
58 | desc->chip->startup(i); | ||
59 | } | ||
45 | spin_unlock_irq(&desc->lock); | 60 | spin_unlock_irq(&desc->lock); |
46 | } | 61 | } |
47 | 62 | ||
@@ -57,9 +72,9 @@ unsigned long probe_irq_on(void) | |||
57 | desc = irq_desc + i; | 72 | desc = irq_desc + i; |
58 | 73 | ||
59 | spin_lock_irq(&desc->lock); | 74 | spin_lock_irq(&desc->lock); |
60 | if (!desc->action) { | 75 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
61 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; | 76 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; |
62 | if (desc->handler->startup(i)) | 77 | if (desc->chip->startup(i)) |
63 | desc->status |= IRQ_PENDING; | 78 | desc->status |= IRQ_PENDING; |
64 | } | 79 | } |
65 | spin_unlock_irq(&desc->lock); | 80 | spin_unlock_irq(&desc->lock); |
@@ -73,11 +88,11 @@ unsigned long probe_irq_on(void) | |||
73 | /* | 88 | /* |
74 | * Now filter out any obviously spurious interrupts | 89 | * Now filter out any obviously spurious interrupts |
75 | */ | 90 | */ |
76 | val = 0; | 91 | mask = 0; |
77 | for (i = 0; i < NR_IRQS; i++) { | 92 | for (i = 0; i < NR_IRQS; i++) { |
78 | irq_desc_t *desc = irq_desc + i; | ||
79 | unsigned int status; | 93 | unsigned int status; |
80 | 94 | ||
95 | desc = irq_desc + i; | ||
81 | spin_lock_irq(&desc->lock); | 96 | spin_lock_irq(&desc->lock); |
82 | status = desc->status; | 97 | status = desc->status; |
83 | 98 | ||
@@ -85,17 +100,16 @@ unsigned long probe_irq_on(void) | |||
85 | /* It triggered already - consider it spurious. */ | 100 | /* It triggered already - consider it spurious. */ |
86 | if (!(status & IRQ_WAITING)) { | 101 | if (!(status & IRQ_WAITING)) { |
87 | desc->status = status & ~IRQ_AUTODETECT; | 102 | desc->status = status & ~IRQ_AUTODETECT; |
88 | desc->handler->shutdown(i); | 103 | desc->chip->shutdown(i); |
89 | } else | 104 | } else |
90 | if (i < 32) | 105 | if (i < 32) |
91 | val |= 1 << i; | 106 | mask |= 1 << i; |
92 | } | 107 | } |
93 | spin_unlock_irq(&desc->lock); | 108 | spin_unlock_irq(&desc->lock); |
94 | } | 109 | } |
95 | 110 | ||
96 | return val; | 111 | return mask; |
97 | } | 112 | } |
98 | |||
99 | EXPORT_SYMBOL(probe_irq_on); | 113 | EXPORT_SYMBOL(probe_irq_on); |
100 | 114 | ||
101 | /** | 115 | /** |
@@ -117,7 +131,7 @@ unsigned int probe_irq_mask(unsigned long val) | |||
117 | 131 | ||
118 | mask = 0; | 132 | mask = 0; |
119 | for (i = 0; i < NR_IRQS; i++) { | 133 | for (i = 0; i < NR_IRQS; i++) { |
120 | irq_desc_t *desc = irq_desc + i; | 134 | struct irq_desc *desc = irq_desc + i; |
121 | unsigned int status; | 135 | unsigned int status; |
122 | 136 | ||
123 | spin_lock_irq(&desc->lock); | 137 | spin_lock_irq(&desc->lock); |
@@ -128,11 +142,11 @@ unsigned int probe_irq_mask(unsigned long val) | |||
128 | mask |= 1 << i; | 142 | mask |= 1 << i; |
129 | 143 | ||
130 | desc->status = status & ~IRQ_AUTODETECT; | 144 | desc->status = status & ~IRQ_AUTODETECT; |
131 | desc->handler->shutdown(i); | 145 | desc->chip->shutdown(i); |
132 | } | 146 | } |
133 | spin_unlock_irq(&desc->lock); | 147 | spin_unlock_irq(&desc->lock); |
134 | } | 148 | } |
135 | up(&probe_sem); | 149 | mutex_unlock(&probing_active); |
136 | 150 | ||
137 | return mask & val; | 151 | return mask & val; |
138 | } | 152 | } |
@@ -160,7 +174,7 @@ int probe_irq_off(unsigned long val) | |||
160 | int i, irq_found = 0, nr_irqs = 0; | 174 | int i, irq_found = 0, nr_irqs = 0; |
161 | 175 | ||
162 | for (i = 0; i < NR_IRQS; i++) { | 176 | for (i = 0; i < NR_IRQS; i++) { |
163 | irq_desc_t *desc = irq_desc + i; | 177 | struct irq_desc *desc = irq_desc + i; |
164 | unsigned int status; | 178 | unsigned int status; |
165 | 179 | ||
166 | spin_lock_irq(&desc->lock); | 180 | spin_lock_irq(&desc->lock); |
@@ -173,16 +187,16 @@ int probe_irq_off(unsigned long val) | |||
173 | nr_irqs++; | 187 | nr_irqs++; |
174 | } | 188 | } |
175 | desc->status = status & ~IRQ_AUTODETECT; | 189 | desc->status = status & ~IRQ_AUTODETECT; |
176 | desc->handler->shutdown(i); | 190 | desc->chip->shutdown(i); |
177 | } | 191 | } |
178 | spin_unlock_irq(&desc->lock); | 192 | spin_unlock_irq(&desc->lock); |
179 | } | 193 | } |
180 | up(&probe_sem); | 194 | mutex_unlock(&probing_active); |
181 | 195 | ||
182 | if (nr_irqs > 1) | 196 | if (nr_irqs > 1) |
183 | irq_found = -irq_found; | 197 | irq_found = -irq_found; |
198 | |||
184 | return irq_found; | 199 | return irq_found; |
185 | } | 200 | } |
186 | |||
187 | EXPORT_SYMBOL(probe_irq_off); | 201 | EXPORT_SYMBOL(probe_irq_off); |
188 | 202 | ||