diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2009-10-26 18:24:35 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-02 09:56:36 -0500 |
commit | b3ec0a37a7907813bb4fb85a2d94102c152470b7 (patch) | |
tree | aec7a1de95df7b05231f52608899ca34d48f5105 /arch/x86/kernel/apic/io_apic.c | |
parent | a5e74b841930bec78a4684ab9f208b2ddfe7c736 (diff) |
x86: Use EOI register in io-apic on intel platforms
IO-APIC's in intel chipsets support EOI register starting from
IO-APIC version 2. Use that when ever we need to clear the
IO-APIC RTE's RemoteIRR bit explicitly.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Acked-by: Gary Hade <garyhade@us.ibm.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
LKML-Reference: <20091026230001.947855317@sbs-t61.sc.intel.com>
[ Marked use_eio_reg as __read_mostly, fixed small details ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-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(); |