diff options
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 4e886efd9a15..31e9db3c12ad 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -2492,6 +2492,51 @@ static void ack_apic_edge(unsigned int irq) | |||
| 2492 | 2492 | ||
| 2493 | atomic_t irq_mis_count; | 2493 | atomic_t irq_mis_count; |
| 2494 | 2494 | ||
| 2495 | static int use_eoi_reg __read_mostly; | ||
| 2496 | |||
| 2497 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) | ||
| 2498 | { | ||
| 2499 | struct irq_pin_list *entry; | ||
| 2500 | |||
| 2501 | for_each_irq_pin(entry, cfg->irq_2_pin) { | ||
| 2502 | if (irq_remapped(irq)) | ||
| 2503 | io_apic_eoi(entry->apic, entry->pin); | ||
| 2504 | else | ||
| 2505 | io_apic_eoi(entry->apic, cfg->vector); | ||
| 2506 | } | ||
| 2507 | } | ||
| 2508 | |||
| 2509 | static void eoi_ioapic_irq(struct irq_desc *desc) | ||
| 2510 | { | ||
| 2511 | struct irq_cfg *cfg; | ||
| 2512 | unsigned long flags; | ||
| 2513 | unsigned int irq; | ||
| 2514 | |||
| 2515 | irq = desc->irq; | ||
| 2516 | cfg = desc->chip_data; | ||
| 2517 | |||
| 2518 | spin_lock_irqsave(&ioapic_lock, flags); | ||
| 2519 | __eoi_ioapic_irq(irq, cfg); | ||
| 2520 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
| 2521 | } | ||
| 2522 | |||
| 2523 | static int ioapic_supports_eoi(void) | ||
| 2524 | { | ||
| 2525 | struct pci_dev *root; | ||
| 2526 | |||
| 2527 | root = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); | ||
| 2528 | if (root && root->vendor == PCI_VENDOR_ID_INTEL && | ||
| 2529 | mp_ioapics[0].apicver >= 0x2) { | ||
| 2530 | use_eoi_reg = 1; | ||
| 2531 | printk(KERN_INFO "IO-APIC supports EOI register\n"); | ||
| 2532 | } else | ||
| 2533 | printk(KERN_INFO "IO-APIC doesn't support EOI\n"); | ||
| 2534 | |||
| 2535 | return 0; | ||
| 2536 | } | ||
| 2537 | |||
| 2538 | fs_initcall(ioapic_supports_eoi); | ||
| 2539 | |||
| 2495 | static void ack_apic_level(unsigned int irq) | 2540 | static void ack_apic_level(unsigned int irq) |
| 2496 | { | 2541 | { |
| 2497 | struct irq_desc *desc = irq_to_desc(irq); | 2542 | struct irq_desc *desc = irq_to_desc(irq); |
| @@ -2575,37 +2620,19 @@ static void ack_apic_level(unsigned int irq) | |||
| 2575 | /* Tail end of version 0x11 I/O APIC bug workaround */ | 2620 | /* Tail end of version 0x11 I/O APIC bug workaround */ |
| 2576 | if (!(v & (1 << (i & 0x1f)))) { | 2621 | if (!(v & (1 << (i & 0x1f)))) { |
| 2577 | atomic_inc(&irq_mis_count); | 2622 | atomic_inc(&irq_mis_count); |
| 2578 | spin_lock(&ioapic_lock); | 2623 | |
| 2579 | __mask_and_edge_IO_APIC_irq(cfg); | 2624 | if (use_eoi_reg) |
| 2580 | __unmask_and_level_IO_APIC_irq(cfg); | 2625 | eoi_ioapic_irq(desc); |
| 2581 | spin_unlock(&ioapic_lock); | 2626 | else { |
| 2627 | spin_lock(&ioapic_lock); | ||
| 2628 | __mask_and_edge_IO_APIC_irq(cfg); | ||
| 2629 | __unmask_and_level_IO_APIC_irq(cfg); | ||
| 2630 | spin_unlock(&ioapic_lock); | ||
| 2631 | } | ||
| 2582 | } | 2632 | } |
| 2583 | } | 2633 | } |
| 2584 | 2634 | ||
| 2585 | #ifdef CONFIG_INTR_REMAP | 2635 | #ifdef CONFIG_INTR_REMAP |
| 2586 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) | ||
| 2587 | { | ||
| 2588 | struct irq_pin_list *entry; | ||
| 2589 | |||
| 2590 | for_each_irq_pin(entry, cfg->irq_2_pin) | ||
| 2591 | io_apic_eoi(entry->apic, entry->pin); | ||
| 2592 | } | ||
| 2593 | |||
| 2594 | static void | ||
| 2595 | eoi_ioapic_irq(struct irq_desc *desc) | ||
| 2596 | { | ||
| 2597 | struct irq_cfg *cfg; | ||
| 2598 | unsigned long flags; | ||
| 2599 | unsigned int irq; | ||
| 2600 | |||
| 2601 | irq = desc->irq; | ||
| 2602 | cfg = desc->chip_data; | ||
| 2603 | |||
| 2604 | spin_lock_irqsave(&ioapic_lock, flags); | ||
| 2605 | __eoi_ioapic_irq(irq, cfg); | ||
| 2606 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
| 2607 | } | ||
| 2608 | |||
| 2609 | static void ir_ack_apic_edge(unsigned int irq) | 2636 | static void ir_ack_apic_edge(unsigned int irq) |
| 2610 | { | 2637 | { |
| 2611 | ack_APIC_irq(); | 2638 | ack_APIC_irq(); |
