diff options
Diffstat (limited to 'arch/x86/kernel/io_apic.c')
-rw-r--r-- | arch/x86/kernel/io_apic.c | 631 |
1 files changed, 383 insertions, 248 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 1184210e6d0c..d7f0993b8056 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c | |||
@@ -108,8 +108,33 @@ static int __init parse_noapic(char *str) | |||
108 | early_param("noapic", parse_noapic); | 108 | early_param("noapic", parse_noapic); |
109 | 109 | ||
110 | struct irq_pin_list; | 110 | struct irq_pin_list; |
111 | |||
112 | /* | ||
113 | * This is performance-critical, we want to do it O(1) | ||
114 | * | ||
115 | * the indexing order of this array favors 1:1 mappings | ||
116 | * between pins and IRQs. | ||
117 | */ | ||
118 | |||
119 | struct irq_pin_list { | ||
120 | int apic, pin; | ||
121 | struct irq_pin_list *next; | ||
122 | }; | ||
123 | |||
124 | static struct irq_pin_list *get_one_free_irq_2_pin(int cpu) | ||
125 | { | ||
126 | struct irq_pin_list *pin; | ||
127 | int node; | ||
128 | |||
129 | node = cpu_to_node(cpu); | ||
130 | |||
131 | pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node); | ||
132 | printk(KERN_DEBUG " alloc irq_2_pin on cpu %d node %d\n", cpu, node); | ||
133 | |||
134 | return pin; | ||
135 | } | ||
136 | |||
111 | struct irq_cfg { | 137 | struct irq_cfg { |
112 | unsigned int irq; | ||
113 | struct irq_pin_list *irq_2_pin; | 138 | struct irq_pin_list *irq_2_pin; |
114 | cpumask_t domain; | 139 | cpumask_t domain; |
115 | cpumask_t old_domain; | 140 | cpumask_t old_domain; |
@@ -119,81 +144,95 @@ struct irq_cfg { | |||
119 | }; | 144 | }; |
120 | 145 | ||
121 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ | 146 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ |
147 | #ifdef CONFIG_SPARSE_IRQ | ||
148 | static struct irq_cfg irq_cfgx[] = { | ||
149 | #else | ||
122 | static struct irq_cfg irq_cfgx[NR_IRQS] = { | 150 | static struct irq_cfg irq_cfgx[NR_IRQS] = { |
123 | [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, | 151 | #endif |
124 | [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, | 152 | [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, |
125 | [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, | 153 | [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, |
126 | [3] = { .irq = 3, .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR, }, | 154 | [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, |
127 | [4] = { .irq = 4, .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR, }, | 155 | [3] = { .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR, }, |
128 | [5] = { .irq = 5, .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR, }, | 156 | [4] = { .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR, }, |
129 | [6] = { .irq = 6, .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR, }, | 157 | [5] = { .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR, }, |
130 | [7] = { .irq = 7, .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR, }, | 158 | [6] = { .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR, }, |
131 | [8] = { .irq = 8, .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR, }, | 159 | [7] = { .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR, }, |
132 | [9] = { .irq = 9, .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR, }, | 160 | [8] = { .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR, }, |
133 | [10] = { .irq = 10, .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, }, | 161 | [9] = { .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR, }, |
134 | [11] = { .irq = 11, .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, }, | 162 | [10] = { .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, }, |
135 | [12] = { .irq = 12, .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, }, | 163 | [11] = { .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, }, |
136 | [13] = { .irq = 13, .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, }, | 164 | [12] = { .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, }, |
137 | [14] = { .irq = 14, .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, }, | 165 | [13] = { .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, }, |
138 | [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, | 166 | [14] = { .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, }, |
167 | [15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, | ||
139 | }; | 168 | }; |
140 | 169 | ||
141 | #define for_each_irq_cfg(irq, cfg) \ | 170 | void __init arch_early_irq_init(void) |
142 | for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++) | ||
143 | |||
144 | static struct irq_cfg *irq_cfg(unsigned int irq) | ||
145 | { | 171 | { |
146 | return irq < nr_irqs ? irq_cfgx + irq : NULL; | 172 | struct irq_cfg *cfg; |
173 | struct irq_desc *desc; | ||
174 | int count; | ||
175 | int i; | ||
176 | |||
177 | cfg = irq_cfgx; | ||
178 | count = ARRAY_SIZE(irq_cfgx); | ||
179 | |||
180 | for (i = 0; i < count; i++) { | ||
181 | desc = irq_to_desc(i); | ||
182 | desc->chip_data = &cfg[i]; | ||
183 | } | ||
147 | } | 184 | } |
148 | 185 | ||
149 | static struct irq_cfg *irq_cfg_alloc(unsigned int irq) | 186 | #ifdef CONFIG_SPARSE_IRQ |
187 | static struct irq_cfg *irq_cfg(unsigned int irq) | ||
150 | { | 188 | { |
151 | return irq_cfg(irq); | 189 | struct irq_cfg *cfg = NULL; |
190 | struct irq_desc *desc; | ||
191 | |||
192 | desc = irq_to_desc(irq); | ||
193 | if (desc) | ||
194 | cfg = desc->chip_data; | ||
195 | |||
196 | return cfg; | ||
152 | } | 197 | } |
153 | 198 | ||
154 | /* | 199 | static struct irq_cfg *get_one_free_irq_cfg(int cpu) |
155 | * Rough estimation of how many shared IRQs there are, can be changed | 200 | { |
156 | * anytime. | 201 | struct irq_cfg *cfg; |
157 | */ | 202 | int node; |
158 | #define MAX_PLUS_SHARED_IRQS NR_IRQS | ||
159 | #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) | ||
160 | 203 | ||
161 | /* | 204 | node = cpu_to_node(cpu); |
162 | * This is performance-critical, we want to do it O(1) | ||
163 | * | ||
164 | * the indexing order of this array favors 1:1 mappings | ||
165 | * between pins and IRQs. | ||
166 | */ | ||
167 | 205 | ||
168 | struct irq_pin_list { | 206 | cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node); |
169 | int apic, pin; | 207 | printk(KERN_DEBUG " alloc irq_cfg on cpu %d node %d\n", cpu, node); |
170 | struct irq_pin_list *next; | ||
171 | }; | ||
172 | 208 | ||
173 | static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE]; | 209 | return cfg; |
174 | static struct irq_pin_list *irq_2_pin_ptr; | 210 | } |
175 | 211 | ||
176 | static void __init irq_2_pin_init(void) | 212 | void arch_init_chip_data(struct irq_desc *desc, int cpu) |
177 | { | 213 | { |
178 | struct irq_pin_list *pin = irq_2_pin_head; | 214 | struct irq_cfg *cfg; |
179 | int i; | ||
180 | |||
181 | for (i = 1; i < PIN_MAP_SIZE; i++) | ||
182 | pin[i-1].next = &pin[i]; | ||
183 | 215 | ||
184 | irq_2_pin_ptr = &pin[0]; | 216 | cfg = desc->chip_data; |
217 | if (!cfg) { | ||
218 | desc->chip_data = get_one_free_irq_cfg(cpu); | ||
219 | if (!desc->chip_data) { | ||
220 | printk(KERN_ERR "can not alloc irq_cfg\n"); | ||
221 | BUG_ON(1); | ||
222 | } | ||
223 | } | ||
185 | } | 224 | } |
186 | 225 | ||
187 | static struct irq_pin_list *get_one_free_irq_2_pin(void) | 226 | #else |
227 | static struct irq_cfg *irq_cfg(unsigned int irq) | ||
188 | { | 228 | { |
189 | struct irq_pin_list *pin = irq_2_pin_ptr; | 229 | return irq < nr_irqs ? irq_cfgx + irq : NULL; |
230 | } | ||
190 | 231 | ||
191 | if (!pin) | 232 | #endif |
192 | panic("can not get more irq_2_pin\n"); | ||
193 | 233 | ||
194 | irq_2_pin_ptr = pin->next; | 234 | static inline void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask) |
195 | pin->next = NULL; | 235 | { |
196 | return pin; | ||
197 | } | 236 | } |
198 | 237 | ||
199 | struct io_apic { | 238 | struct io_apic { |
@@ -237,11 +276,10 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned | |||
237 | writel(value, &io_apic->data); | 276 | writel(value, &io_apic->data); |
238 | } | 277 | } |
239 | 278 | ||
240 | static bool io_apic_level_ack_pending(unsigned int irq) | 279 | static bool io_apic_level_ack_pending(struct irq_cfg *cfg) |
241 | { | 280 | { |
242 | struct irq_pin_list *entry; | 281 | struct irq_pin_list *entry; |
243 | unsigned long flags; | 282 | unsigned long flags; |
244 | struct irq_cfg *cfg = irq_cfg(irq); | ||
245 | 283 | ||
246 | spin_lock_irqsave(&ioapic_lock, flags); | 284 | spin_lock_irqsave(&ioapic_lock, flags); |
247 | entry = cfg->irq_2_pin; | 285 | entry = cfg->irq_2_pin; |
@@ -323,13 +361,12 @@ static void ioapic_mask_entry(int apic, int pin) | |||
323 | } | 361 | } |
324 | 362 | ||
325 | #ifdef CONFIG_SMP | 363 | #ifdef CONFIG_SMP |
326 | static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) | 364 | static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg) |
327 | { | 365 | { |
328 | int apic, pin; | 366 | int apic, pin; |
329 | struct irq_cfg *cfg; | ||
330 | struct irq_pin_list *entry; | 367 | struct irq_pin_list *entry; |
368 | u8 vector = cfg->vector; | ||
331 | 369 | ||
332 | cfg = irq_cfg(irq); | ||
333 | entry = cfg->irq_2_pin; | 370 | entry = cfg->irq_2_pin; |
334 | for (;;) { | 371 | for (;;) { |
335 | unsigned int reg; | 372 | unsigned int reg; |
@@ -359,24 +396,27 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) | |||
359 | } | 396 | } |
360 | } | 397 | } |
361 | 398 | ||
362 | static int assign_irq_vector(int irq, cpumask_t mask); | 399 | static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask); |
363 | 400 | ||
364 | static void set_ioapic_affinity_irq(unsigned int irq, | 401 | static void set_ioapic_affinity_irq_desc(struct irq_desc *desc, |
365 | const struct cpumask *mask) | 402 | const struct cpumask *mask) |
366 | { | 403 | { |
367 | struct irq_cfg *cfg; | 404 | struct irq_cfg *cfg; |
368 | unsigned long flags; | 405 | unsigned long flags; |
369 | unsigned int dest; | 406 | unsigned int dest; |
370 | cpumask_t tmp; | 407 | cpumask_t tmp; |
371 | struct irq_desc *desc; | 408 | unsigned int irq; |
372 | 409 | ||
373 | if (!cpumask_intersects(mask, cpu_online_mask)) | 410 | if (!cpumask_intersects(mask, cpu_online_mask)) |
374 | return; | 411 | return; |
375 | 412 | ||
376 | cfg = irq_cfg(irq); | 413 | irq = desc->irq; |
377 | if (assign_irq_vector(irq, *mask)) | 414 | cfg = desc->chip_data; |
415 | if (assign_irq_vector(irq, cfg, *mask)) | ||
378 | return; | 416 | return; |
379 | 417 | ||
418 | set_extra_move_desc(desc, *mask); | ||
419 | |||
380 | cpumask_and(&tmp, &cfg->domain, mask); | 420 | cpumask_and(&tmp, &cfg->domain, mask); |
381 | dest = cpu_mask_to_apicid(tmp); | 421 | dest = cpu_mask_to_apicid(tmp); |
382 | /* | 422 | /* |
@@ -384,12 +424,21 @@ static void set_ioapic_affinity_irq(unsigned int irq, | |||
384 | */ | 424 | */ |
385 | dest = SET_APIC_LOGICAL_ID(dest); | 425 | dest = SET_APIC_LOGICAL_ID(dest); |
386 | 426 | ||
387 | desc = irq_to_desc(irq); | ||
388 | spin_lock_irqsave(&ioapic_lock, flags); | 427 | spin_lock_irqsave(&ioapic_lock, flags); |
389 | __target_IO_APIC_irq(irq, dest, cfg->vector); | 428 | __target_IO_APIC_irq(irq, dest, cfg); |
390 | cpumask_copy(&desc->affinity, mask); | 429 | cpumask_copy(&desc->affinity, mask); |
391 | spin_unlock_irqrestore(&ioapic_lock, flags); | 430 | spin_unlock_irqrestore(&ioapic_lock, flags); |
392 | } | 431 | } |
432 | |||
433 | static void set_ioapic_affinity_irq(unsigned int irq, | ||
434 | const struct cpumask *mask) | ||
435 | { | ||
436 | struct irq_desc *desc; | ||
437 | |||
438 | desc = irq_to_desc(irq); | ||
439 | |||
440 | set_ioapic_affinity_irq_desc(desc, mask); | ||
441 | } | ||
393 | #endif /* CONFIG_SMP */ | 442 | #endif /* CONFIG_SMP */ |
394 | 443 | ||
395 | /* | 444 | /* |
@@ -397,16 +446,18 @@ static void set_ioapic_affinity_irq(unsigned int irq, | |||
397 | * shared ISA-space IRQs, so we have to support them. We are super | 446 | * shared ISA-space IRQs, so we have to support them. We are super |
398 | * fast in the common case, and fast for shared ISA-space IRQs. | 447 | * fast in the common case, and fast for shared ISA-space IRQs. |
399 | */ | 448 | */ |
400 | static void add_pin_to_irq(unsigned int irq, int apic, int pin) | 449 | static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin) |
401 | { | 450 | { |
402 | struct irq_cfg *cfg; | ||
403 | struct irq_pin_list *entry; | 451 | struct irq_pin_list *entry; |
404 | 452 | ||
405 | /* first time to refer irq_cfg, so with new */ | ||
406 | cfg = irq_cfg_alloc(irq); | ||
407 | entry = cfg->irq_2_pin; | 453 | entry = cfg->irq_2_pin; |
408 | if (!entry) { | 454 | if (!entry) { |
409 | entry = get_one_free_irq_2_pin(); | 455 | entry = get_one_free_irq_2_pin(cpu); |
456 | if (!entry) { | ||
457 | printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n", | ||
458 | apic, pin); | ||
459 | return; | ||
460 | } | ||
410 | cfg->irq_2_pin = entry; | 461 | cfg->irq_2_pin = entry; |
411 | entry->apic = apic; | 462 | entry->apic = apic; |
412 | entry->pin = pin; | 463 | entry->pin = pin; |
@@ -421,7 +472,7 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) | |||
421 | entry = entry->next; | 472 | entry = entry->next; |
422 | } | 473 | } |
423 | 474 | ||
424 | entry->next = get_one_free_irq_2_pin(); | 475 | entry->next = get_one_free_irq_2_pin(cpu); |
425 | entry = entry->next; | 476 | entry = entry->next; |
426 | entry->apic = apic; | 477 | entry->apic = apic; |
427 | entry->pin = pin; | 478 | entry->pin = pin; |
@@ -430,11 +481,10 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) | |||
430 | /* | 481 | /* |
431 | * Reroute an IRQ to a different pin. | 482 | * Reroute an IRQ to a different pin. |
432 | */ | 483 | */ |
433 | static void __init replace_pin_at_irq(unsigned int irq, | 484 | static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu, |
434 | int oldapic, int oldpin, | 485 | int oldapic, int oldpin, |
435 | int newapic, int newpin) | 486 | int newapic, int newpin) |
436 | { | 487 | { |
437 | struct irq_cfg *cfg = irq_cfg(irq); | ||
438 | struct irq_pin_list *entry = cfg->irq_2_pin; | 488 | struct irq_pin_list *entry = cfg->irq_2_pin; |
439 | int replaced = 0; | 489 | int replaced = 0; |
440 | 490 | ||
@@ -451,18 +501,16 @@ static void __init replace_pin_at_irq(unsigned int irq, | |||
451 | 501 | ||
452 | /* why? call replace before add? */ | 502 | /* why? call replace before add? */ |
453 | if (!replaced) | 503 | if (!replaced) |
454 | add_pin_to_irq(irq, newapic, newpin); | 504 | add_pin_to_irq_cpu(cfg, cpu, newapic, newpin); |
455 | } | 505 | } |
456 | 506 | ||
457 | static inline void io_apic_modify_irq(unsigned int irq, | 507 | static inline void io_apic_modify_irq(struct irq_cfg *cfg, |
458 | int mask_and, int mask_or, | 508 | int mask_and, int mask_or, |
459 | void (*final)(struct irq_pin_list *entry)) | 509 | void (*final)(struct irq_pin_list *entry)) |
460 | { | 510 | { |
461 | int pin; | 511 | int pin; |
462 | struct irq_cfg *cfg; | ||
463 | struct irq_pin_list *entry; | 512 | struct irq_pin_list *entry; |
464 | 513 | ||
465 | cfg = irq_cfg(irq); | ||
466 | for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) { | 514 | for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) { |
467 | unsigned int reg; | 515 | unsigned int reg; |
468 | pin = entry->pin; | 516 | pin = entry->pin; |
@@ -475,9 +523,9 @@ static inline void io_apic_modify_irq(unsigned int irq, | |||
475 | } | 523 | } |
476 | } | 524 | } |
477 | 525 | ||
478 | static void __unmask_IO_APIC_irq(unsigned int irq) | 526 | static void __unmask_IO_APIC_irq(struct irq_cfg *cfg) |
479 | { | 527 | { |
480 | io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL); | 528 | io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL); |
481 | } | 529 | } |
482 | 530 | ||
483 | #ifdef CONFIG_X86_64 | 531 | #ifdef CONFIG_X86_64 |
@@ -492,47 +540,64 @@ void io_apic_sync(struct irq_pin_list *entry) | |||
492 | readl(&io_apic->data); | 540 | readl(&io_apic->data); |
493 | } | 541 | } |
494 | 542 | ||
495 | static void __mask_IO_APIC_irq(unsigned int irq) | 543 | static void __mask_IO_APIC_irq(struct irq_cfg *cfg) |
496 | { | 544 | { |
497 | io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); | 545 | io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); |
498 | } | 546 | } |
499 | #else /* CONFIG_X86_32 */ | 547 | #else /* CONFIG_X86_32 */ |
500 | static void __mask_IO_APIC_irq(unsigned int irq) | 548 | static void __mask_IO_APIC_irq(struct irq_cfg *cfg) |
501 | { | 549 | { |
502 | io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, NULL); | 550 | io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, NULL); |
503 | } | 551 | } |
504 | 552 | ||
505 | static void __mask_and_edge_IO_APIC_irq(unsigned int irq) | 553 | static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg) |
506 | { | 554 | { |
507 | io_apic_modify_irq(irq, ~IO_APIC_REDIR_LEVEL_TRIGGER, | 555 | io_apic_modify_irq(cfg, ~IO_APIC_REDIR_LEVEL_TRIGGER, |
508 | IO_APIC_REDIR_MASKED, NULL); | 556 | IO_APIC_REDIR_MASKED, NULL); |
509 | } | 557 | } |
510 | 558 | ||
511 | static void __unmask_and_level_IO_APIC_irq(unsigned int irq) | 559 | static void __unmask_and_level_IO_APIC_irq(struct irq_cfg *cfg) |
512 | { | 560 | { |
513 | io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, | 561 | io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, |
514 | IO_APIC_REDIR_LEVEL_TRIGGER, NULL); | 562 | IO_APIC_REDIR_LEVEL_TRIGGER, NULL); |
515 | } | 563 | } |
516 | #endif /* CONFIG_X86_32 */ | 564 | #endif /* CONFIG_X86_32 */ |
517 | 565 | ||
518 | static void mask_IO_APIC_irq (unsigned int irq) | 566 | static void mask_IO_APIC_irq_desc(struct irq_desc *desc) |
519 | { | 567 | { |
568 | struct irq_cfg *cfg = desc->chip_data; | ||
520 | unsigned long flags; | 569 | unsigned long flags; |
521 | 570 | ||
571 | BUG_ON(!cfg); | ||
572 | |||
522 | spin_lock_irqsave(&ioapic_lock, flags); | 573 | spin_lock_irqsave(&ioapic_lock, flags); |
523 | __mask_IO_APIC_irq(irq); | 574 | __mask_IO_APIC_irq(cfg); |
524 | spin_unlock_irqrestore(&ioapic_lock, flags); | 575 | spin_unlock_irqrestore(&ioapic_lock, flags); |
525 | } | 576 | } |
526 | 577 | ||
527 | static void unmask_IO_APIC_irq (unsigned int irq) | 578 | static void unmask_IO_APIC_irq_desc(struct irq_desc *desc) |
528 | { | 579 | { |
580 | struct irq_cfg *cfg = desc->chip_data; | ||
529 | unsigned long flags; | 581 | unsigned long flags; |
530 | 582 | ||
531 | spin_lock_irqsave(&ioapic_lock, flags); | 583 | spin_lock_irqsave(&ioapic_lock, flags); |
532 | __unmask_IO_APIC_irq(irq); | 584 | __unmask_IO_APIC_irq(cfg); |
533 | spin_unlock_irqrestore(&ioapic_lock, flags); | 585 | spin_unlock_irqrestore(&ioapic_lock, flags); |
534 | } | 586 | } |
535 | 587 | ||
588 | static void mask_IO_APIC_irq(unsigned int irq) | ||
589 | { | ||
590 | struct irq_desc *desc = irq_to_desc(irq); | ||
591 | |||
592 | mask_IO_APIC_irq_desc(desc); | ||
593 | } | ||
594 | static void unmask_IO_APIC_irq(unsigned int irq) | ||
595 | { | ||
596 | struct irq_desc *desc = irq_to_desc(irq); | ||
597 | |||
598 | unmask_IO_APIC_irq_desc(desc); | ||
599 | } | ||
600 | |||
536 | static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) | 601 | static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) |
537 | { | 602 | { |
538 | struct IO_APIC_route_entry entry; | 603 | struct IO_APIC_route_entry entry; |
@@ -809,7 +874,7 @@ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); | |||
809 | */ | 874 | */ |
810 | static int EISA_ELCR(unsigned int irq) | 875 | static int EISA_ELCR(unsigned int irq) |
811 | { | 876 | { |
812 | if (irq < 16) { | 877 | if (irq < NR_IRQS_LEGACY) { |
813 | unsigned int port = 0x4d0 + (irq >> 3); | 878 | unsigned int port = 0x4d0 + (irq >> 3); |
814 | return (inb(port) >> (irq & 7)) & 1; | 879 | return (inb(port) >> (irq & 7)) & 1; |
815 | } | 880 | } |
@@ -1034,7 +1099,7 @@ void unlock_vector_lock(void) | |||
1034 | spin_unlock(&vector_lock); | 1099 | spin_unlock(&vector_lock); |
1035 | } | 1100 | } |
1036 | 1101 | ||
1037 | static int __assign_irq_vector(int irq, cpumask_t mask) | 1102 | static int __assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask) |
1038 | { | 1103 | { |
1039 | /* | 1104 | /* |
1040 | * NOTE! The local APIC isn't very good at handling | 1105 | * NOTE! The local APIC isn't very good at handling |
@@ -1050,16 +1115,13 @@ static int __assign_irq_vector(int irq, cpumask_t mask) | |||
1050 | static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; | 1115 | static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; |
1051 | unsigned int old_vector; | 1116 | unsigned int old_vector; |
1052 | int cpu; | 1117 | int cpu; |
1053 | struct irq_cfg *cfg; | ||
1054 | 1118 | ||
1055 | cfg = irq_cfg(irq); | 1119 | if ((cfg->move_in_progress) || cfg->move_cleanup_count) |
1120 | return -EBUSY; | ||
1056 | 1121 | ||
1057 | /* Only try and allocate irqs on cpus that are present */ | 1122 | /* Only try and allocate irqs on cpus that are present */ |
1058 | cpus_and(mask, mask, cpu_online_map); | 1123 | cpus_and(mask, mask, cpu_online_map); |
1059 | 1124 | ||
1060 | if ((cfg->move_in_progress) || cfg->move_cleanup_count) | ||
1061 | return -EBUSY; | ||
1062 | |||
1063 | old_vector = cfg->vector; | 1125 | old_vector = cfg->vector; |
1064 | if (old_vector) { | 1126 | if (old_vector) { |
1065 | cpumask_t tmp; | 1127 | cpumask_t tmp; |
@@ -1113,24 +1175,22 @@ next: | |||
1113 | return -ENOSPC; | 1175 | return -ENOSPC; |
1114 | } | 1176 | } |
1115 | 1177 | ||
1116 | static int assign_irq_vector(int irq, cpumask_t mask) | 1178 | static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask) |
1117 | { | 1179 | { |
1118 | int err; | 1180 | int err; |
1119 | unsigned long flags; | 1181 | unsigned long flags; |
1120 | 1182 | ||
1121 | spin_lock_irqsave(&vector_lock, flags); | 1183 | spin_lock_irqsave(&vector_lock, flags); |
1122 | err = __assign_irq_vector(irq, mask); | 1184 | err = __assign_irq_vector(irq, cfg, mask); |
1123 | spin_unlock_irqrestore(&vector_lock, flags); | 1185 | spin_unlock_irqrestore(&vector_lock, flags); |
1124 | return err; | 1186 | return err; |
1125 | } | 1187 | } |
1126 | 1188 | ||
1127 | static void __clear_irq_vector(int irq) | 1189 | static void __clear_irq_vector(int irq, struct irq_cfg *cfg) |
1128 | { | 1190 | { |
1129 | struct irq_cfg *cfg; | ||
1130 | cpumask_t mask; | 1191 | cpumask_t mask; |
1131 | int cpu, vector; | 1192 | int cpu, vector; |
1132 | 1193 | ||
1133 | cfg = irq_cfg(irq); | ||
1134 | BUG_ON(!cfg->vector); | 1194 | BUG_ON(!cfg->vector); |
1135 | 1195 | ||
1136 | vector = cfg->vector; | 1196 | vector = cfg->vector; |
@@ -1162,9 +1222,13 @@ void __setup_vector_irq(int cpu) | |||
1162 | /* This function must be called with vector_lock held */ | 1222 | /* This function must be called with vector_lock held */ |
1163 | int irq, vector; | 1223 | int irq, vector; |
1164 | struct irq_cfg *cfg; | 1224 | struct irq_cfg *cfg; |
1225 | struct irq_desc *desc; | ||
1165 | 1226 | ||
1166 | /* Mark the inuse vectors */ | 1227 | /* Mark the inuse vectors */ |
1167 | for_each_irq_cfg(irq, cfg) { | 1228 | for_each_irq_desc(irq, desc) { |
1229 | if (!desc) | ||
1230 | continue; | ||
1231 | cfg = desc->chip_data; | ||
1168 | if (!cpu_isset(cpu, cfg->domain)) | 1232 | if (!cpu_isset(cpu, cfg->domain)) |
1169 | continue; | 1233 | continue; |
1170 | vector = cfg->vector; | 1234 | vector = cfg->vector; |
@@ -1215,11 +1279,8 @@ static inline int IO_APIC_irq_trigger(int irq) | |||
1215 | } | 1279 | } |
1216 | #endif | 1280 | #endif |
1217 | 1281 | ||
1218 | static void ioapic_register_intr(int irq, unsigned long trigger) | 1282 | static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger) |
1219 | { | 1283 | { |
1220 | struct irq_desc *desc; | ||
1221 | |||
1222 | desc = irq_to_desc(irq); | ||
1223 | 1284 | ||
1224 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || | 1285 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || |
1225 | trigger == IOAPIC_LEVEL) | 1286 | trigger == IOAPIC_LEVEL) |
@@ -1311,7 +1372,7 @@ static int setup_ioapic_entry(int apic, int irq, | |||
1311 | return 0; | 1372 | return 0; |
1312 | } | 1373 | } |
1313 | 1374 | ||
1314 | static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, | 1375 | static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_desc *desc, |
1315 | int trigger, int polarity) | 1376 | int trigger, int polarity) |
1316 | { | 1377 | { |
1317 | struct irq_cfg *cfg; | 1378 | struct irq_cfg *cfg; |
@@ -1321,10 +1382,10 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, | |||
1321 | if (!IO_APIC_IRQ(irq)) | 1382 | if (!IO_APIC_IRQ(irq)) |
1322 | return; | 1383 | return; |
1323 | 1384 | ||
1324 | cfg = irq_cfg(irq); | 1385 | cfg = desc->chip_data; |
1325 | 1386 | ||
1326 | mask = TARGET_CPUS; | 1387 | mask = TARGET_CPUS; |
1327 | if (assign_irq_vector(irq, mask)) | 1388 | if (assign_irq_vector(irq, cfg, mask)) |
1328 | return; | 1389 | return; |
1329 | 1390 | ||
1330 | cpus_and(mask, cfg->domain, mask); | 1391 | cpus_and(mask, cfg->domain, mask); |
@@ -1341,12 +1402,12 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, | |||
1341 | cfg->vector)) { | 1402 | cfg->vector)) { |
1342 | printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", | 1403 | printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", |
1343 | mp_ioapics[apic].mp_apicid, pin); | 1404 | mp_ioapics[apic].mp_apicid, pin); |
1344 | __clear_irq_vector(irq); | 1405 | __clear_irq_vector(irq, cfg); |
1345 | return; | 1406 | return; |
1346 | } | 1407 | } |
1347 | 1408 | ||
1348 | ioapic_register_intr(irq, trigger); | 1409 | ioapic_register_intr(irq, desc, trigger); |
1349 | if (irq < 16) | 1410 | if (irq < NR_IRQS_LEGACY) |
1350 | disable_8259A_irq(irq); | 1411 | disable_8259A_irq(irq); |
1351 | 1412 | ||
1352 | ioapic_write_entry(apic, pin, entry); | 1413 | ioapic_write_entry(apic, pin, entry); |
@@ -1356,6 +1417,9 @@ static void __init setup_IO_APIC_irqs(void) | |||
1356 | { | 1417 | { |
1357 | int apic, pin, idx, irq; | 1418 | int apic, pin, idx, irq; |
1358 | int notcon = 0; | 1419 | int notcon = 0; |
1420 | struct irq_desc *desc; | ||
1421 | struct irq_cfg *cfg; | ||
1422 | int cpu = boot_cpu_id; | ||
1359 | 1423 | ||
1360 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | 1424 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); |
1361 | 1425 | ||
@@ -1387,9 +1451,15 @@ static void __init setup_IO_APIC_irqs(void) | |||
1387 | if (multi_timer_check(apic, irq)) | 1451 | if (multi_timer_check(apic, irq)) |
1388 | continue; | 1452 | continue; |
1389 | #endif | 1453 | #endif |
1390 | add_pin_to_irq(irq, apic, pin); | 1454 | desc = irq_to_desc_alloc_cpu(irq, cpu); |
1455 | if (!desc) { | ||
1456 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
1457 | continue; | ||
1458 | } | ||
1459 | cfg = desc->chip_data; | ||
1460 | add_pin_to_irq_cpu(cfg, cpu, apic, pin); | ||
1391 | 1461 | ||
1392 | setup_IO_APIC_irq(apic, pin, irq, | 1462 | setup_IO_APIC_irq(apic, pin, irq, desc, |
1393 | irq_trigger(idx), irq_polarity(idx)); | 1463 | irq_trigger(idx), irq_polarity(idx)); |
1394 | } | 1464 | } |
1395 | } | 1465 | } |
@@ -1448,6 +1518,7 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
1448 | union IO_APIC_reg_03 reg_03; | 1518 | union IO_APIC_reg_03 reg_03; |
1449 | unsigned long flags; | 1519 | unsigned long flags; |
1450 | struct irq_cfg *cfg; | 1520 | struct irq_cfg *cfg; |
1521 | struct irq_desc *desc; | ||
1451 | unsigned int irq; | 1522 | unsigned int irq; |
1452 | 1523 | ||
1453 | if (apic_verbosity == APIC_QUIET) | 1524 | if (apic_verbosity == APIC_QUIET) |
@@ -1537,8 +1608,13 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
1537 | } | 1608 | } |
1538 | } | 1609 | } |
1539 | printk(KERN_DEBUG "IRQ to pin mappings:\n"); | 1610 | printk(KERN_DEBUG "IRQ to pin mappings:\n"); |
1540 | for_each_irq_cfg(irq, cfg) { | 1611 | for_each_irq_desc(irq, desc) { |
1541 | struct irq_pin_list *entry = cfg->irq_2_pin; | 1612 | struct irq_pin_list *entry; |
1613 | |||
1614 | if (!desc) | ||
1615 | continue; | ||
1616 | cfg = desc->chip_data; | ||
1617 | entry = cfg->irq_2_pin; | ||
1542 | if (!entry) | 1618 | if (!entry) |
1543 | continue; | 1619 | continue; |
1544 | printk(KERN_DEBUG "IRQ%d ", irq); | 1620 | printk(KERN_DEBUG "IRQ%d ", irq); |
@@ -2022,14 +2098,16 @@ static unsigned int startup_ioapic_irq(unsigned int irq) | |||
2022 | { | 2098 | { |
2023 | int was_pending = 0; | 2099 | int was_pending = 0; |
2024 | unsigned long flags; | 2100 | unsigned long flags; |
2101 | struct irq_cfg *cfg; | ||
2025 | 2102 | ||
2026 | spin_lock_irqsave(&ioapic_lock, flags); | 2103 | spin_lock_irqsave(&ioapic_lock, flags); |
2027 | if (irq < 16) { | 2104 | if (irq < NR_IRQS_LEGACY) { |
2028 | disable_8259A_irq(irq); | 2105 | disable_8259A_irq(irq); |
2029 | if (i8259A_irq_pending(irq)) | 2106 | if (i8259A_irq_pending(irq)) |
2030 | was_pending = 1; | 2107 | was_pending = 1; |
2031 | } | 2108 | } |
2032 | __unmask_IO_APIC_irq(irq); | 2109 | cfg = irq_cfg(irq); |
2110 | __unmask_IO_APIC_irq(cfg); | ||
2033 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2111 | spin_unlock_irqrestore(&ioapic_lock, flags); |
2034 | 2112 | ||
2035 | return was_pending; | 2113 | return was_pending; |
@@ -2092,35 +2170,37 @@ static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration); | |||
2092 | * as simple as edge triggered migration and we can do the irq migration | 2170 | * as simple as edge triggered migration and we can do the irq migration |
2093 | * with a simple atomic update to IO-APIC RTE. | 2171 | * with a simple atomic update to IO-APIC RTE. |
2094 | */ | 2172 | */ |
2095 | static void migrate_ioapic_irq(int irq, cpumask_t mask) | 2173 | static void migrate_ioapic_irq_desc(struct irq_desc *desc, cpumask_t mask) |
2096 | { | 2174 | { |
2097 | struct irq_cfg *cfg; | 2175 | struct irq_cfg *cfg; |
2098 | struct irq_desc *desc; | ||
2099 | cpumask_t tmp, cleanup_mask; | 2176 | cpumask_t tmp, cleanup_mask; |
2100 | struct irte irte; | 2177 | struct irte irte; |
2101 | int modify_ioapic_rte; | 2178 | int modify_ioapic_rte; |
2102 | unsigned int dest; | 2179 | unsigned int dest; |
2103 | unsigned long flags; | 2180 | unsigned long flags; |
2181 | unsigned int irq; | ||
2104 | 2182 | ||
2105 | cpus_and(tmp, mask, cpu_online_map); | 2183 | cpus_and(tmp, mask, cpu_online_map); |
2106 | if (cpus_empty(tmp)) | 2184 | if (cpus_empty(tmp)) |
2107 | return; | 2185 | return; |
2108 | 2186 | ||
2187 | irq = desc->irq; | ||
2109 | if (get_irte(irq, &irte)) | 2188 | if (get_irte(irq, &irte)) |
2110 | return; | 2189 | return; |
2111 | 2190 | ||
2112 | if (assign_irq_vector(irq, mask)) | 2191 | cfg = desc->chip_data; |
2192 | if (assign_irq_vector(irq, cfg, mask)) | ||
2113 | return; | 2193 | return; |
2114 | 2194 | ||
2115 | cfg = irq_cfg(irq); | 2195 | set_extra_move_desc(desc, mask); |
2196 | |||
2116 | cpus_and(tmp, cfg->domain, mask); | 2197 | cpus_and(tmp, cfg->domain, mask); |
2117 | dest = cpu_mask_to_apicid(tmp); | 2198 | dest = cpu_mask_to_apicid(tmp); |
2118 | 2199 | ||
2119 | desc = irq_to_desc(irq); | ||
2120 | modify_ioapic_rte = desc->status & IRQ_LEVEL; | 2200 | modify_ioapic_rte = desc->status & IRQ_LEVEL; |
2121 | if (modify_ioapic_rte) { | 2201 | if (modify_ioapic_rte) { |
2122 | spin_lock_irqsave(&ioapic_lock, flags); | 2202 | spin_lock_irqsave(&ioapic_lock, flags); |
2123 | __target_IO_APIC_irq(irq, dest, cfg->vector); | 2203 | __target_IO_APIC_irq(irq, dest, cfg); |
2124 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2204 | spin_unlock_irqrestore(&ioapic_lock, flags); |
2125 | } | 2205 | } |
2126 | 2206 | ||
@@ -2142,14 +2222,14 @@ static void migrate_ioapic_irq(int irq, cpumask_t mask) | |||
2142 | desc->affinity = mask; | 2222 | desc->affinity = mask; |
2143 | } | 2223 | } |
2144 | 2224 | ||
2145 | static int migrate_irq_remapped_level(int irq) | 2225 | static int migrate_irq_remapped_level_desc(struct irq_desc *desc) |
2146 | { | 2226 | { |
2147 | int ret = -1; | 2227 | int ret = -1; |
2148 | struct irq_desc *desc = irq_to_desc(irq); | 2228 | struct irq_cfg *cfg = desc->chip_data; |
2149 | 2229 | ||
2150 | mask_IO_APIC_irq(irq); | 2230 | mask_IO_APIC_irq_desc(desc); |
2151 | 2231 | ||
2152 | if (io_apic_level_ack_pending(irq)) { | 2232 | if (io_apic_level_ack_pending(cfg)) { |
2153 | /* | 2233 | /* |
2154 | * Interrupt in progress. Migrating irq now will change the | 2234 | * Interrupt in progress. Migrating irq now will change the |
2155 | * vector information in the IO-APIC RTE and that will confuse | 2235 | * vector information in the IO-APIC RTE and that will confuse |
@@ -2161,14 +2241,15 @@ static int migrate_irq_remapped_level(int irq) | |||
2161 | } | 2241 | } |
2162 | 2242 | ||
2163 | /* everthing is clear. we have right of way */ | 2243 | /* everthing is clear. we have right of way */ |
2164 | migrate_ioapic_irq(irq, desc->pending_mask); | 2244 | migrate_ioapic_irq_desc(desc, desc->pending_mask); |
2165 | 2245 | ||
2166 | ret = 0; | 2246 | ret = 0; |
2167 | desc->status &= ~IRQ_MOVE_PENDING; | 2247 | desc->status &= ~IRQ_MOVE_PENDING; |
2168 | cpus_clear(desc->pending_mask); | 2248 | cpus_clear(desc->pending_mask); |
2169 | 2249 | ||
2170 | unmask: | 2250 | unmask: |
2171 | unmask_IO_APIC_irq(irq); | 2251 | unmask_IO_APIC_irq_desc(desc); |
2252 | |||
2172 | return ret; | 2253 | return ret; |
2173 | } | 2254 | } |
2174 | 2255 | ||
@@ -2178,6 +2259,9 @@ static void ir_irq_migration(struct work_struct *work) | |||
2178 | struct irq_desc *desc; | 2259 | struct irq_desc *desc; |
2179 | 2260 | ||
2180 | for_each_irq_desc(irq, desc) { | 2261 | for_each_irq_desc(irq, desc) { |
2262 | if (!desc) | ||
2263 | continue; | ||
2264 | |||
2181 | if (desc->status & IRQ_MOVE_PENDING) { | 2265 | if (desc->status & IRQ_MOVE_PENDING) { |
2182 | unsigned long flags; | 2266 | unsigned long flags; |
2183 | 2267 | ||
@@ -2198,19 +2282,24 @@ static void ir_irq_migration(struct work_struct *work) | |||
2198 | /* | 2282 | /* |
2199 | * Migrates the IRQ destination in the process context. | 2283 | * Migrates the IRQ destination in the process context. |
2200 | */ | 2284 | */ |
2201 | static void set_ir_ioapic_affinity_irq(unsigned int irq, | 2285 | static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, |
2202 | const struct cpumask *mask) | 2286 | const struct cpumask *mask) |
2203 | { | 2287 | { |
2204 | struct irq_desc *desc = irq_to_desc(irq); | ||
2205 | |||
2206 | if (desc->status & IRQ_LEVEL) { | 2288 | if (desc->status & IRQ_LEVEL) { |
2207 | desc->status |= IRQ_MOVE_PENDING; | 2289 | desc->status |= IRQ_MOVE_PENDING; |
2208 | cpumask_copy(&desc->pending_mask, mask); | 2290 | cpumask_copy(&desc->pending_mask, mask); |
2209 | migrate_irq_remapped_level(irq); | 2291 | migrate_irq_remapped_level_desc(desc); |
2210 | return; | 2292 | return; |
2211 | } | 2293 | } |
2212 | 2294 | ||
2213 | migrate_ioapic_irq(irq, *mask); | 2295 | migrate_ioapic_irq_desc(desc, mask); |
2296 | } | ||
2297 | static void set_ir_ioapic_affinity_irq(unsigned int irq, | ||
2298 | const struct cpumask *mask) | ||
2299 | { | ||
2300 | struct irq_desc *desc = irq_to_desc(irq); | ||
2301 | |||
2302 | set_ir_ioapic_affinity_irq_desc(desc, mask); | ||
2214 | } | 2303 | } |
2215 | #endif | 2304 | #endif |
2216 | 2305 | ||
@@ -2230,6 +2319,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) | |||
2230 | struct irq_cfg *cfg; | 2319 | struct irq_cfg *cfg; |
2231 | irq = __get_cpu_var(vector_irq)[vector]; | 2320 | irq = __get_cpu_var(vector_irq)[vector]; |
2232 | 2321 | ||
2322 | if (irq == -1) | ||
2323 | continue; | ||
2324 | |||
2233 | desc = irq_to_desc(irq); | 2325 | desc = irq_to_desc(irq); |
2234 | if (!desc) | 2326 | if (!desc) |
2235 | continue; | 2327 | continue; |
@@ -2251,9 +2343,10 @@ unlock: | |||
2251 | irq_exit(); | 2343 | irq_exit(); |
2252 | } | 2344 | } |
2253 | 2345 | ||
2254 | static void irq_complete_move(unsigned int irq) | 2346 | static void irq_complete_move(struct irq_desc **descp) |
2255 | { | 2347 | { |
2256 | struct irq_cfg *cfg = irq_cfg(irq); | 2348 | struct irq_desc *desc = *descp; |
2349 | struct irq_cfg *cfg = desc->chip_data; | ||
2257 | unsigned vector, me; | 2350 | unsigned vector, me; |
2258 | 2351 | ||
2259 | if (likely(!cfg->move_in_progress)) | 2352 | if (likely(!cfg->move_in_progress)) |
@@ -2271,8 +2364,9 @@ static void irq_complete_move(unsigned int irq) | |||
2271 | } | 2364 | } |
2272 | } | 2365 | } |
2273 | #else | 2366 | #else |
2274 | static inline void irq_complete_move(unsigned int irq) {} | 2367 | static inline void irq_complete_move(struct irq_desc **descp) {} |
2275 | #endif | 2368 | #endif |
2369 | |||
2276 | #ifdef CONFIG_INTR_REMAP | 2370 | #ifdef CONFIG_INTR_REMAP |
2277 | static void ack_x2apic_level(unsigned int irq) | 2371 | static void ack_x2apic_level(unsigned int irq) |
2278 | { | 2372 | { |
@@ -2283,11 +2377,14 @@ static void ack_x2apic_edge(unsigned int irq) | |||
2283 | { | 2377 | { |
2284 | ack_x2APIC_irq(); | 2378 | ack_x2APIC_irq(); |
2285 | } | 2379 | } |
2380 | |||
2286 | #endif | 2381 | #endif |
2287 | 2382 | ||
2288 | static void ack_apic_edge(unsigned int irq) | 2383 | static void ack_apic_edge(unsigned int irq) |
2289 | { | 2384 | { |
2290 | irq_complete_move(irq); | 2385 | struct irq_desc *desc = irq_to_desc(irq); |
2386 | |||
2387 | irq_complete_move(&desc); | ||
2291 | move_native_irq(irq); | 2388 | move_native_irq(irq); |
2292 | ack_APIC_irq(); | 2389 | ack_APIC_irq(); |
2293 | } | 2390 | } |
@@ -2296,18 +2393,21 @@ atomic_t irq_mis_count; | |||
2296 | 2393 | ||
2297 | static void ack_apic_level(unsigned int irq) | 2394 | static void ack_apic_level(unsigned int irq) |
2298 | { | 2395 | { |
2396 | struct irq_desc *desc = irq_to_desc(irq); | ||
2397 | |||
2299 | #ifdef CONFIG_X86_32 | 2398 | #ifdef CONFIG_X86_32 |
2300 | unsigned long v; | 2399 | unsigned long v; |
2301 | int i; | 2400 | int i; |
2302 | #endif | 2401 | #endif |
2402 | struct irq_cfg *cfg; | ||
2303 | int do_unmask_irq = 0; | 2403 | int do_unmask_irq = 0; |
2304 | 2404 | ||
2305 | irq_complete_move(irq); | 2405 | irq_complete_move(&desc); |
2306 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 2406 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
2307 | /* If we are moving the irq we need to mask it */ | 2407 | /* If we are moving the irq we need to mask it */ |
2308 | if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) { | 2408 | if (unlikely(desc->status & IRQ_MOVE_PENDING)) { |
2309 | do_unmask_irq = 1; | 2409 | do_unmask_irq = 1; |
2310 | mask_IO_APIC_irq(irq); | 2410 | mask_IO_APIC_irq_desc(desc); |
2311 | } | 2411 | } |
2312 | #endif | 2412 | #endif |
2313 | 2413 | ||
@@ -2331,7 +2431,8 @@ static void ack_apic_level(unsigned int irq) | |||
2331 | * operation to prevent an edge-triggered interrupt escaping meanwhile. | 2431 | * operation to prevent an edge-triggered interrupt escaping meanwhile. |
2332 | * The idea is from Manfred Spraul. --macro | 2432 | * The idea is from Manfred Spraul. --macro |
2333 | */ | 2433 | */ |
2334 | i = irq_cfg(irq)->vector; | 2434 | cfg = desc->chip_data; |
2435 | i = cfg->vector; | ||
2335 | 2436 | ||
2336 | v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); | 2437 | v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); |
2337 | #endif | 2438 | #endif |
@@ -2370,17 +2471,18 @@ static void ack_apic_level(unsigned int irq) | |||
2370 | * accurate and is causing problems then it is a hardware bug | 2471 | * accurate and is causing problems then it is a hardware bug |
2371 | * and you can go talk to the chipset vendor about it. | 2472 | * and you can go talk to the chipset vendor about it. |
2372 | */ | 2473 | */ |
2373 | if (!io_apic_level_ack_pending(irq)) | 2474 | cfg = desc->chip_data; |
2475 | if (!io_apic_level_ack_pending(cfg)) | ||
2374 | move_masked_irq(irq); | 2476 | move_masked_irq(irq); |
2375 | unmask_IO_APIC_irq(irq); | 2477 | unmask_IO_APIC_irq_desc(desc); |
2376 | } | 2478 | } |
2377 | 2479 | ||
2378 | #ifdef CONFIG_X86_32 | 2480 | #ifdef CONFIG_X86_32 |
2379 | if (!(v & (1 << (i & 0x1f)))) { | 2481 | if (!(v & (1 << (i & 0x1f)))) { |
2380 | atomic_inc(&irq_mis_count); | 2482 | atomic_inc(&irq_mis_count); |
2381 | spin_lock(&ioapic_lock); | 2483 | spin_lock(&ioapic_lock); |
2382 | __mask_and_edge_IO_APIC_irq(irq); | 2484 | __mask_and_edge_IO_APIC_irq(cfg); |
2383 | __unmask_and_level_IO_APIC_irq(irq); | 2485 | __unmask_and_level_IO_APIC_irq(cfg); |
2384 | spin_unlock(&ioapic_lock); | 2486 | spin_unlock(&ioapic_lock); |
2385 | } | 2487 | } |
2386 | #endif | 2488 | #endif |
@@ -2431,20 +2533,22 @@ static inline void init_IO_APIC_traps(void) | |||
2431 | * Also, we've got to be careful not to trash gate | 2533 | * Also, we've got to be careful not to trash gate |
2432 | * 0x80, because int 0x80 is hm, kind of importantish. ;) | 2534 | * 0x80, because int 0x80 is hm, kind of importantish. ;) |
2433 | */ | 2535 | */ |
2434 | for_each_irq_cfg(irq, cfg) { | 2536 | for_each_irq_desc(irq, desc) { |
2435 | if (IO_APIC_IRQ(irq) && !cfg->vector) { | 2537 | if (!desc) |
2538 | continue; | ||
2539 | |||
2540 | cfg = desc->chip_data; | ||
2541 | if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) { | ||
2436 | /* | 2542 | /* |
2437 | * Hmm.. We don't have an entry for this, | 2543 | * Hmm.. We don't have an entry for this, |
2438 | * so default to an old-fashioned 8259 | 2544 | * so default to an old-fashioned 8259 |
2439 | * interrupt if we can.. | 2545 | * interrupt if we can.. |
2440 | */ | 2546 | */ |
2441 | if (irq < 16) | 2547 | if (irq < NR_IRQS_LEGACY) |
2442 | make_8259A_irq(irq); | 2548 | make_8259A_irq(irq); |
2443 | else { | 2549 | else |
2444 | desc = irq_to_desc(irq); | ||
2445 | /* Strange. Oh, well.. */ | 2550 | /* Strange. Oh, well.. */ |
2446 | desc->chip = &no_irq_chip; | 2551 | desc->chip = &no_irq_chip; |
2447 | } | ||
2448 | } | 2552 | } |
2449 | } | 2553 | } |
2450 | } | 2554 | } |
@@ -2469,7 +2573,7 @@ static void unmask_lapic_irq(unsigned int irq) | |||
2469 | apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); | 2573 | apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); |
2470 | } | 2574 | } |
2471 | 2575 | ||
2472 | static void ack_lapic_irq (unsigned int irq) | 2576 | static void ack_lapic_irq(unsigned int irq) |
2473 | { | 2577 | { |
2474 | ack_APIC_irq(); | 2578 | ack_APIC_irq(); |
2475 | } | 2579 | } |
@@ -2481,11 +2585,8 @@ static struct irq_chip lapic_chip __read_mostly = { | |||
2481 | .ack = ack_lapic_irq, | 2585 | .ack = ack_lapic_irq, |
2482 | }; | 2586 | }; |
2483 | 2587 | ||
2484 | static void lapic_register_intr(int irq) | 2588 | static void lapic_register_intr(int irq, struct irq_desc *desc) |
2485 | { | 2589 | { |
2486 | struct irq_desc *desc; | ||
2487 | |||
2488 | desc = irq_to_desc(irq); | ||
2489 | desc->status &= ~IRQ_LEVEL; | 2590 | desc->status &= ~IRQ_LEVEL; |
2490 | set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, | 2591 | set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, |
2491 | "edge"); | 2592 | "edge"); |
@@ -2589,7 +2690,9 @@ int timer_through_8259 __initdata; | |||
2589 | */ | 2690 | */ |
2590 | static inline void __init check_timer(void) | 2691 | static inline void __init check_timer(void) |
2591 | { | 2692 | { |
2592 | struct irq_cfg *cfg = irq_cfg(0); | 2693 | struct irq_desc *desc = irq_to_desc(0); |
2694 | struct irq_cfg *cfg = desc->chip_data; | ||
2695 | int cpu = boot_cpu_id; | ||
2593 | int apic1, pin1, apic2, pin2; | 2696 | int apic1, pin1, apic2, pin2; |
2594 | unsigned long flags; | 2697 | unsigned long flags; |
2595 | unsigned int ver; | 2698 | unsigned int ver; |
@@ -2604,7 +2707,7 @@ static inline void __init check_timer(void) | |||
2604 | * get/set the timer IRQ vector: | 2707 | * get/set the timer IRQ vector: |
2605 | */ | 2708 | */ |
2606 | disable_8259A_irq(0); | 2709 | disable_8259A_irq(0); |
2607 | assign_irq_vector(0, TARGET_CPUS); | 2710 | assign_irq_vector(0, cfg, TARGET_CPUS); |
2608 | 2711 | ||
2609 | /* | 2712 | /* |
2610 | * As IRQ0 is to be enabled in the 8259A, the virtual | 2713 | * As IRQ0 is to be enabled in the 8259A, the virtual |
@@ -2655,10 +2758,10 @@ static inline void __init check_timer(void) | |||
2655 | * Ok, does IRQ0 through the IOAPIC work? | 2758 | * Ok, does IRQ0 through the IOAPIC work? |
2656 | */ | 2759 | */ |
2657 | if (no_pin1) { | 2760 | if (no_pin1) { |
2658 | add_pin_to_irq(0, apic1, pin1); | 2761 | add_pin_to_irq_cpu(cfg, cpu, apic1, pin1); |
2659 | setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); | 2762 | setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); |
2660 | } | 2763 | } |
2661 | unmask_IO_APIC_irq(0); | 2764 | unmask_IO_APIC_irq_desc(desc); |
2662 | if (timer_irq_works()) { | 2765 | if (timer_irq_works()) { |
2663 | if (nmi_watchdog == NMI_IO_APIC) { | 2766 | if (nmi_watchdog == NMI_IO_APIC) { |
2664 | setup_nmi(); | 2767 | setup_nmi(); |
@@ -2684,9 +2787,9 @@ static inline void __init check_timer(void) | |||
2684 | /* | 2787 | /* |
2685 | * legacy devices should be connected to IO APIC #0 | 2788 | * legacy devices should be connected to IO APIC #0 |
2686 | */ | 2789 | */ |
2687 | replace_pin_at_irq(0, apic1, pin1, apic2, pin2); | 2790 | replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2); |
2688 | setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); | 2791 | setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); |
2689 | unmask_IO_APIC_irq(0); | 2792 | unmask_IO_APIC_irq_desc(desc); |
2690 | enable_8259A_irq(0); | 2793 | enable_8259A_irq(0); |
2691 | if (timer_irq_works()) { | 2794 | if (timer_irq_works()) { |
2692 | apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); | 2795 | apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); |
@@ -2718,7 +2821,7 @@ static inline void __init check_timer(void) | |||
2718 | apic_printk(APIC_QUIET, KERN_INFO | 2821 | apic_printk(APIC_QUIET, KERN_INFO |
2719 | "...trying to set up timer as Virtual Wire IRQ...\n"); | 2822 | "...trying to set up timer as Virtual Wire IRQ...\n"); |
2720 | 2823 | ||
2721 | lapic_register_intr(0); | 2824 | lapic_register_intr(0, desc); |
2722 | apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ | 2825 | apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ |
2723 | enable_8259A_irq(0); | 2826 | enable_8259A_irq(0); |
2724 | 2827 | ||
@@ -2903,22 +3006,26 @@ unsigned int create_irq_nr(unsigned int irq_want) | |||
2903 | unsigned int irq; | 3006 | unsigned int irq; |
2904 | unsigned int new; | 3007 | unsigned int new; |
2905 | unsigned long flags; | 3008 | unsigned long flags; |
2906 | struct irq_cfg *cfg_new; | 3009 | struct irq_cfg *cfg_new = NULL; |
2907 | 3010 | int cpu = boot_cpu_id; | |
2908 | irq_want = nr_irqs - 1; | 3011 | struct irq_desc *desc_new = NULL; |
2909 | 3012 | ||
2910 | irq = 0; | 3013 | irq = 0; |
2911 | spin_lock_irqsave(&vector_lock, flags); | 3014 | spin_lock_irqsave(&vector_lock, flags); |
2912 | for (new = irq_want; new > 0; new--) { | 3015 | for (new = irq_want; new < NR_IRQS; new++) { |
2913 | if (platform_legacy_irq(new)) | 3016 | if (platform_legacy_irq(new)) |
2914 | continue; | 3017 | continue; |
2915 | cfg_new = irq_cfg(new); | 3018 | |
2916 | if (cfg_new && cfg_new->vector != 0) | 3019 | desc_new = irq_to_desc_alloc_cpu(new, cpu); |
3020 | if (!desc_new) { | ||
3021 | printk(KERN_INFO "can not get irq_desc for %d\n", new); | ||
3022 | continue; | ||
3023 | } | ||
3024 | cfg_new = desc_new->chip_data; | ||
3025 | |||
3026 | if (cfg_new->vector != 0) | ||
2917 | continue; | 3027 | continue; |
2918 | /* check if need to create one */ | 3028 | if (__assign_irq_vector(new, cfg_new, TARGET_CPUS) == 0) |
2919 | if (!cfg_new) | ||
2920 | cfg_new = irq_cfg_alloc(new); | ||
2921 | if (__assign_irq_vector(new, TARGET_CPUS) == 0) | ||
2922 | irq = new; | 3029 | irq = new; |
2923 | break; | 3030 | break; |
2924 | } | 3031 | } |
@@ -2926,15 +3033,21 @@ unsigned int create_irq_nr(unsigned int irq_want) | |||
2926 | 3033 | ||
2927 | if (irq > 0) { | 3034 | if (irq > 0) { |
2928 | dynamic_irq_init(irq); | 3035 | dynamic_irq_init(irq); |
3036 | /* restore it, in case dynamic_irq_init clear it */ | ||
3037 | if (desc_new) | ||
3038 | desc_new->chip_data = cfg_new; | ||
2929 | } | 3039 | } |
2930 | return irq; | 3040 | return irq; |
2931 | } | 3041 | } |
2932 | 3042 | ||
3043 | static int nr_irqs_gsi = NR_IRQS_LEGACY; | ||
2933 | int create_irq(void) | 3044 | int create_irq(void) |
2934 | { | 3045 | { |
3046 | unsigned int irq_want; | ||
2935 | int irq; | 3047 | int irq; |
2936 | 3048 | ||
2937 | irq = create_irq_nr(nr_irqs - 1); | 3049 | irq_want = nr_irqs_gsi; |
3050 | irq = create_irq_nr(irq_want); | ||
2938 | 3051 | ||
2939 | if (irq == 0) | 3052 | if (irq == 0) |
2940 | irq = -1; | 3053 | irq = -1; |
@@ -2945,14 +3058,22 @@ int create_irq(void) | |||
2945 | void destroy_irq(unsigned int irq) | 3058 | void destroy_irq(unsigned int irq) |
2946 | { | 3059 | { |
2947 | unsigned long flags; | 3060 | unsigned long flags; |
3061 | struct irq_cfg *cfg; | ||
3062 | struct irq_desc *desc; | ||
2948 | 3063 | ||
3064 | /* store it, in case dynamic_irq_cleanup clear it */ | ||
3065 | desc = irq_to_desc(irq); | ||
3066 | cfg = desc->chip_data; | ||
2949 | dynamic_irq_cleanup(irq); | 3067 | dynamic_irq_cleanup(irq); |
3068 | /* connect back irq_cfg */ | ||
3069 | if (desc) | ||
3070 | desc->chip_data = cfg; | ||
2950 | 3071 | ||
2951 | #ifdef CONFIG_INTR_REMAP | 3072 | #ifdef CONFIG_INTR_REMAP |
2952 | free_irte(irq); | 3073 | free_irte(irq); |
2953 | #endif | 3074 | #endif |
2954 | spin_lock_irqsave(&vector_lock, flags); | 3075 | spin_lock_irqsave(&vector_lock, flags); |
2955 | __clear_irq_vector(irq); | 3076 | __clear_irq_vector(irq, cfg); |
2956 | spin_unlock_irqrestore(&vector_lock, flags); | 3077 | spin_unlock_irqrestore(&vector_lock, flags); |
2957 | } | 3078 | } |
2958 | 3079 | ||
@@ -2967,12 +3088,12 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms | |||
2967 | unsigned dest; | 3088 | unsigned dest; |
2968 | cpumask_t tmp; | 3089 | cpumask_t tmp; |
2969 | 3090 | ||
3091 | cfg = irq_cfg(irq); | ||
2970 | tmp = TARGET_CPUS; | 3092 | tmp = TARGET_CPUS; |
2971 | err = assign_irq_vector(irq, tmp); | 3093 | err = assign_irq_vector(irq, cfg, tmp); |
2972 | if (err) | 3094 | if (err) |
2973 | return err; | 3095 | return err; |
2974 | 3096 | ||
2975 | cfg = irq_cfg(irq); | ||
2976 | cpus_and(tmp, cfg->domain, tmp); | 3097 | cpus_and(tmp, cfg->domain, tmp); |
2977 | dest = cpu_mask_to_apicid(tmp); | 3098 | dest = cpu_mask_to_apicid(tmp); |
2978 | 3099 | ||
@@ -3030,34 +3151,34 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms | |||
3030 | #ifdef CONFIG_SMP | 3151 | #ifdef CONFIG_SMP |
3031 | static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) | 3152 | static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) |
3032 | { | 3153 | { |
3154 | struct irq_desc *desc = irq_to_desc(irq); | ||
3033 | struct irq_cfg *cfg; | 3155 | struct irq_cfg *cfg; |
3034 | struct msi_msg msg; | 3156 | struct msi_msg msg; |
3035 | unsigned int dest; | 3157 | unsigned int dest; |
3036 | cpumask_t tmp; | 3158 | cpumask_t tmp; |
3037 | struct irq_desc *desc; | ||
3038 | 3159 | ||
3039 | if (!cpumask_intersects(mask, cpu_online_mask)) | 3160 | if (!cpumask_intersects(mask, cpu_online_mask)) |
3040 | return; | 3161 | return; |
3041 | 3162 | ||
3042 | if (assign_irq_vector(irq, *mask)) | 3163 | cfg = desc->chip_data; |
3164 | if (assign_irq_vector(irq, cfg, *mask)) | ||
3043 | return; | 3165 | return; |
3044 | 3166 | ||
3045 | cfg = irq_cfg(irq); | 3167 | set_extra_move_desc(desc, *mask); |
3168 | |||
3046 | cpumask_and(&tmp, &cfg->domain, mask); | 3169 | cpumask_and(&tmp, &cfg->domain, mask); |
3047 | dest = cpu_mask_to_apicid(tmp); | 3170 | dest = cpu_mask_to_apicid(tmp); |
3048 | 3171 | ||
3049 | read_msi_msg(irq, &msg); | 3172 | read_msi_msg_desc(desc, &msg); |
3050 | 3173 | ||
3051 | msg.data &= ~MSI_DATA_VECTOR_MASK; | 3174 | msg.data &= ~MSI_DATA_VECTOR_MASK; |
3052 | msg.data |= MSI_DATA_VECTOR(cfg->vector); | 3175 | msg.data |= MSI_DATA_VECTOR(cfg->vector); |
3053 | msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; | 3176 | msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; |
3054 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); | 3177 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); |
3055 | 3178 | ||
3056 | write_msi_msg(irq, &msg); | 3179 | write_msi_msg_desc(desc, &msg); |
3057 | desc = irq_to_desc(irq); | ||
3058 | cpumask_copy(&desc->affinity, mask); | 3180 | cpumask_copy(&desc->affinity, mask); |
3059 | } | 3181 | } |
3060 | |||
3061 | #ifdef CONFIG_INTR_REMAP | 3182 | #ifdef CONFIG_INTR_REMAP |
3062 | /* | 3183 | /* |
3063 | * Migrate the MSI irq to another cpumask. This migration is | 3184 | * Migrate the MSI irq to another cpumask. This migration is |
@@ -3066,11 +3187,11 @@ static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) | |||
3066 | static void ir_set_msi_irq_affinity(unsigned int irq, | 3187 | static void ir_set_msi_irq_affinity(unsigned int irq, |
3067 | const struct cpumask *mask) | 3188 | const struct cpumask *mask) |
3068 | { | 3189 | { |
3190 | struct irq_desc *desc = irq_to_desc(irq); | ||
3069 | struct irq_cfg *cfg; | 3191 | struct irq_cfg *cfg; |
3070 | unsigned int dest; | 3192 | unsigned int dest; |
3071 | cpumask_t tmp, cleanup_mask; | 3193 | cpumask_t tmp, cleanup_mask; |
3072 | struct irte irte; | 3194 | struct irte irte; |
3073 | struct irq_desc *desc; | ||
3074 | 3195 | ||
3075 | if (!cpumask_intersects(mask, cpu_online_mask)) | 3196 | if (!cpumask_intersects(mask, cpu_online_mask)) |
3076 | return; | 3197 | return; |
@@ -3078,10 +3199,12 @@ static void ir_set_msi_irq_affinity(unsigned int irq, | |||
3078 | if (get_irte(irq, &irte)) | 3199 | if (get_irte(irq, &irte)) |
3079 | return; | 3200 | return; |
3080 | 3201 | ||
3081 | if (assign_irq_vector(irq, *mask)) | 3202 | cfg = desc->chip_data; |
3203 | if (assign_irq_vector(irq, cfg, *mask)) | ||
3082 | return; | 3204 | return; |
3083 | 3205 | ||
3084 | cfg = irq_cfg(irq); | 3206 | set_extra_move_desc(desc, mask); |
3207 | |||
3085 | cpumask_and(&tmp, &cfg->domain, mask); | 3208 | cpumask_and(&tmp, &cfg->domain, mask); |
3086 | dest = cpu_mask_to_apicid(tmp); | 3209 | dest = cpu_mask_to_apicid(tmp); |
3087 | 3210 | ||
@@ -3105,9 +3228,9 @@ static void ir_set_msi_irq_affinity(unsigned int irq, | |||
3105 | cfg->move_in_progress = 0; | 3228 | cfg->move_in_progress = 0; |
3106 | } | 3229 | } |
3107 | 3230 | ||
3108 | desc = irq_to_desc(irq); | ||
3109 | cpumask_copy(&desc->affinity, mask); | 3231 | cpumask_copy(&desc->affinity, mask); |
3110 | } | 3232 | } |
3233 | |||
3111 | #endif | 3234 | #endif |
3112 | #endif /* CONFIG_SMP */ | 3235 | #endif /* CONFIG_SMP */ |
3113 | 3236 | ||
@@ -3166,7 +3289,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec) | |||
3166 | } | 3289 | } |
3167 | #endif | 3290 | #endif |
3168 | 3291 | ||
3169 | static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) | 3292 | static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) |
3170 | { | 3293 | { |
3171 | int ret; | 3294 | int ret; |
3172 | struct msi_msg msg; | 3295 | struct msi_msg msg; |
@@ -3175,7 +3298,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) | |||
3175 | if (ret < 0) | 3298 | if (ret < 0) |
3176 | return ret; | 3299 | return ret; |
3177 | 3300 | ||
3178 | set_irq_msi(irq, desc); | 3301 | set_irq_msi(irq, msidesc); |
3179 | write_msi_msg(irq, &msg); | 3302 | write_msi_msg(irq, &msg); |
3180 | 3303 | ||
3181 | #ifdef CONFIG_INTR_REMAP | 3304 | #ifdef CONFIG_INTR_REMAP |
@@ -3195,26 +3318,13 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) | |||
3195 | return 0; | 3318 | return 0; |
3196 | } | 3319 | } |
3197 | 3320 | ||
3198 | static unsigned int build_irq_for_pci_dev(struct pci_dev *dev) | 3321 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc) |
3199 | { | ||
3200 | unsigned int irq; | ||
3201 | |||
3202 | irq = dev->bus->number; | ||
3203 | irq <<= 8; | ||
3204 | irq |= dev->devfn; | ||
3205 | irq <<= 12; | ||
3206 | |||
3207 | return irq; | ||
3208 | } | ||
3209 | |||
3210 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) | ||
3211 | { | 3322 | { |
3212 | unsigned int irq; | 3323 | unsigned int irq; |
3213 | int ret; | 3324 | int ret; |
3214 | unsigned int irq_want; | 3325 | unsigned int irq_want; |
3215 | 3326 | ||
3216 | irq_want = build_irq_for_pci_dev(dev) + 0x100; | 3327 | irq_want = nr_irqs_gsi; |
3217 | |||
3218 | irq = create_irq_nr(irq_want); | 3328 | irq = create_irq_nr(irq_want); |
3219 | if (irq == 0) | 3329 | if (irq == 0) |
3220 | return -1; | 3330 | return -1; |
@@ -3228,7 +3338,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) | |||
3228 | goto error; | 3338 | goto error; |
3229 | no_ir: | 3339 | no_ir: |
3230 | #endif | 3340 | #endif |
3231 | ret = setup_msi_irq(dev, desc, irq); | 3341 | ret = setup_msi_irq(dev, msidesc, irq); |
3232 | if (ret < 0) { | 3342 | if (ret < 0) { |
3233 | destroy_irq(irq); | 3343 | destroy_irq(irq); |
3234 | return ret; | 3344 | return ret; |
@@ -3246,7 +3356,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
3246 | { | 3356 | { |
3247 | unsigned int irq; | 3357 | unsigned int irq; |
3248 | int ret, sub_handle; | 3358 | int ret, sub_handle; |
3249 | struct msi_desc *desc; | 3359 | struct msi_desc *msidesc; |
3250 | unsigned int irq_want; | 3360 | unsigned int irq_want; |
3251 | 3361 | ||
3252 | #ifdef CONFIG_INTR_REMAP | 3362 | #ifdef CONFIG_INTR_REMAP |
@@ -3254,10 +3364,11 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
3254 | int index = 0; | 3364 | int index = 0; |
3255 | #endif | 3365 | #endif |
3256 | 3366 | ||
3257 | irq_want = build_irq_for_pci_dev(dev) + 0x100; | 3367 | irq_want = nr_irqs_gsi; |
3258 | sub_handle = 0; | 3368 | sub_handle = 0; |
3259 | list_for_each_entry(desc, &dev->msi_list, list) { | 3369 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
3260 | irq = create_irq_nr(irq_want--); | 3370 | irq = create_irq_nr(irq_want); |
3371 | irq_want++; | ||
3261 | if (irq == 0) | 3372 | if (irq == 0) |
3262 | return -1; | 3373 | return -1; |
3263 | #ifdef CONFIG_INTR_REMAP | 3374 | #ifdef CONFIG_INTR_REMAP |
@@ -3289,7 +3400,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
3289 | } | 3400 | } |
3290 | no_ir: | 3401 | no_ir: |
3291 | #endif | 3402 | #endif |
3292 | ret = setup_msi_irq(dev, desc, irq); | 3403 | ret = setup_msi_irq(dev, msidesc, irq); |
3293 | if (ret < 0) | 3404 | if (ret < 0) |
3294 | goto error; | 3405 | goto error; |
3295 | sub_handle++; | 3406 | sub_handle++; |
@@ -3310,19 +3421,21 @@ void arch_teardown_msi_irq(unsigned int irq) | |||
3310 | #ifdef CONFIG_SMP | 3421 | #ifdef CONFIG_SMP |
3311 | static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | 3422 | static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) |
3312 | { | 3423 | { |
3424 | struct irq_desc *desc = irq_to_desc(irq); | ||
3313 | struct irq_cfg *cfg; | 3425 | struct irq_cfg *cfg; |
3314 | struct msi_msg msg; | 3426 | struct msi_msg msg; |
3315 | unsigned int dest; | 3427 | unsigned int dest; |
3316 | cpumask_t tmp; | 3428 | cpumask_t tmp; |
3317 | struct irq_desc *desc; | ||
3318 | 3429 | ||
3319 | if (!cpumask_intersects(mask, cpu_online_mask)) | 3430 | if (!cpumask_intersects(mask, cpu_online_mask)) |
3320 | return; | 3431 | return; |
3321 | 3432 | ||
3322 | if (assign_irq_vector(irq, *mask)) | 3433 | cfg = desc->chip_data; |
3434 | if (assign_irq_vector(irq, cfg, *mask)) | ||
3323 | return; | 3435 | return; |
3324 | 3436 | ||
3325 | cfg = irq_cfg(irq); | 3437 | set_extra_move_desc(desc, *mask); |
3438 | |||
3326 | cpumask_and(&tmp, &cfg->domain, mask); | 3439 | cpumask_and(&tmp, &cfg->domain, mask); |
3327 | dest = cpu_mask_to_apicid(tmp); | 3440 | dest = cpu_mask_to_apicid(tmp); |
3328 | 3441 | ||
@@ -3334,9 +3447,9 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
3334 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); | 3447 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); |
3335 | 3448 | ||
3336 | dmar_msi_write(irq, &msg); | 3449 | dmar_msi_write(irq, &msg); |
3337 | desc = irq_to_desc(irq); | ||
3338 | cpumask_copy(&desc->affinity, mask); | 3450 | cpumask_copy(&desc->affinity, mask); |
3339 | } | 3451 | } |
3452 | |||
3340 | #endif /* CONFIG_SMP */ | 3453 | #endif /* CONFIG_SMP */ |
3341 | 3454 | ||
3342 | struct irq_chip dmar_msi_type = { | 3455 | struct irq_chip dmar_msi_type = { |
@@ -3370,8 +3483,8 @@ int arch_setup_dmar_msi(unsigned int irq) | |||
3370 | #ifdef CONFIG_SMP | 3483 | #ifdef CONFIG_SMP |
3371 | static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | 3484 | static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) |
3372 | { | 3485 | { |
3486 | struct irq_desc *desc = irq_to_desc(irq); | ||
3373 | struct irq_cfg *cfg; | 3487 | struct irq_cfg *cfg; |
3374 | struct irq_desc *desc; | ||
3375 | struct msi_msg msg; | 3488 | struct msi_msg msg; |
3376 | unsigned int dest; | 3489 | unsigned int dest; |
3377 | cpumask_t tmp; | 3490 | cpumask_t tmp; |
@@ -3379,10 +3492,12 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
3379 | if (!cpumask_intersects(mask, cpu_online_mask)) | 3492 | if (!cpumask_intersects(mask, cpu_online_mask)) |
3380 | return; | 3493 | return; |
3381 | 3494 | ||
3382 | if (assign_irq_vector(irq, *mask)) | 3495 | cfg = desc->chip_data; |
3496 | if (assign_irq_vector(irq, cfg, *mask)) | ||
3383 | return; | 3497 | return; |
3384 | 3498 | ||
3385 | cfg = irq_cfg(irq); | 3499 | set_extra_move_desc(desc, *mask); |
3500 | |||
3386 | cpumask_and(&tmp, &cfg->domain, mask); | 3501 | cpumask_and(&tmp, &cfg->domain, mask); |
3387 | dest = cpu_mask_to_apicid(tmp); | 3502 | dest = cpu_mask_to_apicid(tmp); |
3388 | 3503 | ||
@@ -3394,9 +3509,9 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
3394 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); | 3509 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); |
3395 | 3510 | ||
3396 | hpet_msi_write(irq, &msg); | 3511 | hpet_msi_write(irq, &msg); |
3397 | desc = irq_to_desc(irq); | ||
3398 | cpumask_copy(&desc->affinity, mask); | 3512 | cpumask_copy(&desc->affinity, mask); |
3399 | } | 3513 | } |
3514 | |||
3400 | #endif /* CONFIG_SMP */ | 3515 | #endif /* CONFIG_SMP */ |
3401 | 3516 | ||
3402 | struct irq_chip hpet_msi_type = { | 3517 | struct irq_chip hpet_msi_type = { |
@@ -3451,25 +3566,27 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) | |||
3451 | 3566 | ||
3452 | static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask) | 3567 | static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask) |
3453 | { | 3568 | { |
3569 | struct irq_desc *desc = irq_to_desc(irq); | ||
3454 | struct irq_cfg *cfg; | 3570 | struct irq_cfg *cfg; |
3455 | unsigned int dest; | 3571 | unsigned int dest; |
3456 | cpumask_t tmp; | 3572 | cpumask_t tmp; |
3457 | struct irq_desc *desc; | ||
3458 | 3573 | ||
3459 | if (!cpumask_intersects(mask, cpu_online_mask)) | 3574 | if (!cpumask_intersects(mask, cpu_online_mask)) |
3460 | return; | 3575 | return; |
3461 | 3576 | ||
3462 | if (assign_irq_vector(irq, *mask)) | 3577 | cfg = desc->chip_data; |
3578 | if (assign_irq_vector(irq, cfg, *mask)) | ||
3463 | return; | 3579 | return; |
3464 | 3580 | ||
3465 | cfg = irq_cfg(irq); | 3581 | set_extra_move_desc(desc, *mask); |
3582 | |||
3466 | cpumask_and(&tmp, &cfg->domain, mask); | 3583 | cpumask_and(&tmp, &cfg->domain, mask); |
3467 | dest = cpu_mask_to_apicid(tmp); | 3584 | dest = cpu_mask_to_apicid(tmp); |
3468 | 3585 | ||
3469 | target_ht_irq(irq, dest, cfg->vector); | 3586 | target_ht_irq(irq, dest, cfg->vector); |
3470 | desc = irq_to_desc(irq); | ||
3471 | cpumask_copy(&desc->affinity, mask); | 3587 | cpumask_copy(&desc->affinity, mask); |
3472 | } | 3588 | } |
3589 | |||
3473 | #endif | 3590 | #endif |
3474 | 3591 | ||
3475 | static struct irq_chip ht_irq_chip = { | 3592 | static struct irq_chip ht_irq_chip = { |
@@ -3489,13 +3606,13 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | |||
3489 | int err; | 3606 | int err; |
3490 | cpumask_t tmp; | 3607 | cpumask_t tmp; |
3491 | 3608 | ||
3609 | cfg = irq_cfg(irq); | ||
3492 | tmp = TARGET_CPUS; | 3610 | tmp = TARGET_CPUS; |
3493 | err = assign_irq_vector(irq, tmp); | 3611 | err = assign_irq_vector(irq, cfg, tmp); |
3494 | if (!err) { | 3612 | if (!err) { |
3495 | struct ht_irq_msg msg; | 3613 | struct ht_irq_msg msg; |
3496 | unsigned dest; | 3614 | unsigned dest; |
3497 | 3615 | ||
3498 | cfg = irq_cfg(irq); | ||
3499 | cpus_and(tmp, cfg->domain, tmp); | 3616 | cpus_and(tmp, cfg->domain, tmp); |
3500 | dest = cpu_mask_to_apicid(tmp); | 3617 | dest = cpu_mask_to_apicid(tmp); |
3501 | 3618 | ||
@@ -3541,7 +3658,9 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, | |||
3541 | unsigned long flags; | 3658 | unsigned long flags; |
3542 | int err; | 3659 | int err; |
3543 | 3660 | ||
3544 | err = assign_irq_vector(irq, *eligible_cpu); | 3661 | cfg = irq_cfg(irq); |
3662 | |||
3663 | err = assign_irq_vector(irq, cfg, *eligible_cpu); | ||
3545 | if (err != 0) | 3664 | if (err != 0) |
3546 | return err; | 3665 | return err; |
3547 | 3666 | ||
@@ -3550,8 +3669,6 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, | |||
3550 | irq_name); | 3669 | irq_name); |
3551 | spin_unlock_irqrestore(&vector_lock, flags); | 3670 | spin_unlock_irqrestore(&vector_lock, flags); |
3552 | 3671 | ||
3553 | cfg = irq_cfg(irq); | ||
3554 | |||
3555 | mmr_value = 0; | 3672 | mmr_value = 0; |
3556 | entry = (struct uv_IO_APIC_route_entry *)&mmr_value; | 3673 | entry = (struct uv_IO_APIC_route_entry *)&mmr_value; |
3557 | BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); | 3674 | BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); |
@@ -3603,9 +3720,16 @@ int __init io_apic_get_redir_entries (int ioapic) | |||
3603 | return reg_01.bits.entries; | 3720 | return reg_01.bits.entries; |
3604 | } | 3721 | } |
3605 | 3722 | ||
3606 | int __init probe_nr_irqs(void) | 3723 | void __init probe_nr_irqs_gsi(void) |
3607 | { | 3724 | { |
3608 | return NR_IRQS; | 3725 | int idx; |
3726 | int nr = 0; | ||
3727 | |||
3728 | for (idx = 0; idx < nr_ioapics; idx++) | ||
3729 | nr += io_apic_get_redir_entries(idx) + 1; | ||
3730 | |||
3731 | if (nr > nr_irqs_gsi) | ||
3732 | nr_irqs_gsi = nr; | ||
3609 | } | 3733 | } |
3610 | 3734 | ||
3611 | /* -------------------------------------------------------------------------- | 3735 | /* -------------------------------------------------------------------------- |
@@ -3704,19 +3828,31 @@ int __init io_apic_get_version(int ioapic) | |||
3704 | 3828 | ||
3705 | int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity) | 3829 | int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity) |
3706 | { | 3830 | { |
3831 | struct irq_desc *desc; | ||
3832 | struct irq_cfg *cfg; | ||
3833 | int cpu = boot_cpu_id; | ||
3834 | |||
3707 | if (!IO_APIC_IRQ(irq)) { | 3835 | if (!IO_APIC_IRQ(irq)) { |
3708 | apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", | 3836 | apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", |
3709 | ioapic); | 3837 | ioapic); |
3710 | return -EINVAL; | 3838 | return -EINVAL; |
3711 | } | 3839 | } |
3712 | 3840 | ||
3841 | desc = irq_to_desc_alloc_cpu(irq, cpu); | ||
3842 | if (!desc) { | ||
3843 | printk(KERN_INFO "can not get irq_desc %d\n", irq); | ||
3844 | return 0; | ||
3845 | } | ||
3846 | |||
3713 | /* | 3847 | /* |
3714 | * IRQs < 16 are already in the irq_2_pin[] map | 3848 | * IRQs < 16 are already in the irq_2_pin[] map |
3715 | */ | 3849 | */ |
3716 | if (irq >= 16) | 3850 | if (irq >= NR_IRQS_LEGACY) { |
3717 | add_pin_to_irq(irq, ioapic, pin); | 3851 | cfg = desc->chip_data; |
3852 | add_pin_to_irq_cpu(cfg, cpu, ioapic, pin); | ||
3853 | } | ||
3718 | 3854 | ||
3719 | setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity); | 3855 | setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity); |
3720 | 3856 | ||
3721 | return 0; | 3857 | return 0; |
3722 | } | 3858 | } |
@@ -3770,9 +3906,10 @@ void __init setup_ioapic_dest(void) | |||
3770 | * when you have too many devices, because at that time only boot | 3906 | * when you have too many devices, because at that time only boot |
3771 | * cpu is online. | 3907 | * cpu is online. |
3772 | */ | 3908 | */ |
3773 | cfg = irq_cfg(irq); | 3909 | desc = irq_to_desc(irq); |
3910 | cfg = desc->chip_data; | ||
3774 | if (!cfg->vector) { | 3911 | if (!cfg->vector) { |
3775 | setup_IO_APIC_irq(ioapic, pin, irq, | 3912 | setup_IO_APIC_irq(ioapic, pin, irq, desc, |
3776 | irq_trigger(irq_entry), | 3913 | irq_trigger(irq_entry), |
3777 | irq_polarity(irq_entry)); | 3914 | irq_polarity(irq_entry)); |
3778 | continue; | 3915 | continue; |
@@ -3782,7 +3919,6 @@ void __init setup_ioapic_dest(void) | |||
3782 | /* | 3919 | /* |
3783 | * Honour affinities which have been set in early boot | 3920 | * Honour affinities which have been set in early boot |
3784 | */ | 3921 | */ |
3785 | desc = irq_to_desc(irq); | ||
3786 | if (desc->status & | 3922 | if (desc->status & |
3787 | (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) | 3923 | (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) |
3788 | mask = desc->affinity; | 3924 | mask = desc->affinity; |
@@ -3791,10 +3927,10 @@ void __init setup_ioapic_dest(void) | |||
3791 | 3927 | ||
3792 | #ifdef CONFIG_INTR_REMAP | 3928 | #ifdef CONFIG_INTR_REMAP |
3793 | if (intr_remapping_enabled) | 3929 | if (intr_remapping_enabled) |
3794 | set_ir_ioapic_affinity_irq(irq, &mask); | 3930 | set_ir_ioapic_affinity_irq_desc(desc, &mask); |
3795 | else | 3931 | else |
3796 | #endif | 3932 | #endif |
3797 | set_ioapic_affinity_irq(irq, &mask); | 3933 | set_ioapic_affinity_irq_desc(desc, &mask); |
3798 | } | 3934 | } |
3799 | 3935 | ||
3800 | } | 3936 | } |
@@ -3843,7 +3979,6 @@ void __init ioapic_init_mappings(void) | |||
3843 | struct resource *ioapic_res; | 3979 | struct resource *ioapic_res; |
3844 | int i; | 3980 | int i; |
3845 | 3981 | ||
3846 | irq_2_pin_init(); | ||
3847 | ioapic_res = ioapic_setup_resources(); | 3982 | ioapic_res = ioapic_setup_resources(); |
3848 | for (i = 0; i < nr_ioapics; i++) { | 3983 | for (i = 0; i < nr_ioapics; i++) { |
3849 | if (smp_found_config) { | 3984 | if (smp_found_config) { |