diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2011-02-23 11:47:41 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-02-23 12:58:09 -0500 |
commit | 710dcda64369e3f3704a0eee502ce27dbf9fedc1 (patch) | |
tree | 42f74f2bef2e6b05da7f58163fcb787d267f34e5 /arch/x86/kernel/apic/io_apic.c | |
parent | b77cf6a8609a8450786c572bc8af6ad068022dbe (diff) |
x86: ioapic: Implement and use io_apic_setup_irq_pin_once()
io_apic_set_pci_routing() and mp_save_irq() check the pin_programmed
bit before calling io_apic_setup_irq_pin() and set the bit when the
pin was setup.
Move that duplicated code into a separate function and use it.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 57 |
1 files changed, 25 insertions, 32 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 2d49e4b41c2..46913ef88ea 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -128,6 +128,9 @@ static int __init parse_noapic(char *str) | |||
128 | } | 128 | } |
129 | early_param("noapic", parse_noapic); | 129 | early_param("noapic", parse_noapic); |
130 | 130 | ||
131 | static int io_apic_setup_irq_pin_once(unsigned int irq, int node, | ||
132 | struct io_apic_irq_attr *attr); | ||
133 | |||
131 | /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ | 134 | /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ |
132 | void mp_save_irq(struct mpc_intsrc *m) | 135 | void mp_save_irq(struct mpc_intsrc *m) |
133 | { | 136 | { |
@@ -1457,17 +1460,10 @@ void setup_IO_APIC_irq_extra(u32 gsi) | |||
1457 | if (apic_id == 0 || irq < NR_IRQS_LEGACY) | 1460 | if (apic_id == 0 || irq < NR_IRQS_LEGACY) |
1458 | return; | 1461 | return; |
1459 | 1462 | ||
1460 | if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) { | ||
1461 | pr_debug("Pin %d-%d already programmed\n", | ||
1462 | mp_ioapics[apic_id].apicid, pin); | ||
1463 | return; | ||
1464 | } | ||
1465 | |||
1466 | set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), | 1463 | set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), |
1467 | irq_polarity(idx)); | 1464 | irq_polarity(idx)); |
1468 | 1465 | ||
1469 | if (!io_apic_setup_irq_pin(irq, node, &attr)) | 1466 | io_apic_setup_irq_pin_once(irq, node, &attr); |
1470 | set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed); | ||
1471 | } | 1467 | } |
1472 | 1468 | ||
1473 | /* | 1469 | /* |
@@ -3601,6 +3597,24 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) | |||
3601 | return ret; | 3597 | return ret; |
3602 | } | 3598 | } |
3603 | 3599 | ||
3600 | static int io_apic_setup_irq_pin_once(unsigned int irq, int node, | ||
3601 | struct io_apic_irq_attr *attr) | ||
3602 | { | ||
3603 | unsigned int id = attr->ioapic, pin = attr->ioapic_pin; | ||
3604 | int ret; | ||
3605 | |||
3606 | /* Avoid redundant programming */ | ||
3607 | if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) { | ||
3608 | pr_debug("Pin %d-%d already programmed\n", | ||
3609 | mp_ioapics[id].apicid, pin); | ||
3610 | return 0; | ||
3611 | } | ||
3612 | ret = io_apic_setup_irq_pin(irq, node, attr); | ||
3613 | if (!ret) | ||
3614 | set_bit(pin, mp_ioapic_routing[id].pin_programmed); | ||
3615 | return ret; | ||
3616 | } | ||
3617 | |||
3604 | static int __init io_apic_get_redir_entries(int ioapic) | 3618 | static int __init io_apic_get_redir_entries(int ioapic) |
3605 | { | 3619 | { |
3606 | union IO_APIC_reg_01 reg_01; | 3620 | union IO_APIC_reg_01 reg_01; |
@@ -3655,8 +3669,8 @@ int __init arch_probe_nr_irqs(void) | |||
3655 | } | 3669 | } |
3656 | #endif | 3670 | #endif |
3657 | 3671 | ||
3658 | static int __io_apic_set_pci_routing(struct device *dev, int irq, | 3672 | int io_apic_set_pci_routing(struct device *dev, int irq, |
3659 | struct io_apic_irq_attr *irq_attr) | 3673 | struct io_apic_irq_attr *irq_attr) |
3660 | { | 3674 | { |
3661 | int node; | 3675 | int node; |
3662 | 3676 | ||
@@ -3668,28 +3682,7 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq, | |||
3668 | 3682 | ||
3669 | node = dev ? dev_to_node(dev) : cpu_to_node(0); | 3683 | node = dev ? dev_to_node(dev) : cpu_to_node(0); |
3670 | 3684 | ||
3671 | return io_apic_setup_irq_pin(irq, node, irq_attr); | 3685 | return io_apic_setup_irq_pin_once(irq, node, irq_attr); |
3672 | } | ||
3673 | |||
3674 | int io_apic_set_pci_routing(struct device *dev, int irq, | ||
3675 | struct io_apic_irq_attr *irq_attr) | ||
3676 | { | ||
3677 | int ioapic, pin; | ||
3678 | /* | ||
3679 | * Avoid pin reprogramming. PRTs typically include entries | ||
3680 | * with redundant pin->gsi mappings (but unique PCI devices); | ||
3681 | * we only program the IOAPIC on the first. | ||
3682 | */ | ||
3683 | ioapic = irq_attr->ioapic; | ||
3684 | pin = irq_attr->ioapic_pin; | ||
3685 | if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) { | ||
3686 | pr_debug("Pin %d-%d already programmed\n", | ||
3687 | mp_ioapics[ioapic].apicid, pin); | ||
3688 | return 0; | ||
3689 | } | ||
3690 | set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed); | ||
3691 | |||
3692 | return __io_apic_set_pci_routing(dev, irq, irq_attr); | ||
3693 | } | 3686 | } |
3694 | 3687 | ||
3695 | #ifdef CONFIG_X86_32 | 3688 | #ifdef CONFIG_X86_32 |