aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/io_apic.c318
-rw-r--r--drivers/pci/msi.c55
-rw-r--r--include/linux/msi.h3
3 files changed, 222 insertions, 154 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index 0dcde74abd1d..a1a2e070f31a 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -231,6 +231,10 @@ static struct irq_cfg *irq_cfg(unsigned int irq)
231 231
232#endif 232#endif
233 233
234static inline void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask)
235{
236}
237
234struct io_apic { 238struct io_apic {
235 unsigned int index; 239 unsigned int index;
236 unsigned int unused[3]; 240 unsigned int unused[3];
@@ -272,11 +276,10 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned
272 writel(value, &io_apic->data); 276 writel(value, &io_apic->data);
273} 277}
274 278
275static bool io_apic_level_ack_pending(unsigned int irq) 279static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
276{ 280{
277 struct irq_pin_list *entry; 281 struct irq_pin_list *entry;
278 unsigned long flags; 282 unsigned long flags;
279 struct irq_cfg *cfg = irq_cfg(irq);
280 283
281 spin_lock_irqsave(&ioapic_lock, flags); 284 spin_lock_irqsave(&ioapic_lock, flags);
282 entry = cfg->irq_2_pin; 285 entry = cfg->irq_2_pin;
@@ -358,13 +361,12 @@ static void ioapic_mask_entry(int apic, int pin)
358} 361}
359 362
360#ifdef CONFIG_SMP 363#ifdef CONFIG_SMP
361static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) 364static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
362{ 365{
363 int apic, pin; 366 int apic, pin;
364 struct irq_cfg *cfg;
365 struct irq_pin_list *entry; 367 struct irq_pin_list *entry;
368 u8 vector = cfg->vector;
366 369
367 cfg = irq_cfg(irq);
368 entry = cfg->irq_2_pin; 370 entry = cfg->irq_2_pin;
369 for (;;) { 371 for (;;) {
370 unsigned int reg; 372 unsigned int reg;
@@ -394,24 +396,27 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
394 } 396 }
395} 397}
396 398
397static int assign_irq_vector(int irq, cpumask_t mask); 399static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask);
398 400
399static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) 401static void set_ioapic_affinity_irq_desc(struct irq_desc *desc, cpumask_t mask)
400{ 402{
401 struct irq_cfg *cfg; 403 struct irq_cfg *cfg;
402 unsigned long flags; 404 unsigned long flags;
403 unsigned int dest; 405 unsigned int dest;
404 cpumask_t tmp; 406 cpumask_t tmp;
405 struct irq_desc *desc; 407 unsigned int irq;
406 408
407 cpus_and(tmp, mask, cpu_online_map); 409 cpus_and(tmp, mask, cpu_online_map);
408 if (cpus_empty(tmp)) 410 if (cpus_empty(tmp))
409 return; 411 return;
410 412
411 cfg = irq_cfg(irq); 413 irq = desc->irq;
412 if (assign_irq_vector(irq, mask)) 414 cfg = desc->chip_data;
415 if (assign_irq_vector(irq, cfg, mask))
413 return; 416 return;
414 417
418 set_extra_move_desc(desc, mask);
419
415 cpus_and(tmp, cfg->domain, mask); 420 cpus_and(tmp, cfg->domain, mask);
416 dest = cpu_mask_to_apicid(tmp); 421 dest = cpu_mask_to_apicid(tmp);
417 /* 422 /*
@@ -419,12 +424,20 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
419 */ 424 */
420 dest = SET_APIC_LOGICAL_ID(dest); 425 dest = SET_APIC_LOGICAL_ID(dest);
421 426
422 desc = irq_to_desc(irq);
423 spin_lock_irqsave(&ioapic_lock, flags); 427 spin_lock_irqsave(&ioapic_lock, flags);
424 __target_IO_APIC_irq(irq, dest, cfg->vector); 428 __target_IO_APIC_irq(irq, dest, cfg);
425 desc->affinity = mask; 429 desc->affinity = mask;
426 spin_unlock_irqrestore(&ioapic_lock, flags); 430 spin_unlock_irqrestore(&ioapic_lock, flags);
427} 431}
432
433static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
434{
435 struct irq_desc *desc;
436
437 desc = irq_to_desc(irq);
438
439 set_ioapic_affinity_irq_desc(desc, mask);
440}
428#endif /* CONFIG_SMP */ 441#endif /* CONFIG_SMP */
429 442
430/* 443/*
@@ -432,10 +445,9 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
432 * shared ISA-space IRQs, so we have to support them. We are super 445 * shared ISA-space IRQs, so we have to support them. We are super
433 * fast in the common case, and fast for shared ISA-space IRQs. 446 * fast in the common case, and fast for shared ISA-space IRQs.
434 */ 447 */
435static void add_pin_to_irq_cpu(unsigned int irq, int cpu, int apic, int pin) 448static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
436{ 449{
437 struct irq_pin_list *entry; 450 struct irq_pin_list *entry;
438 struct irq_cfg *cfg = irq_cfg(irq);
439 451
440 entry = cfg->irq_2_pin; 452 entry = cfg->irq_2_pin;
441 if (!entry) { 453 if (!entry) {
@@ -468,11 +480,10 @@ static void add_pin_to_irq_cpu(unsigned int irq, int cpu, int apic, int pin)
468/* 480/*
469 * Reroute an IRQ to a different pin. 481 * Reroute an IRQ to a different pin.
470 */ 482 */
471static void __init replace_pin_at_irq(unsigned int irq, int cpu, 483static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
472 int oldapic, int oldpin, 484 int oldapic, int oldpin,
473 int newapic, int newpin) 485 int newapic, int newpin)
474{ 486{
475 struct irq_cfg *cfg = irq_cfg(irq);
476 struct irq_pin_list *entry = cfg->irq_2_pin; 487 struct irq_pin_list *entry = cfg->irq_2_pin;
477 int replaced = 0; 488 int replaced = 0;
478 489
@@ -489,18 +500,16 @@ static void __init replace_pin_at_irq(unsigned int irq, int cpu,
489 500
490 /* why? call replace before add? */ 501 /* why? call replace before add? */
491 if (!replaced) 502 if (!replaced)
492 add_pin_to_irq_cpu(irq, cpu, newapic, newpin); 503 add_pin_to_irq_cpu(cfg, cpu, newapic, newpin);
493} 504}
494 505
495static inline void io_apic_modify_irq(unsigned int irq, 506static inline void io_apic_modify_irq(struct irq_cfg *cfg,
496 int mask_and, int mask_or, 507 int mask_and, int mask_or,
497 void (*final)(struct irq_pin_list *entry)) 508 void (*final)(struct irq_pin_list *entry))
498{ 509{
499 int pin; 510 int pin;
500 struct irq_cfg *cfg;
501 struct irq_pin_list *entry; 511 struct irq_pin_list *entry;
502 512
503 cfg = irq_cfg(irq);
504 for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) { 513 for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
505 unsigned int reg; 514 unsigned int reg;
506 pin = entry->pin; 515 pin = entry->pin;
@@ -513,9 +522,9 @@ static inline void io_apic_modify_irq(unsigned int irq,
513 } 522 }
514} 523}
515 524
516static void __unmask_IO_APIC_irq(unsigned int irq) 525static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
517{ 526{
518 io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL); 527 io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
519} 528}
520 529
521#ifdef CONFIG_X86_64 530#ifdef CONFIG_X86_64
@@ -530,47 +539,64 @@ void io_apic_sync(struct irq_pin_list *entry)
530 readl(&io_apic->data); 539 readl(&io_apic->data);
531} 540}
532 541
533static void __mask_IO_APIC_irq(unsigned int irq)