diff options
| -rw-r--r-- | arch/x86/kernel/io_apic.c | 318 | ||||
| -rw-r--r-- | drivers/pci/msi.c | 55 | ||||
| -rw-r--r-- | include/linux/msi.h | 3 |
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 | ||
| 234 | static inline void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask) | ||
| 235 | { | ||
| 236 | } | ||
| 237 | |||
| 234 | struct io_apic { | 238 | struct 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 | ||
| 275 | static bool io_apic_level_ack_pending(unsigned int irq) | 279 | static 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 |
| 361 | 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) |
| 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 | ||
| 397 | 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); |
| 398 | 400 | ||
| 399 | static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) | 401 | static 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 | |||
| 433 | static 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 | */ |
| 435 | static void add_pin_to_irq_cpu(unsigned int irq, int cpu, int apic, int pin) | 448 | static 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 | */ |
| 471 | static void __init replace_pin_at_irq(unsigned int irq, int cpu, | 483 | static 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 | ||
| 495 | static inline void io_apic_modify_irq(unsigned int irq, | 506 | static 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 | ||
| 516 | static void __unmask_IO_APIC_irq(unsigned int irq) | 525 | static 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 | ||
| 533 | static void __mask_IO_APIC_irq(unsigned int irq) | ||
