diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2014-06-09 16:20:04 +0800 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2014-06-21 23:05:44 +0200 |
commit | 16ee7b3dcc56be14b9a813612cff2cc2339cdced (patch) | |
tree | d9af7dfef67c95ade1dacc7dc1fc9f1dac3aa944 /arch/x86/kernel/apic | |
parent | 9f354b0252b81c870ac7534d71906280cb573f86 (diff) |
x86, irq: Simplify the way to handle ISA IRQ
On startup, setup_IO_APIC_irqs() will program all IOAPIC pins for ISA
IRQs. Later when mp_map_pin_to_irq() is called, it just returns ISA IRQ
number without programming corresponding IOAPIC pin.
This patch consolidates the way to program IOAPIC pins for both ISA and
non-ISA IRQs into mp_map_pin_to_irq() as below:
1) For ISA IRQs, mp_irqs array is used to map IOAPIC pin to IRQ and
mp_irqdomain_map() is used to actually program the pin.
2) For non-ISA IRQs, irqdomain is used to map IOAPIC pin to IRQ, and
mp_irqdomain_map() is also used to actually program the pin.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <len.brown@intel.com>
Cc: Pavel Machek <pavel@ucw.cz>
Link: http://lkml.kernel.org/r/1402302011-23642-36-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/apic')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 98 |
1 files changed, 38 insertions, 60 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 6e3d4c771832..8485d904b653 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -204,8 +204,6 @@ static int __init parse_noapic(char *str) } early_param("noapic", parse_noapic); -static int io_apic_setup_irq_pin(unsigned int irq, int node, - struct io_apic_irq_attr *attr); static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node); /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ @@ -1021,6 +1019,16 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, struct irq_domain *domain = mp_ioapic_irqdomain(ioapic); struct mp_pin_info *info = mp_pin_info(ioapic, pin); + if (!domain) { + /* + * Provide an identity mapping of gsi == irq except on truly + * weird platforms that have non isa irqs in the first 16 gsis. + */ + return gsi >= nr_legacy_irqs() ? gsi : gsi_top + gsi; + } + + mutex_lock(&ioapic_mutex); + /* * Don't use irqdomain to manage ISA IRQs because there may be * multiple IOAPIC pins sharing the same ISA IRQ number and @@ -1033,28 +1041,30 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, * the interrupt routing logic. Thus there may be multiple pins * sharing the same legacy IRQ number when ACPI is disabled. */ - if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) - return mp_irqs[idx].srcbusirq; - - if (!domain) { - /* - * Provide an identity mapping of gsi == irq except on truly - * weird platforms that have non isa irqs in the first 16 gsis. - */ - return gsi >= nr_legacy_irqs() ? gsi : gsi_top + gsi; + if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) { + irq = mp_irqs[idx].srcbusirq; + if (flags & IOAPIC_MAP_ALLOC) { + if (info->count == 0 && + mp_irqdomain_map(domain, irq, pin) != 0) + irq = -1; + + /* special handling for timer IRQ0 */ + if (irq == 0) + info->count++; + } + } else { + irq = irq_find_mapping(domain, pin); + if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC)) + irq = alloc_irq_from_domain(domain, gsi, pin); } - mutex_lock(&ioapic_mutex); - irq = irq_find_mapping(domain, pin); - if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC)) - irq = alloc_irq_from_domain(domain, gsi, pin); - if (flags & IOAPIC_MAP_ALLOC) { if (irq > 0) info->count++; else if (info->count == 0) info->set = 0; } + mutex_unlock(&ioapic_mutex); return irq > 0 ? irq : -1; @@ -1471,55 +1481,23 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry); } -static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin) -{ - if (idx != -1) - return false; - - apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n", - mpc_ioapic_id(ioapic_idx), pin); - return true; -} - -static void __init __io_apic_setup_irqs(unsigned int ioapic_idx) -{ - int idx, node = cpu_to_node(0); - struct io_apic_irq_attr attr; - unsigned int pin, irq; - - for_each_pin(ioapic_idx, pin) { - idx = find_irq_entry(ioapic_idx, pin, mp_INT); - if (io_apic_pin_not_connected(idx, ioapic_idx, pin)) - continue; - - irq = pin_2_irq(idx, ioapic_idx, pin, - ioapic_idx ? 0 : IOAPIC_MAP_ALLOC); - if (irq < 0 || !mp_init_irq_at_boot(ioapic_idx, irq)) - continue; - - /* - * Skip the timer IRQ if there's a quirk handler - * installed and if it returns 1: - */ - if (apic->multi_timer_check && - apic->multi_timer_check(ioapic_idx, irq)) - continue; - - set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx), - irq_polarity(idx)); - - io_apic_setup_irq_pin(irq, node, &attr); - } -} - static void __init setup_IO_APIC_irqs(void) { - unsigned int ioapic_idx; + unsigned int ioapic, pin; + int idx; apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); - for_each_ioapic(ioapic_idx) - __io_apic_setup_irqs(ioapic_idx); + for_each_ioapic_pin(ioapic, pin) { + idx = find_irq_entry(ioapic, pin, mp_INT); + if (idx < 0) + apic_printk(APIC_VERBOSE, + KERN_DEBUG " apic %d pin %d not connected\n", + mpc_ioapic_id(ioapic), pin); + else + pin_2_irq(idx, ioapic, pin, + ioapic ? 0 : IOAPIC_MAP_ALLOC); + } } /* |