diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-08-19 23:50:05 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:52:29 -0400 |
commit | 08678b0841267c1d00d771fe01548d86043d065e (patch) | |
tree | 7debb21f9e9a768ced43077f7376797a0c46f8c0 /kernel | |
parent | bfea1238beac9d306eeac081c67de5ca6aec4c7a (diff) |
generic: sparse irqs: use irq_desc() together with dyn_array, instead of irq_desc[]
add CONFIG_HAVE_SPARSE_IRQ to for use condensed array.
Get rid of irq_desc[] array assumptions.
Preallocate 32 irq_desc, and irq_desc() will try to get more.
( No change in functionality is expected anywhere, except the odd build
failure where we missed a code site or where a crossing commit itroduces
new irq_desc[] usage. )
v2: according to Eric, change get_irq_desc() to irq_desc()
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq/autoprobe.c | 10 | ||||
-rw-r--r-- | kernel/irq/chip.c | 32 | ||||
-rw-r--r-- | kernel/irq/handle.c | 138 | ||||
-rw-r--r-- | kernel/irq/manage.c | 35 | ||||
-rw-r--r-- | kernel/irq/migration.c | 14 | ||||
-rw-r--r-- | kernel/irq/proc.c | 36 | ||||
-rw-r--r-- | kernel/irq/resend.c | 2 | ||||
-rw-r--r-- | kernel/irq/spurious.c | 5 |
8 files changed, 199 insertions, 73 deletions
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c index c689e9851a80..c45ab718cf07 100644 --- a/kernel/irq/autoprobe.c +++ b/kernel/irq/autoprobe.c | |||
@@ -39,7 +39,7 @@ unsigned long probe_irq_on(void) | |||
39 | * flush such a longstanding irq before considering it as spurious. | 39 | * flush such a longstanding irq before considering it as spurious. |
40 | */ | 40 | */ |
41 | for (i = nr_irqs-1; i > 0; i--) { | 41 | for (i = nr_irqs-1; i > 0; i--) { |
42 | desc = irq_desc + i; | 42 | desc = irq_to_desc(i); |
43 | 43 | ||
44 | spin_lock_irq(&desc->lock); | 44 | spin_lock_irq(&desc->lock); |
45 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { | 45 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
@@ -69,7 +69,7 @@ unsigned long probe_irq_on(void) | |||
69 | * happened in the previous stage, it may have masked itself) | 69 | * happened in the previous stage, it may have masked itself) |
70 | */ | 70 | */ |
71 | for (i = nr_irqs-1; i > 0; i--) { | 71 | for (i = nr_irqs-1; i > 0; i--) { |
72 | desc = irq_desc + i; | 72 | desc = irq_to_desc(i); |
73 | 73 | ||
74 | spin_lock_irq(&desc->lock); | 74 | spin_lock_irq(&desc->lock); |
75 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { | 75 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
@@ -92,7 +92,7 @@ unsigned long probe_irq_on(void) | |||
92 | for (i = 0; i < nr_irqs; i++) { | 92 | for (i = 0; i < nr_irqs; i++) { |
93 | unsigned int status; | 93 | unsigned int status; |
94 | 94 | ||
95 | desc = irq_desc + i; | 95 | desc = irq_to_desc(i); |
96 | spin_lock_irq(&desc->lock); | 96 | spin_lock_irq(&desc->lock); |
97 | status = desc->status; | 97 | status = desc->status; |
98 | 98 | ||
@@ -131,7 +131,7 @@ unsigned int probe_irq_mask(unsigned long val) | |||
131 | 131 | ||
132 | mask = 0; | 132 | mask = 0; |
133 | for (i = 0; i < nr_irqs; i++) { | 133 | for (i = 0; i < nr_irqs; i++) { |
134 | struct irq_desc *desc = irq_desc + i; | 134 | struct irq_desc *desc = irq_to_desc(i); |
135 | unsigned int status; | 135 | unsigned int status; |
136 | 136 | ||
137 | spin_lock_irq(&desc->lock); | 137 | spin_lock_irq(&desc->lock); |
@@ -174,7 +174,7 @@ int probe_irq_off(unsigned long val) | |||
174 | int i, irq_found = 0, nr_irqs = 0; | 174 | int i, irq_found = 0, nr_irqs = 0; |
175 | 175 | ||
176 | for (i = 0; i < nr_irqs; i++) { | 176 | for (i = 0; i < nr_irqs; i++) { |
177 | struct irq_desc *desc = irq_desc + i; | 177 | struct irq_desc *desc = irq_to_desc(i); |
178 | unsigned int status; | 178 | unsigned int status; |
179 | 179 | ||
180 | spin_lock_irq(&desc->lock); | 180 | spin_lock_irq(&desc->lock); |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index bba66e098703..76c225cf4b26 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -33,7 +33,7 @@ void dynamic_irq_init(unsigned int irq) | |||
33 | } | 33 | } |
34 | 34 | ||
35 | /* Ensure we don't have left over values from a previous use of this irq */ | 35 | /* Ensure we don't have left over values from a previous use of this irq */ |
36 | desc = irq_desc + irq; | 36 | desc = irq_to_desc(irq); |
37 | spin_lock_irqsave(&desc->lock, flags); | 37 | spin_lock_irqsave(&desc->lock, flags); |
38 | desc->status = IRQ_DISABLED; | 38 | desc->status = IRQ_DISABLED; |
39 | desc->chip = &no_irq_chip; | 39 | desc->chip = &no_irq_chip; |
@@ -65,7 +65,7 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | desc = irq_desc + irq; | 68 | desc = irq_to_desc(irq); |
69 | spin_lock_irqsave(&desc->lock, flags); | 69 | spin_lock_irqsave(&desc->lock, flags); |
70 | if (desc->action) { | 70 | if (desc->action) { |
71 | spin_unlock_irqrestore(&desc->lock, flags); | 71 | spin_unlock_irqrestore(&desc->lock, flags); |
@@ -100,7 +100,7 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip) | |||
100 | if (!chip) | 100 | if (!chip) |
101 | chip = &no_irq_chip; | 101 | chip = &no_irq_chip; |
102 | 102 | ||
103 | desc = irq_desc + irq; | 103 | desc = irq_to_desc(irq); |
104 | spin_lock_irqsave(&desc->lock, flags); | 104 | spin_lock_irqsave(&desc->lock, flags); |
105 | irq_chip_set_defaults(chip); | 105 | irq_chip_set_defaults(chip); |
106 | desc->chip = chip; | 106 | desc->chip = chip; |
@@ -126,7 +126,7 @@ int set_irq_type(unsigned int irq, unsigned int type) | |||
126 | return -ENODEV; | 126 | return -ENODEV; |
127 | } | 127 | } |
128 | 128 | ||
129 | desc = irq_desc + irq; | 129 | desc = irq_to_desc(irq); |
130 | if (type == IRQ_TYPE_NONE) | 130 | if (type == IRQ_TYPE_NONE) |
131 | return 0; | 131 | return 0; |
132 | 132 | ||
@@ -155,7 +155,7 @@ int set_irq_data(unsigned int irq, void *data) | |||
155 | return -EINVAL; | 155 | return -EINVAL; |
156 | } | 156 | } |
157 | 157 | ||
158 | desc = irq_desc + irq; | 158 | desc = irq_to_desc(irq); |
159 | spin_lock_irqsave(&desc->lock, flags); | 159 | spin_lock_irqsave(&desc->lock, flags); |
160 | desc->handler_data = data; | 160 | desc->handler_data = data; |
161 | spin_unlock_irqrestore(&desc->lock, flags); | 161 | spin_unlock_irqrestore(&desc->lock, flags); |
@@ -180,7 +180,7 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry) | |||
180 | "Trying to install msi data for IRQ%d\n", irq); | 180 | "Trying to install msi data for IRQ%d\n", irq); |
181 | return -EINVAL; | 181 | return -EINVAL; |
182 | } | 182 | } |
183 | desc = irq_desc + irq; | 183 | desc = irq_to_desc(irq); |
184 | spin_lock_irqsave(&desc->lock, flags); | 184 | spin_lock_irqsave(&desc->lock, flags); |
185 | desc->msi_desc = entry; | 185 | desc->msi_desc = entry; |
186 | if (entry) | 186 | if (entry) |
@@ -198,9 +198,10 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry) | |||
198 | */ | 198 | */ |
199 | int set_irq_chip_data(unsigned int irq, void *data) | 199 | int set_irq_chip_data(unsigned int irq, void *data) |
200 | { | 200 | { |
201 | struct irq_desc *desc = irq_desc + irq; | 201 | struct irq_desc *desc; |
202 | unsigned long flags; | 202 | unsigned long flags; |
203 | 203 | ||
204 | desc = irq_to_desc(irq); | ||
204 | if (irq >= nr_irqs || !desc->chip) { | 205 | if (irq >= nr_irqs || !desc->chip) { |
205 | printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); | 206 | printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); |
206 | return -EINVAL; | 207 | return -EINVAL; |
@@ -219,8 +220,9 @@ EXPORT_SYMBOL(set_irq_chip_data); | |||
219 | */ | 220 | */ |
220 | static void default_enable(unsigned int irq) | 221 | static void default_enable(unsigned int irq) |
221 | { | 222 | { |
222 | struct irq_desc *desc = irq_desc + irq; | 223 | struct irq_desc *desc; |
223 | 224 | ||
225 | desc = irq_to_desc(irq); | ||
224 | desc->chip->unmask(irq); | 226 | desc->chip->unmask(irq); |
225 | desc->status &= ~IRQ_MASKED; | 227 | desc->status &= ~IRQ_MASKED; |
226 | } | 228 | } |
@@ -237,7 +239,10 @@ static void default_disable(unsigned int irq) | |||
237 | */ | 239 | */ |
238 | static unsigned int default_startup(unsigned int irq) | 240 | static unsigned int default_startup(unsigned int irq) |
239 | { | 241 | { |
240 | irq_desc[irq].chip->enable(irq); | 242 | struct irq_desc *desc; |
243 | |||
244 | desc = irq_to_desc(irq); | ||
245 | desc->chip->enable(irq); | ||
241 | 246 | ||
242 | return 0; | 247 | return 0; |
243 | } | 248 | } |
@@ -247,8 +252,9 @@ static unsigned int default_startup(unsigned int irq) | |||
247 | */ | 252 | */ |
248 | static void default_shutdown(unsigned int irq) | 253 | static void default_shutdown(unsigned int irq) |
249 | { | 254 | { |
250 | struct irq_desc *desc = irq_desc + irq; | 255 | struct irq_desc *desc; |
251 | 256 | ||
257 | desc = irq_to_desc(irq); | ||
252 | desc->chip->mask(irq); | 258 | desc->chip->mask(irq); |
253 | desc->status |= IRQ_MASKED; | 259 | desc->status |= IRQ_MASKED; |
254 | } | 260 | } |
@@ -551,7 +557,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
551 | return; | 557 | return; |
552 | } | 558 | } |
553 | 559 | ||
554 | desc = irq_desc + irq; | 560 | desc = irq_to_desc(irq); |
555 | 561 | ||
556 | if (!handle) | 562 | if (!handle) |
557 | handle = handle_bad_irq; | 563 | handle = handle_bad_irq; |
@@ -616,7 +622,7 @@ void __init set_irq_noprobe(unsigned int irq) | |||
616 | return; | 622 | return; |
617 | } | 623 | } |
618 | 624 | ||
619 | desc = irq_desc + irq; | 625 | desc = irq_to_desc(irq); |
620 | 626 | ||
621 | spin_lock_irqsave(&desc->lock, flags); | 627 | spin_lock_irqsave(&desc->lock, flags); |
622 | desc->status |= IRQ_NOPROBE; | 628 | desc->status |= IRQ_NOPROBE; |
@@ -634,7 +640,7 @@ void __init set_irq_probe(unsigned int irq) | |||
634 | return; | 640 | return; |
635 | } | 641 | } |
636 | 642 | ||
637 | desc = irq_desc + irq; | 643 | desc = irq_to_desc(irq); |
638 | 644 | ||
639 | spin_lock_irqsave(&desc->lock, flags); | 645 | spin_lock_irqsave(&desc->lock, flags); |
640 | desc->status &= ~IRQ_NOPROBE; | 646 | desc->status &= ~IRQ_NOPROBE; |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 6ce3bcc2b8f7..9fc33b3378e6 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -18,6 +18,14 @@ | |||
18 | 18 | ||
19 | #include "internals.h" | 19 | #include "internals.h" |
20 | 20 | ||
21 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
22 | |||
23 | /* | ||
24 | * lockdep: we want to handle all irq_desc locks as a single lock-class: | ||
25 | */ | ||
26 | static struct lock_class_key irq_desc_lock_class; | ||
27 | #endif | ||
28 | |||
21 | /** | 29 | /** |
22 | * handle_bad_irq - handle spurious and unhandled irqs | 30 | * handle_bad_irq - handle spurious and unhandled irqs |
23 | * @irq: the interrupt number | 31 | * @irq: the interrupt number |
@@ -51,7 +59,8 @@ int nr_irqs = NR_IRQS; | |||
51 | EXPORT_SYMBOL_GPL(nr_irqs); | 59 | EXPORT_SYMBOL_GPL(nr_irqs); |
52 | 60 | ||
53 | #ifdef CONFIG_HAVE_DYN_ARRAY | 61 | #ifdef CONFIG_HAVE_DYN_ARRAY |
54 | static struct irq_desc irq_desc_init __initdata = { | 62 | static struct irq_desc irq_desc_init = { |
63 | .irq = -1U, | ||
55 | .status = IRQ_DISABLED, | 64 | .status = IRQ_DISABLED, |
56 | .chip = &no_irq_chip, | 65 | .chip = &no_irq_chip, |
57 | .handle_irq = handle_bad_irq, | 66 | .handle_irq = handle_bad_irq, |
@@ -62,6 +71,27 @@ static struct irq_desc irq_desc_init __initdata = { | |||
62 | #endif | 71 | #endif |
63 | }; | 72 | }; |
64 | 73 | ||
74 | |||
75 | static void init_one_irq_desc(struct irq_desc *desc) | ||
76 | { | ||
77 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); | ||
78 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
79 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); | ||
80 | #endif | ||
81 | } | ||
82 | |||
83 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
84 | static int nr_irq_desc = 32; | ||
85 | |||
86 | static int __init parse_nr_irq_desc(char *arg) | ||
87 | { | ||
88 | if (arg) | ||
89 | nr_irq_desc = simple_strtoul(arg, NULL, 0); | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | early_param("nr_irq_desc", parse_nr_irq_desc); | ||
94 | |||
65 | static void __init init_work(void *data) | 95 | static void __init init_work(void *data) |
66 | { | 96 | { |
67 | struct dyn_array *da = data; | 97 | struct dyn_array *da = data; |
@@ -71,12 +101,83 @@ static void __init init_work(void *data) | |||
71 | desc = *da->name; | 101 | desc = *da->name; |
72 | 102 | ||
73 | for (i = 0; i < *da->nr; i++) | 103 | for (i = 0; i < *da->nr; i++) |
74 | memcpy(&desc[i], &irq_desc_init, sizeof(struct irq_desc)); | 104 | init_one_irq_desc(&desc[i]); |
105 | |||
106 | for (i = 1; i < *da->nr; i++) | ||
107 | desc[i-1].next = &desc[i]; | ||
75 | } | 108 | } |
76 | 109 | ||
77 | struct irq_desc *irq_desc; | 110 | static struct irq_desc *sparse_irqs; |
111 | DEFINE_DYN_ARRAY(sparse_irqs, sizeof(struct irq_desc), nr_irq_desc, PAGE_SIZE, init_work); | ||
112 | |||
113 | extern int after_bootmem; | ||
114 | extern void *__alloc_bootmem_nopanic(unsigned long size, | ||
115 | unsigned long align, | ||
116 | unsigned long goal); | ||
117 | struct irq_desc *irq_to_desc(unsigned int irq) | ||
118 | { | ||
119 | struct irq_desc *desc, *desc_pri; | ||
120 | int i; | ||
121 | int count = 0; | ||
122 | |||
123 | BUG_ON(irq == -1U); | ||
124 | |||
125 | desc_pri = desc = &sparse_irqs[0]; | ||
126 | while (desc) { | ||
127 | if (desc->irq == irq) | ||
128 | return desc; | ||
129 | |||
130 | if (desc->irq == -1U) { | ||
131 | desc->irq = irq; | ||
132 | return desc; | ||
133 | } | ||
134 | desc_pri = desc; | ||
135 | desc = desc->next; | ||
136 | count++; | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * we run out of pre-allocate ones, allocate more | ||
141 | */ | ||
142 | printk(KERN_DEBUG "try to get more irq_desc %d\n", nr_irq_desc); | ||
143 | |||
144 | if (after_bootmem) | ||
145 | desc = kzalloc(sizeof(struct irq_desc)*nr_irq_desc, GFP_ATOMIC); | ||
146 | else | ||
147 | desc = __alloc_bootmem_nopanic(sizeof(struct irq_desc)*nr_irq_desc, PAGE_SIZE, 0); | ||
148 | |||
149 | if (!desc) | ||
150 | panic("please boot with nr_irq_desc= %d\n", count * 2); | ||
151 | |||
152 | for (i = 0; i < nr_irq_desc; i++) | ||
153 | init_one_irq_desc(&desc[i]); | ||
154 | |||
155 | for (i = 1; i < nr_irq_desc; i++) | ||
156 | desc[i-1].next = &desc[i]; | ||
157 | |||
158 | desc->irq = irq; | ||
159 | desc_pri->next = desc; | ||
160 | |||
161 | return desc; | ||
162 | } | ||
163 | #else | ||
164 | static void __init init_work(void *data) | ||
165 | { | ||
166 | struct dyn_array *da = data; | ||
167 | int i; | ||
168 | struct irq_desc *desc; | ||
169 | |||
170 | desc = *da->name; | ||
171 | |||
172 | for (i = 0; i < *da->nr; i++) | ||
173 | init_one_irq_desc(&desc[i]); | ||
174 | |||
175 | } | ||
176 | static struct irq_desc *irq_desc; | ||
78 | DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work); | 177 | DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work); |
79 | 178 | ||
179 | #endif | ||
180 | |||
80 | #else | 181 | #else |
81 | 182 | ||
82 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 183 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { |
@@ -85,12 +186,23 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | |||
85 | .chip = &no_irq_chip, | 186 | .chip = &no_irq_chip, |
86 | .handle_irq = handle_bad_irq, | 187 | .handle_irq = handle_bad_irq, |
87 | .depth = 1, | 188 | .depth = 1, |
88 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), | 189 | .lock = __SPIN_LOCK_UNLOCKED(sparse_irqs->lock), |
89 | #ifdef CONFIG_SMP | 190 | #ifdef CONFIG_SMP |
90 | .affinity = CPU_MASK_ALL | 191 | .affinity = CPU_MASK_ALL |
91 | #endif | 192 | #endif |
92 | } | 193 | } |
93 | }; | 194 | }; |
195 | |||
196 | #endif | ||
197 | |||
198 | #ifndef CONFIG_HAVE_SPARSE_IRQ | ||
199 | struct irq_desc *irq_to_desc(unsigned int irq) | ||
200 | { | ||
201 | if (irq < nr_irqs) | ||
202 | return &irq_desc[irq]; | ||
203 | |||
204 | return NULL; | ||
205 | } | ||
94 | #endif | 206 | #endif |
95 | 207 | ||
96 | /* | 208 | /* |
@@ -99,7 +211,10 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | |||
99 | */ | 211 | */ |
100 | static void ack_bad(unsigned int irq) | 212 | static void ack_bad(unsigned int irq) |
101 | { | 213 | { |
102 | print_irq_desc(irq, irq_desc + irq); | 214 | struct irq_desc *desc; |
215 | |||
216 | desc = irq_to_desc(irq); | ||
217 | print_irq_desc(irq, desc); | ||
103 | ack_bad_irq(irq); | 218 | ack_bad_irq(irq); |
104 | } | 219 | } |
105 | 220 | ||
@@ -196,7 +311,7 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
196 | */ | 311 | */ |
197 | unsigned int __do_IRQ(unsigned int irq) | 312 | unsigned int __do_IRQ(unsigned int irq) |
198 | { | 313 | { |
199 | struct irq_desc *desc = irq_desc + irq; | 314 | struct irq_desc *desc = irq_to_desc(irq); |
200 | struct irqaction *action; | 315 | struct irqaction *action; |
201 | unsigned int status; | 316 | unsigned int status; |
202 | 317 | ||
@@ -287,19 +402,16 @@ out: | |||
287 | } | 402 | } |
288 | #endif | 403 | #endif |
289 | 404 | ||
290 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
291 | |||
292 | /* | ||
293 | * lockdep: we want to handle all irq_desc locks as a single lock-class: | ||
294 | */ | ||
295 | static struct lock_class_key irq_desc_lock_class; | ||
296 | 405 | ||
406 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
297 | void early_init_irq_lock_class(void) | 407 | void early_init_irq_lock_class(void) |
298 | { | 408 | { |
409 | #ifndef CONFIG_HAVE_DYN_ARRAY | ||
299 | int i; | 410 | int i; |
300 | 411 | ||
301 | for (i = 0; i < nr_irqs; i++) | 412 | for (i = 0; i < nr_irqs; i++) |
302 | lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class); | 413 | lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class); |
414 | #endif | ||
303 | } | 415 | } |
304 | |||
305 | #endif | 416 | #endif |
417 | |||
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index d5a4333d8f1f..b5943e9f95aa 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -31,7 +31,7 @@ cpumask_t irq_default_affinity = CPU_MASK_ALL; | |||
31 | */ | 31 | */ |
32 | void synchronize_irq(unsigned int irq) | 32 | void synchronize_irq(unsigned int irq) |
33 | { | 33 | { |
34 | struct irq_desc *desc = irq_desc + irq; | 34 | struct irq_desc *desc = irq_to_desc(irq); |
35 | unsigned int status; | 35 | unsigned int status; |
36 | 36 | ||
37 | if (irq >= nr_irqs) | 37 | if (irq >= nr_irqs) |
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(synchronize_irq); | |||
64 | */ | 64 | */ |
65 | int irq_can_set_affinity(unsigned int irq) | 65 | int irq_can_set_affinity(unsigned int irq) |
66 | { | 66 | { |
67 | struct irq_desc *desc = irq_desc + irq; | 67 | struct irq_desc *desc = irq_to_desc(irq); |
68 | 68 | ||
69 | if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip || | 69 | if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip || |
70 | !desc->chip->set_affinity) | 70 | !desc->chip->set_affinity) |
@@ -81,7 +81,7 @@ int irq_can_set_affinity(unsigned int irq) | |||
81 | */ | 81 | */ |
82 | int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | 82 | int irq_set_affinity(unsigned int irq, cpumask_t cpumask) |
83 | { | 83 | { |
84 | struct irq_desc *desc = irq_desc + irq; | 84 | struct irq_desc *desc = irq_to_desc(irq); |
85 | 85 | ||
86 | if (!desc->chip->set_affinity) | 86 | if (!desc->chip->set_affinity) |
87 | return -EINVAL; | 87 | return -EINVAL; |
@@ -111,14 +111,16 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | |||
111 | int irq_select_affinity(unsigned int irq) | 111 | int irq_select_affinity(unsigned int irq) |
112 | { | 112 | { |
113 | cpumask_t mask; | 113 | cpumask_t mask; |
114 | struct irq_desc *desc; | ||
114 | 115 | ||
115 | if (!irq_can_set_affinity(irq)) | 116 | if (!irq_can_set_affinity(irq)) |
116 | return 0; | 117 | return 0; |
117 | 118 | ||
118 | cpus_and(mask, cpu_online_map, irq_default_affinity); | 119 | cpus_and(mask, cpu_online_map, irq_default_affinity); |
119 | 120 | ||
120 | irq_desc[irq].affinity = mask; | 121 | desc = irq_to_desc(irq); |
121 | irq_desc[irq].chip->set_affinity(irq, mask); | 122 | desc->affinity = mask; |
123 | desc->chip->set_affinity(irq, mask); | ||
122 | 124 | ||
123 | set_balance_irq_affinity(irq, mask); | 125 | set_balance_irq_affinity(irq, mask); |
124 | return 0; | 126 | return 0; |
@@ -140,7 +142,7 @@ int irq_select_affinity(unsigned int irq) | |||
140 | */ | 142 | */ |
141 | void disable_irq_nosync(unsigned int irq) | 143 | void disable_irq_nosync(unsigned int irq) |
142 | { | 144 | { |
143 | struct irq_desc *desc = irq_desc + irq; | 145 | struct irq_desc *desc = irq_to_desc(irq); |
144 | unsigned long flags; | 146 | unsigned long flags; |
145 | 147 | ||
146 | if (irq >= nr_irqs) | 148 | if (irq >= nr_irqs) |
@@ -169,7 +171,7 @@ EXPORT_SYMBOL(disable_irq_nosync); | |||
169 | */ | 171 | */ |
170 | void disable_irq(unsigned int irq) | 172 | void disable_irq(unsigned int irq) |
171 | { | 173 | { |
172 | struct irq_desc *desc = irq_desc + irq; | 174 | struct irq_desc *desc = irq_to_desc(irq); |
173 | 175 | ||
174 | if (irq >= nr_irqs) | 176 | if (irq >= nr_irqs) |
175 | return; | 177 | return; |
@@ -211,7 +213,7 @@ static void __enable_irq(struct irq_desc *desc, unsigned int irq) | |||
211 | */ | 213 | */ |
212 | void enable_irq(unsigned int irq) | 214 | void enable_irq(unsigned int irq) |
213 | { | 215 | { |
214 | struct irq_desc *desc = irq_desc + irq; | 216 | struct irq_desc *desc = irq_to_desc(irq); |
215 | unsigned long flags; | 217 | unsigned long flags; |
216 | 218 | ||
217 | if (irq >= nr_irqs) | 219 | if (irq >= nr_irqs) |
@@ -225,7 +227,7 @@ EXPORT_SYMBOL(enable_irq); | |||
225 | 227 | ||
226 | static int set_irq_wake_real(unsigned int irq, unsigned int on) | 228 | static int set_irq_wake_real(unsigned int irq, unsigned int on) |
227 | { | 229 | { |
228 | struct irq_desc *desc = irq_desc + irq; | 230 | struct irq_desc *desc = irq_to_desc(irq); |
229 | int ret = -ENXIO; | 231 | int ret = -ENXIO; |
230 | 232 | ||
231 | if (desc->chip->set_wake) | 233 | if (desc->chip->set_wake) |
@@ -248,7 +250,7 @@ static int set_irq_wake_real(unsigned int irq, unsigned int on) | |||
248 | */ | 250 | */ |
249 | int set_irq_wake(unsigned int irq, unsigned int on) | 251 | int set_irq_wake(unsigned int irq, unsigned int on) |
250 | { | 252 | { |
251 | struct irq_desc *desc = irq_desc + irq; | 253 | struct irq_desc *desc = irq_to_desc(irq); |
252 | unsigned long flags; | 254 | unsigned long flags; |
253 | int ret = 0; | 255 | int ret = 0; |
254 | 256 | ||
@@ -288,12 +290,13 @@ EXPORT_SYMBOL(set_irq_wake); | |||
288 | */ | 290 | */ |
289 | int can_request_irq(unsigned int irq, unsigned long irqflags) | 291 | int can_request_irq(unsigned int irq, unsigned long irqflags) |
290 | { | 292 | { |
293 | struct irq_desc *desc = irq_to_desc(irq); | ||
291 | struct irqaction *action; | 294 | struct irqaction *action; |
292 | 295 | ||
293 | if (irq >= nr_irqs || irq_desc[irq].status & IRQ_NOREQUEST) | 296 | if (irq >= nr_irqs || desc->status & IRQ_NOREQUEST) |
294 | return 0; | 297 | return 0; |
295 | 298 | ||
296 | action = irq_desc[irq].action; | 299 | action = desc->action; |
297 | if (action) | 300 | if (action) |
298 | if (irqflags & action->flags & IRQF_SHARED) | 301 | if (irqflags & action->flags & IRQF_SHARED) |
299 | action = NULL; | 302 | action = NULL; |
@@ -349,7 +352,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
349 | */ | 352 | */ |
350 | int setup_irq(unsigned int irq, struct irqaction *new) | 353 | int setup_irq(unsigned int irq, struct irqaction *new) |
351 | { | 354 | { |
352 | struct irq_desc *desc = irq_desc + irq; | 355 | struct irq_desc *desc = irq_to_desc(irq); |
353 | struct irqaction *old, **p; | 356 | struct irqaction *old, **p; |
354 | const char *old_name = NULL; | 357 | const char *old_name = NULL; |
355 | unsigned long flags; | 358 | unsigned long flags; |
@@ -518,7 +521,7 @@ void free_irq(unsigned int irq, void *dev_id) | |||
518 | if (irq >= nr_irqs) | 521 | if (irq >= nr_irqs) |
519 | return; | 522 | return; |
520 | 523 | ||
521 | desc = irq_desc + irq; | 524 | desc = irq_to_desc(irq); |
522 | spin_lock_irqsave(&desc->lock, flags); | 525 | spin_lock_irqsave(&desc->lock, flags); |
523 | p = &desc->action; | 526 | p = &desc->action; |
524 | for (;;) { | 527 | for (;;) { |
@@ -615,6 +618,7 @@ int request_irq(unsigned int irq, irq_handler_t handler, | |||
615 | { | 618 | { |
616 | struct irqaction *action; | 619 | struct irqaction *action; |
617 | int retval; | 620 | int retval; |
621 | struct irq_desc *desc; | ||
618 | 622 | ||
619 | #ifdef CONFIG_LOCKDEP | 623 | #ifdef CONFIG_LOCKDEP |
620 | /* | 624 | /* |
@@ -632,7 +636,8 @@ int request_irq(unsigned int irq, irq_handler_t handler, | |||
632 | return -EINVAL; | 636 | return -EINVAL; |
633 | if (irq >= nr_irqs) | 637 | if (irq >= nr_irqs) |
634 | return -EINVAL; | 638 | return -EINVAL; |
635 | if (irq_desc[irq].status & IRQ_NOREQUEST) | 639 | desc = irq_to_desc(irq); |
640 | if (desc->status & IRQ_NOREQUEST) | ||
636 | return -EINVAL; | 641 | return -EINVAL; |
637 | if (!handler) | 642 | if (!handler) |
638 | return -EINVAL; | 643 | return -EINVAL; |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index 77b7acc875c5..90b920d3f52b 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -3,18 +3,18 @@ | |||
3 | 3 | ||
4 | void set_pending_irq(unsigned int irq, cpumask_t mask) | 4 | void set_pending_irq(unsigned int irq, cpumask_t mask) |
5 | { | 5 | { |
6 | struct irq_desc *desc = irq_desc + irq; | 6 | struct irq_desc *desc = irq_to_desc(irq); |
7 | unsigned long flags; | 7 | unsigned long flags; |
8 | 8 | ||
9 | spin_lock_irqsave(&desc->lock, flags); | 9 | spin_lock_irqsave(&desc->lock, flags); |
10 | desc->status |= IRQ_MOVE_PENDING; | 10 | desc->status |= IRQ_MOVE_PENDING; |
11 | irq_desc[irq].pending_mask = mask; | 11 | desc->pending_mask = mask; |
12 | spin_unlock_irqrestore(&desc->lock, flags); | 12 | spin_unlock_irqrestore(&desc->lock, flags); |
13 | } | 13 | } |
14 | 14 | ||
15 | void move_masked_irq(int irq) | 15 | void move_masked_irq(int irq) |
16 | { | 16 | { |
17 | struct irq_desc *desc = irq_desc + irq; | 17 | struct irq_desc *desc = irq_to_desc(irq); |
18 | cpumask_t tmp; | 18 | cpumask_t tmp; |
19 | 19 | ||
20 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) | 20 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) |
@@ -30,7 +30,7 @@ void move_masked_irq(int irq) | |||
30 | 30 | ||
31 | desc->status &= ~IRQ_MOVE_PENDING; | 31 | desc->status &= ~IRQ_MOVE_PENDING; |
32 | 32 | ||
33 | if (unlikely(cpus_empty(irq_desc[irq].pending_mask))) | 33 | if (unlikely(cpus_empty(desc->pending_mask))) |
34 | return; | 34 | return; |
35 | 35 | ||
36 | if (!desc->chip->set_affinity) | 36 | if (!desc->chip->set_affinity) |
@@ -38,7 +38,7 @@ void move_masked_irq(int irq) | |||
38 | 38 | ||
39 | assert_spin_locked(&desc->lock); | 39 | assert_spin_locked(&desc->lock); |
40 | 40 | ||
41 | cpus_and(tmp, irq_desc[irq].pending_mask, cpu_online_map); | 41 | cpus_and(tmp, desc->pending_mask, cpu_online_map); |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * If there was a valid mask to work with, please | 44 | * If there was a valid mask to work with, please |
@@ -55,12 +55,12 @@ void move_masked_irq(int irq) | |||
55 | if (likely(!cpus_empty(tmp))) { | 55 | if (likely(!cpus_empty(tmp))) { |
56 | desc->chip->set_affinity(irq,tmp); | 56 | desc->chip->set_affinity(irq,tmp); |
57 | } | 57 | } |
58 | cpus_clear(irq_desc[irq].pending_mask); | 58 | cpus_clear(desc->pending_mask); |
59 | } | 59 | } |
60 | 60 | ||
61 | void move_native_irq(int irq) | 61 | void move_native_irq(int irq) |
62 | { | 62 | { |
63 | struct irq_desc *desc = irq_desc + irq; | 63 | struct irq_desc *desc = irq_to_desc(irq); |
64 | 64 | ||
65 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) | 65 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) |
66 | return; | 66 | return; |
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index e5225a65a4f9..c2f356c808f6 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
@@ -19,7 +19,7 @@ static struct proc_dir_entry *root_irq_dir; | |||
19 | 19 | ||
20 | static int irq_affinity_proc_show(struct seq_file *m, void *v) | 20 | static int irq_affinity_proc_show(struct seq_file *m, void *v) |
21 | { | 21 | { |
22 | struct irq_desc *desc = irq_desc + (long)m->private; | 22 | struct irq_desc *desc = irq_to_desc((long)m->private); |
23 | cpumask_t *mask = &desc->affinity; | 23 | cpumask_t *mask = &desc->affinity; |
24 | 24 | ||
25 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 25 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
@@ -43,7 +43,7 @@ static ssize_t irq_affinity_proc_write(struct file *file, | |||
43 | cpumask_t new_value; | 43 | cpumask_t new_value; |
44 | int err; | 44 | int err; |
45 | 45 | ||
46 | if (!irq_desc[irq].chip->set_affinity || no_irq_affinity || | 46 | if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity || |
47 | irq_balancing_disabled(irq)) | 47 | irq_balancing_disabled(irq)) |
48 | return -EIO; | 48 | return -EIO; |
49 | 49 | ||
@@ -132,20 +132,20 @@ static const struct file_operations default_affinity_proc_fops = { | |||
132 | static int irq_spurious_read(char *page, char **start, off_t off, | 132 | static int irq_spurious_read(char *page, char **start, off_t off, |
133 | int count, int *eof, void *data) | 133 | int count, int *eof, void *data) |
134 | { | 134 | { |
135 | struct irq_desc *d = &irq_desc[(long) data]; | 135 | struct irq_desc *desc = irq_to_desc((long) data); |
136 | return sprintf(page, "count %u\n" | 136 | return sprintf(page, "count %u\n" |
137 | "unhandled %u\n" | 137 | "unhandled %u\n" |
138 | "last_unhandled %u ms\n", | 138 | "last_unhandled %u ms\n", |
139 | d->irq_count, | 139 | desc->irq_count, |
140 | d->irqs_unhandled, | 140 | desc->irqs_unhandled, |
141 | jiffies_to_msecs(d->last_unhandled)); | 141 | jiffies_to_msecs(desc->last_unhandled)); |
142 | } | 142 | } |
143 | 143 | ||
144 | #define MAX_NAMELEN 128 | 144 | #define MAX_NAMELEN 128 |
145 | 145 | ||
146 | static int name_unique(unsigned int irq, struct irqaction *new_action) | 146 | static int name_unique(unsigned int irq, struct irqaction *new_action) |
147 | { | 147 | { |
148 | struct irq_desc *desc = irq_desc + irq; | 148 | struct irq_desc *desc = irq_to_desc(irq); |
149 | struct irqaction *action; | 149 | struct irqaction *action; |
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | int ret = 1; | 151 | int ret = 1; |
@@ -165,8 +165,9 @@ static int name_unique(unsigned int irq, struct irqaction *new_action) | |||
165 | void register_handler_proc(unsigned int irq, struct irqaction *action) | 165 | void register_handler_proc(unsigned int irq, struct irqaction *action) |
166 | { | 166 | { |
167 | char name [MAX_NAMELEN]; | 167 | char name [MAX_NAMELEN]; |
168 | struct irq_desc *desc = irq_to_desc(irq); | ||
168 | 169 | ||
169 | if (!irq_desc[irq].dir || action->dir || !action->name || | 170 | if (!desc->dir || action->dir || !action->name || |
170 | !name_unique(irq, action)) | 171 | !name_unique(irq, action)) |
171 | return; | 172 | return; |
172 | 173 | ||
@@ -174,7 +175,7 @@ void register_handler_proc(unsigned int irq, struct irqaction *action) | |||
174 | snprintf(name, MAX_NAMELEN, "%s", action->name); | 175 | snprintf(name, MAX_NAMELEN, "%s", action->name); |
175 | 176 | ||
176 | /* create /proc/irq/1234/handler/ */ | 177 | /* create /proc/irq/1234/handler/ */ |
177 | action->dir = proc_mkdir(name, irq_desc[irq].dir); | 178 | action->dir = proc_mkdir(name, desc->dir); |
178 | } | 179 | } |
179 | 180 | ||
180 | #undef MAX_NAMELEN | 181 | #undef MAX_NAMELEN |
@@ -185,25 +186,24 @@ void register_irq_proc(unsigned int irq) | |||
185 | { | 186 | { |
186 | char name [MAX_NAMELEN]; | 187 | char name [MAX_NAMELEN]; |
187 | struct proc_dir_entry *entry; | 188 | struct proc_dir_entry *entry; |
189 | struct irq_desc *desc = irq_to_desc(irq); | ||
188 | 190 | ||
189 | if (!root_irq_dir || | 191 | if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir) |
190 | (irq_desc[irq].chip == &no_irq_chip) || | ||
191 | irq_desc[irq].dir) | ||
192 | return; | 192 | return; |
193 | 193 | ||
194 | memset(name, 0, MAX_NAMELEN); | 194 | memset(name, 0, MAX_NAMELEN); |
195 | sprintf(name, "%d", irq); | 195 | sprintf(name, "%d", irq); |
196 | 196 | ||
197 | /* create /proc/irq/1234 */ | 197 | /* create /proc/irq/1234 */ |
198 | irq_desc[irq].dir = proc_mkdir(name, root_irq_dir); | 198 | desc->dir = proc_mkdir(name, root_irq_dir); |
199 | 199 | ||
200 | #ifdef CONFIG_SMP | 200 | #ifdef CONFIG_SMP |
201 | /* create /proc/irq/<irq>/smp_affinity */ | 201 | /* create /proc/irq/<irq>/smp_affinity */ |
202 | proc_create_data("smp_affinity", 0600, irq_desc[irq].dir, | 202 | proc_create_data("smp_affinity", 0600, desc->dir, |
203 | &irq_affinity_proc_fops, (void *)(long)irq); | 203 | &irq_affinity_proc_fops, (void *)(long)irq); |
204 | #endif | 204 | #endif |
205 | 205 | ||
206 | entry = create_proc_entry("spurious", 0444, irq_desc[irq].dir); | 206 | entry = create_proc_entry("spurious", 0444, desc->dir); |
207 | if (entry) { | 207 | if (entry) { |
208 | entry->data = (void *)(long)irq; | 208 | entry->data = (void *)(long)irq; |
209 | entry->read_proc = irq_spurious_read; | 209 | entry->read_proc = irq_spurious_read; |
@@ -214,8 +214,10 @@ void register_irq_proc(unsigned int irq) | |||
214 | 214 | ||
215 | void unregister_handler_proc(unsigned int irq, struct irqaction *action) | 215 | void unregister_handler_proc(unsigned int irq, struct irqaction *action) |
216 | { | 216 | { |
217 | if (action->dir) | 217 | if (action->dir) { |
218 | remove_proc_entry(action->dir->name, irq_desc[irq].dir); | 218 | struct irq_desc *desc = irq_to_desc(irq); |
219 | remove_proc_entry(action->dir->name, desc->dir); | ||
220 | } | ||
219 | } | 221 | } |
220 | 222 | ||
221 | void register_default_affinity_proc(void) | 223 | void register_default_affinity_proc(void) |
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c index cba8aa5bc7f4..89c7117acf2b 100644 --- a/kernel/irq/resend.c +++ b/kernel/irq/resend.c | |||
@@ -36,7 +36,7 @@ static void resend_irqs(unsigned long arg) | |||
36 | while (!bitmap_empty(irqs_resend, nr_irqs)) { | 36 | while (!bitmap_empty(irqs_resend, nr_irqs)) { |
37 | irq = find_first_bit(irqs_resend, nr_irqs); | 37 | irq = find_first_bit(irqs_resend, nr_irqs); |
38 | clear_bit(irq, irqs_resend); | 38 | clear_bit(irq, irqs_resend); |
39 | desc = irq_desc + irq; | 39 | desc = irq_to_desc(irq); |
40 | local_irq_disable(); | 40 | local_irq_disable(); |
41 | desc->handle_irq(irq, desc); | 41 | desc->handle_irq(irq, desc); |
42 | local_irq_enable(); | 42 | local_irq_enable(); |
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index e26ca1e90c08..b5d906002e1d 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
@@ -92,11 +92,12 @@ static int misrouted_irq(int irq) | |||
92 | int ok = 0; | 92 | int ok = 0; |
93 | 93 | ||
94 | for (i = 1; i < nr_irqs; i++) { | 94 | for (i = 1; i < nr_irqs; i++) { |
95 | struct irq_desc *desc = irq_desc + i; | 95 | struct irq_desc *desc; |
96 | 96 | ||
97 | if (i == irq) /* Already tried */ | 97 | if (i == irq) /* Already tried */ |
98 | continue; | 98 | continue; |
99 | 99 | ||
100 | desc = irq_to_desc(i); | ||
100 | if (try_one_irq(i, desc)) | 101 | if (try_one_irq(i, desc)) |
101 | ok = 1; | 102 | ok = 1; |
102 | } | 103 | } |
@@ -108,7 +109,7 @@ static void poll_spurious_irqs(unsigned long dummy) | |||
108 | { | 109 | { |
109 | int i; | 110 | int i; |
110 | for (i = 1; i < nr_irqs; i++) { | 111 | for (i = 1; i < nr_irqs; i++) { |
111 | struct irq_desc *desc = irq_desc + i; | 112 | struct irq_desc *desc = irq_to_desc(i); |
112 | unsigned int status; | 113 | unsigned int status; |
113 | 114 | ||
114 | /* Racy but it doesn't matter */ | 115 | /* Racy but it doesn't matter */ |