2014-06-09 08:17:09

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 00/42] use irqdomain to dynamically allocate IRQ for IOAPIC

On x86 platforms, IRQ number are statically allocated to IOAPIC pins at boot.
There are two issues with this design. First it causes trouble to IOAPIC
hotplug because we need to allocate a block of IRQ numbers for each IOAPIC.
Second it may waste IRQ nubmers even if some IOAPIC pins are not used because
IRQ numbers are statically assigned.

This patchset tries to enable dynamic IRQ number allocation for IOAPIC
by adopting the irqdomain framework, it solves the two issues mentioned
above. It also simplifies the IOAPIC driver by consolidating ways to
program IOAPIC pins with the irqdomain map interface.

We will enhance the IOAPIC driver core to support ACPI based IOAPIC hotplug
once the IOAPIC driver has been converted to irqdomain.

This patchset applies to tip/irq/core and you may pull from
https://github.com/jiangliu/linux.git ioapic/irqdomain_v4

The patchset has been tested on a two socket 64 bit Intel platforms with:
1) ACPI and mpparse enabled (boot successfully)
2) Mpparse enabled with ACPI disabled (boot successfully)
3) ACPI enabled with Mpparse disabled (boot successfully)
4) boot parameter "pci=nomsi"
5) boot parameter "acpi=noirq"
6) boot parameter "pci=noacpi"
7) UP mode (SMP disabled)

It has also been tested on an one socket laptop with 32bit Ubuntu with:
1) ACPI and mpparse enabled (boot successfully)
2) Mpparse enabled with ACPI disabled (boot successfully)
3) ACPI enabled with Mpparse disabled (boot successfully)
4) boot parameter "pci=nomsi"
5) boot parameter "acpi=noirq"
6) boot parameter "pci=noacpi"
7) UP mode (SMP disabled)
8) UP mode with IOAPIC disabled

It also builds successfully (but without booting due to hardware resource
constraints) for 32 bit platforms with following configuraitons:
1) SFI enabled
2) devicetree (CE4100) enabled

V3->V4
1) simplify interfaces/implementation to enable irqdomain for IOAPIC
2) clean up usage of NR_IRQS_LEGACY
3) refine support of CE4100
4) address review comments from last round of review

V2->V3
1) Implement irqdomain unmap() interface and free IRQ when it's not used
2) Fix posssible conflicts with native and PV Xen IRQ management
3) Fix build errors on CE4100
4) Code quality and readability improvement

V1->V2
1) Rebase to tip/irq/core
2) reorder patches to put bugfixes at the head
3) fix bug in handling shared ISA IRQs
4) refine commit messages

Patch 1 is simple bugfix for MSI.

Patch 2-20 are trivial code improvements, bugfixes and preparation.

Patch 21-28 enable basic irqdomain support and IRQ number dynamic
allocation.

Patch 29-33 consoldate the way to program IOAPIC pins by using
irqdomain map() interface.

Patch 34-35 cleans up unused interfaces and functions in IOAPIC driver.

Patch 36-41 implement irqdoamin unmap() interfaces and free IRQ when
it's not used

Patch 42 is a simple clean up

Tests and comments are warmly welcomed!

Jiang Liu (42):
x86, irq: update high address field when updating affinity for MSI
IRQ
x86, mpparse: use pr_lvl() helper utilities to replace
printk(KERN_LVL)
x86, mpparse: simplify arch/x86/include/asm/mpspec.h
x86, acpi: reorganize code to avoid forward declaration in boot.c
x86, PCI, ACPI: use kmalloc_node() to optimize for performance
x86, acpi, irq: kill static function irq_to_gsi()
x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c
x86, ACPI, irq: enhance error handling in function
acpi_register_gsi()
x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy
IRQ
x86, irq, trivial: minor improvements of IRQ related code
x86, ioapic: kill unused global variable timer_through_8259
x86, ioapic: kill static variable nr_irqs_gsi
x86, ioapic: introduce helper utilities to walk ioapics and pins
x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better
readability
x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for
irqdomain
x86, irq: introduce some helper utilities to improve readability
ce4100, irq: make CE4100 depend on CONFIG_X86_IO_APIC
ce4100, irq: do not set legacy_pic to null_legacy_pic
x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of
NR_IRQS_LEGACY
x86, irq: simplify arch_early_irq_init()
x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ
number
x86, irq, ACPI: change __acpi_register_gsi to return IRQ number
instead of GSI
x86, irq: introduce mechanisms to support dynamically allocate IRQ
for IOAPIC
x86, irq: enhance mp_register_ioapic() to support irqdomain
x86, ACPI, irq: provide basic irqdomain support
x86, mpparse, irq: provide basic irqdomain support
x86, SFI, irq: provide basic irqdomain support
x86, devicetree, irq: use common mechanism to support irqdomain
x86, irq: introduce two helper functions to support irqdomain map
operation
x86, irq, ACPI: use common irqdomain map interface to program IOAPIC
pins
x86, irq, mpparse: use common irqdomain map interface to program
IOAPIC pins
x86, irq, SFI: use common irqdomain map interface to program IOAPIC
pins
x86, irq, devicetree: use common irqdomain map interface to program
IOAPIC pins
x86, irq: clean up unused IOAPIC interface
x86, irq: simplify the way to handle ISA IRQ
genirq: export irq_domain_disassociate() to architecture interrupt
drivers
x86, irq: introduce helper functions to release IOAPIC pin
x86, irq, ACPI: release IOAPIC pin when PCI device is disabled
x86, irq, mpparse: release IOAPIC pin when PCI device is disabled
x86, irq, SFI: release IOAPIC pin when PCI device is disabled
x86, irq, devicetree: release IOAPIC pin when PCI device is disabled
x86, irq: clean up irqdomain transition code

arch/x86/Kconfig | 2 +
arch/x86/include/asm/apic.h | 4 +-
arch/x86/include/asm/hardirq.h | 3 -
arch/x86/include/asm/i8259.h | 5 +
arch/x86/include/asm/io_apic.h | 56 +--
arch/x86/include/asm/mpspec.h | 13 -
arch/x86/include/asm/prom.h | 2 -
arch/x86/kernel/acpi/boot.c | 400 +++++++++----------
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/apic/io_apic.c | 779 +++++++++++++++++++++++--------------
arch/x86/kernel/devicetree.c | 211 ++++------
arch/x86/kernel/irqinit.c | 12 +-
arch/x86/kernel/mpparse.c | 108 ++---
arch/x86/pci/acpi.c | 6 +-
arch/x86/pci/intel_mid_pci.c | 27 +-
arch/x86/pci/irq.c | 15 +-
arch/x86/pci/xen.c | 7 +-
arch/x86/platform/ce4100/ce4100.c | 11 +-
arch/x86/platform/intel-mid/sfi.c | 56 ++-
arch/x86/platform/sfi/sfi.c | 10 +-
drivers/acpi/pci_irq.c | 3 +-
include/linux/irqdomain.h | 2 +
kernel/irq/irqdomain.c | 2 +-
23 files changed, 919 insertions(+), 817 deletions(-)

--
1.7.10.4


2014-06-09 08:17:19

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 01/42] x86, irq: update high address field when updating affinity for MSI IRQ

If x2apic is enabled, the MSI high address field should also be aslo
updated when setting affinity for MSI IRQ, otherwise the MSI IRQ may
target wrong APIC IDs.

Signed-off-by: Jiang Liu <[email protected]>
Cc: [email protected]
---
arch/x86/kernel/apic/io_apic.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 9d0a9795a0f8..2de992501a1b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3007,6 +3007,10 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)

__get_cached_msi_msg(data->msi_desc, &msg);

+ msg.address_hi = MSI_ADDR_BASE_HI;
+ if (x2apic_enabled())
+ msg.address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
+
msg.data &= ~MSI_DATA_VECTOR_MASK;
msg.data |= MSI_DATA_VECTOR(cfg->vector);
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
--
1.7.10.4

2014-06-09 08:17:28

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 02/42] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL)

Use pr_lvl() helper utilities to replace printk(KERN_LVL) for readability,
no function changes. Also use pr_cont() to avoid multiple newlines in
one printk().

Acked-by: David Rientjes <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/mpparse.c | 95 +++++++++++++++++++++------------------------
1 file changed, 44 insertions(+), 51 deletions(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index d2b56489d70f..b10e1132f316 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -67,7 +67,7 @@ static void __init MP_processor_info(struct mpc_cpu *m)
boot_cpu_physical_apicid = m->apicid;
}

- printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
+ pr_info("Processor #%d%s\n", m->apicid, bootup_cpu);
generic_processor_info(apicid, m->apicver);
}

@@ -87,9 +87,8 @@ static void __init MP_bus_info(struct mpc_bus *m)

#if MAX_MP_BUSSES < 256
if (m->busid >= MAX_MP_BUSSES) {
- printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
- " is too large, max. supported is %d\n",
- m->busid, str, MAX_MP_BUSSES - 1);
+ pr_warn("MP table busid value (%d) for bustype %s is too large, max. supported is %d\n",
+ m->busid, str, MAX_MP_BUSSES - 1);
return;
}
#endif
@@ -110,7 +109,7 @@ static void __init MP_bus_info(struct mpc_bus *m)
mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
#endif
} else
- printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+ pr_warn("Unknown bustype %s - ignoring\n", str);
}

static void __init MP_ioapic_info(struct mpc_ioapic *m)
@@ -121,8 +120,8 @@ static void __init MP_ioapic_info(struct mpc_ioapic *m)

static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
{
- apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
- " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ apic_printk(APIC_VERBOSE,
+ "Int: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC INT %02x\n",
mp_irq->irqtype, mp_irq->irqflag & 3,
(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
@@ -135,8 +134,8 @@ static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}

static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
{
- apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
- " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+ apic_printk(APIC_VERBOSE,
+ "Lint: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC LINT %02x\n",
m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
m->srcbusirq, m->destapic, m->destapiclint);
}
@@ -148,34 +147,33 @@ static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
{

if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
- printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
+ pr_err("MPTABLE: bad signature [%c%c%c%c]!\n",
mpc->signature[0], mpc->signature[1],
mpc->signature[2], mpc->signature[3]);
return 0;
}
if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
- printk(KERN_ERR "MPTABLE: checksum error!\n");
+ pr_err("MPTABLE: checksum error!\n");
return 0;
}
if (mpc->spec != 0x01 && mpc->spec != 0x04) {
- printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
- mpc->spec);
+ pr_err("MPTABLE: bad table version (%d)!!\n", mpc->spec);
return 0;
}
if (!mpc->lapic) {
- printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+ pr_err("MPTABLE: null local APIC address!\n");
return 0;
}
memcpy(oem, mpc->oem, 8);
oem[8] = 0;
- printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
+ pr_info("MPTABLE: OEM ID: %s\n", oem);

memcpy(str, mpc->productid, 12);
str[12] = 0;

- printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+ pr_info("MPTABLE: Product ID: %s\n", str);

- printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
+ pr_info("MPTABLE: APIC at: 0x%X\n", mpc->lapic);

return 1;
}
@@ -188,8 +186,8 @@ static void skip_entry(unsigned char **ptr, int *count, int size)

static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
{
- printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
- "type %x\n", *mpt);
+ pr_err("Your mptable is wrong, contact your HW vendor!\n");
+ pr_cont("type %x\n", *mpt);
print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
1, mpc, mpc->length, 1);
}
@@ -259,7 +257,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
}

if (!num_processors)
- printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ pr_err("MPTABLE: no processors registered!\n");
return num_processors;
}

@@ -295,16 +293,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
* If it does, we assume it's valid.
*/
if (mpc_default_type == 5) {
- printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
- "falling back to ELCR\n");
+ pr_info("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");

if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
ELCR_trigger(13))
- printk(KERN_ERR "ELCR contains invalid data... "
- "not using ELCR\n");
+ pr_err("ELCR contains invalid data... not using ELCR\n");
else {
- printk(KERN_INFO
- "Using ELCR to identify PCI interrupts\n");
+ pr_info("Using ELCR to identify PCI interrupts\n");
ELCR_fallback = 1;
}
}
@@ -353,7 +348,7 @@ static void __init construct_ioapic_table(int mpc_default_type)
bus.busid = 0;
switch (mpc_default_type) {
default:
- printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+ pr_err("???\nUnknown standard configuration %d\n",
mpc_default_type);
/* fall through */
case 1:
@@ -462,8 +457,8 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
#ifdef CONFIG_X86_LOCAL_APIC
smp_found_config = 0;
#endif
- printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
- "... disabling SMP support. (tell your hw vendor)\n");
+ pr_err("BIOS bug, MP table errors detected!...\n");
+ pr_cont("... disabling SMP support. (tell your hw vendor)\n");
early_iounmap(mpc, size);
return -1;
}
@@ -481,8 +476,7 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
if (!mp_irq_entries) {
struct mpc_bus bus;

- printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
- "using default mptable. (tell your hw vendor)\n");
+ pr_err("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");

bus.type = MP_BUS;
bus.busid = 0;
@@ -516,14 +510,14 @@ void __init default_get_smp_config(unsigned int early)
if (acpi_lapic && acpi_ioapic)
return;

- printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
- mpf->specification);
+ pr_info("Intel MultiProcessor Specification v1.%d\n",
+ mpf->specification);
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
if (mpf->feature2 & (1 << 7)) {
- printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
+ pr_info(" IMCR and PIC compatibility mode.\n");
pic_mode = 1;
} else {
- printk(KERN_INFO " Virtual Wire compatibility mode.\n");
+ pr_info(" Virtual Wire compatibility mode.\n");
pic_mode = 0;
}
#endif
@@ -539,8 +533,7 @@ void __init default_get_smp_config(unsigned int early)
return;
}

- printk(KERN_INFO "Default MP configuration #%d\n",
- mpf->feature1);
+ pr_info("Default MP configuration #%d\n", mpf->feature1);
construct_default_ISA_mptable(mpf->feature1);

} else if (mpf->physptr) {
@@ -550,7 +543,7 @@ void __init default_get_smp_config(unsigned int early)
BUG();

if (!early)
- printk(KERN_INFO "Processors: %d\n", num_processors);
+ pr_info("Processors: %d\n", num_processors);
/*
* Only use the first configuration found.
*/
@@ -583,10 +576,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
#endif
mpf_found = mpf;

- printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
- (unsigned long long) virt_to_phys(mpf),
- (unsigned long long) virt_to_phys(mpf) +
- sizeof(*mpf) - 1, mpf);
+ pr_info("found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
+ (unsigned long long) virt_to_phys(mpf),
+ (unsigned long long) virt_to_phys(mpf) +
+ sizeof(*mpf) - 1, mpf);

mem = virt_to_phys(mpf);
memblock_reserve(mem, sizeof(*mpf));
@@ -735,7 +728,7 @@ static int __init replace_intsrc_all(struct mpc_table *mpc,
int nr_m_spare = 0;
unsigned char *mpt = ((unsigned char *)mpc) + count;

- printk(KERN_INFO "mpc_length %x\n", mpc->length);
+ pr_info("mpc_length %x\n", mpc->length);
while (count < mpc->length) {
switch (*mpt) {
case MP_PROCESSOR:
@@ -862,13 +855,13 @@ static int __init update_mp_table(void)
if (!smp_check_mpc(mpc, oem, str))
return 0;

- printk(KERN_INFO "mpf: %llx\n", (u64)virt_to_phys(mpf));
- printk(KERN_INFO "physptr: %x\n", mpf->physptr);
+ pr_info("mpf: %llx\n", (u64)virt_to_phys(mpf));
+ pr_info("physptr: %x\n", mpf->physptr);

if (mpc_new_phys && mpc->length > mpc_new_length) {
mpc_new_phys = 0;
- printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
- mpc_new_length);
+ pr_info("mpc_new_length is %ld, please use alloc_mptable=8k\n",
+ mpc_new_length);
}

if (!mpc_new_phys) {
@@ -879,10 +872,10 @@ static int __init update_mp_table(void)
mpc->checksum = 0xff;
new = mpf_checksum((unsigned char *)mpc, mpc->length);
if (old == new) {
- printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+ pr_info("mpc is readonly, please try alloc_mptable instead\n");
return 0;
}
- printk(KERN_INFO "use in-position replacing\n");
+ pr_info("use in-position replacing\n");
} else {
mpf->physptr = mpc_new_phys;
mpc_new = phys_to_virt(mpc_new_phys);
@@ -892,7 +885,7 @@ static int __init update_mp_table(void)
if (mpc_new_phys - mpf->physptr) {
struct mpf_intel *mpf_new;
/* steal 16 bytes from [0, 1k) */
- printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+ pr_info("mpf new: %x\n", 0x400 - 16);
mpf_new = phys_to_virt(0x400 - 16);
memcpy(mpf_new, mpf, 16);
mpf = mpf_new;
@@ -900,7 +893,7 @@ static int __init update_mp_table(void)
}
mpf->checksum = 0;
mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
- printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
+ pr_info("physptr new: %x\n", mpf->physptr);
}

/*
--
1.7.10.4

2014-06-09 08:17:52

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 03/42] x86, mpparse: simplify arch/x86/include/asm/mpspec.h

Simplify arch/x86/include/asm/mpspec.h by
1) Change max_physical_apicid to static as it's only used in apic.c.
2) Kill declaration of mpc_default_type, it's never defined.
3) Delete default_acpi_madt_oem_check(), it has already been declared
in apic.h.
4) Make default_acpi_madt_oem_check() depends on CONFIG_X86_LOCAL_APIC
instead of CONFIG_X86_64 to support i386.
5) Change mp_override_legacy_irq(), mp_config_acpi_legacy_irqs() and
mp_register_gsi() as static because they are only used in acpi/boot.c.

Acked-by: David Rientjes <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/apic.h | 4 ++--
arch/x86/include/asm/io_apic.h | 3 ---
arch/x86/include/asm/mpspec.h | 13 -------------
arch/x86/kernel/acpi/boot.c | 12 +++++++++---
arch/x86/kernel/apic/apic.c | 2 +-
5 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 19b0ebafcd3e..69ed79aa9085 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -502,8 +502,6 @@ static inline unsigned default_get_apic_id(unsigned long x)
#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469

#ifdef CONFIG_X86_64
-extern int default_acpi_madt_oem_check(char *, char *);
-
extern void apic_send_IPI_self(int vector);

DECLARE_PER_CPU(int, x2apic_extra_bits);
@@ -552,6 +550,8 @@ static inline int default_apic_id_valid(int apicid)
return (apicid < 255);
}

+extern int default_acpi_madt_oem_check(char *, char *);
+
extern void default_setup_apic_routing(void);

extern struct apic apic_noop;
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 90f97b4b9347..9121abbc8c8f 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -118,9 +118,6 @@ extern int mp_irq_entries;
/* MP IRQ source entries */
extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];

-/* non-0 if default (table-less) MP configuration */
-extern int mpc_default_type;
-
/* Older SiS APIC requires we rewrite the index register */
extern int sis_apic_bug;

diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index f5a617956735..7bef40a01a1d 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -40,8 +40,6 @@ extern int mp_bus_id_to_type[MAX_MP_BUSSES];
extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);

extern unsigned int boot_cpu_physical_apicid;
-extern unsigned int max_physical_apicid;
-extern int mpc_default_type;
extern unsigned long mp_lapic_addr;

#ifdef CONFIG_X86_LOCAL_APIC
@@ -88,15 +86,6 @@ static inline void early_reserve_e820_mpc_new(void) { }
#endif

int generic_processor_info(int apicid, int version);
-#ifdef CONFIG_ACPI
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
-extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi);
-extern void mp_config_acpi_legacy_irqs(void);
-struct device;
-extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
- int active_high_low);
-#endif /* CONFIG_ACPI */

#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_LOCAL_APIC)

@@ -163,6 +152,4 @@ extern physid_mask_t phys_cpu_present_map;

extern int generic_mps_oem_check(struct mpc_table *, char *, char *);

-extern int default_acpi_madt_oem_check(char *, char *);
-
#endif /* _ASM_X86_MPSPEC_H */
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 86281ffb96d6..b41b47021f53 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -345,6 +345,10 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
#endif /*CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
+static void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi);
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity);

static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
@@ -903,7 +907,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
#ifdef CONFIG_X86_IO_APIC
#define MP_ISA_BUS 0

-void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi)
{
int ioapic;
int pin;
@@ -938,7 +943,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
isa_irq_to_gsi[bus_irq] = gsi;
}

-void __init mp_config_acpi_legacy_irqs(void)
+static void __init mp_config_acpi_legacy_irqs(void)
{
int i;
struct mpc_intsrc mp_irq;
@@ -1040,7 +1045,8 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
return 0;
}

-int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
{
int ioapic;
int ioapic_pin;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ad28db7e6bde..ca1bd75e3de2 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
/*
* The highest APIC ID seen during enumeration.
*/
-unsigned int max_physical_apicid;
+static unsigned int max_physical_apicid;

/*
* Bitmask of physically existing CPUs:
--
1.7.10.4

2014-06-09 08:17:59

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 04/42] x86, acpi: reorganize code to avoid forward declaration in boot.c

Reorganize code to avoid forward declaration in boot.c, no function
changes.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 236 +++++++++++++++++++++----------------------
1 file changed, 116 insertions(+), 120 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b41b47021f53..ceb3b36f2b2c 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -345,10 +345,123 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
#endif /*CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
-static void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi);
+#define MP_ISA_BUS 0
+
+static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi)
+{
+ int ioapic;
+ int pin;
+ struct mpc_intsrc mp_irq;
+
+ /*
+ * Convert 'gsi' to 'ioapic.pin'.
+ */
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return;
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+
+ /*
+ * TBD: This check is for faulty timer entries, where the override
+ * erroneously sets the trigger to level, resulting in a HUGE
+ * increase of timer interrupts!
+ */
+ if ((bus_irq == 0) && (trigger == 3))
+ trigger = 1;
+
+ mp_irq.type = MP_INTSRC;
+ mp_irq.irqtype = mp_INT;
+ mp_irq.irqflag = (trigger << 2) | polarity;
+ mp_irq.srcbus = MP_ISA_BUS;
+ mp_irq.srcbusirq = bus_irq; /* IRQ */
+ mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
+ mp_irq.dstirq = pin; /* INTIN# */
+
+ mp_save_irq(&mp_irq);
+
+ isa_irq_to_gsi[bus_irq] = gsi;
+}
+
+static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
+{
+#ifdef CONFIG_X86_MPPARSE
+ struct mpc_intsrc mp_irq;
+ struct pci_dev *pdev;
+ unsigned char number;
+ unsigned int devfn;
+ int ioapic;
+ u8 pin;
+
+ if (!acpi_ioapic)
+ return 0;
+ if (!dev || !dev_is_pci(dev))
+ return 0;
+
+ pdev = to_pci_dev(dev);
+ number = pdev->bus->number;
+ devfn = pdev->devfn;
+ pin = pdev->pin;
+ /* print the entry should happen on mptable identically */
+ mp_irq.type = MP_INTSRC;
+ mp_irq.irqtype = mp_INT;
+ mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ mp_irq.srcbus = number;
+ mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ mp_irq.dstapic = mpc_ioapic_id(ioapic);
+ mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+
+ mp_save_irq(&mp_irq);
+#endif
+ return 0;
+}
+
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity);
+ int polarity)
+{
+ int ioapic;
+ int ioapic_pin;
+ struct io_apic_irq_attr irq_attr;
+ int ret;
+
+ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ return gsi;
+
+ /* Don't set up the ACPI SCI because it's already set up */
+ if (acpi_gbl_FADT.sci_interrupt == gsi)
+ return gsi;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0) {
+ printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+ return gsi;
+ }
+
+ ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
+
+ if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
+ printk(KERN_ERR "Invalid reference to IOAPIC pin "
+ "%d-%d\n", mpc_ioapic_id(ioapic),
+ ioapic_pin);
+ return gsi;
+ }
+
+ if (enable_update_mptable)
+ mp_config_acpi_gsi(dev, gsi, trigger, polarity);
+
+ set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
+ trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
+ polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+ ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ if (ret < 0)
+ gsi = INT_MIN;
+
+ return gsi;
+}
+

static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
@@ -905,44 +1018,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
#endif /* CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
-#define MP_ISA_BUS 0
-
-static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi)
-{
- int ioapic;
- int pin;
- struct mpc_intsrc mp_irq;
-
- /*
- * Convert 'gsi' to 'ioapic.pin'.
- */
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0)
- return;
- pin = mp_find_ioapic_pin(ioapic, gsi);
-
- /*
- * TBD: This check is for faulty timer entries, where the override
- * erroneously sets the trigger to level, resulting in a HUGE
- * increase of timer interrupts!
- */
- if ((bus_irq == 0) && (trigger == 3))
- trigger = 1;
-
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger << 2) | polarity;
- mp_irq.srcbus = MP_ISA_BUS;
- mp_irq.srcbusirq = bus_irq; /* IRQ */
- mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
- mp_irq.dstirq = pin; /* INTIN# */
-
- mp_save_irq(&mp_irq);
-
- isa_irq_to_gsi[bus_irq] = gsi;
-}
-
static void __init mp_config_acpi_legacy_irqs(void)
{
int i;
@@ -1009,85 +1084,6 @@ static void __init mp_config_acpi_legacy_irqs(void)
}
}

-static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity)
-{
-#ifdef CONFIG_X86_MPPARSE
- struct mpc_intsrc mp_irq;
- struct pci_dev *pdev;
- unsigned char number;
- unsigned int devfn;
- int ioapic;
- u8 pin;
-
- if (!acpi_ioapic)
- return 0;
- if (!dev || !dev_is_pci(dev))
- return 0;
-
- pdev = to_pci_dev(dev);
- number = pdev->bus->number;
- devfn = pdev->devfn;
- pin = pdev->pin;
- /* print the entry should happen on mptable identically */
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
- (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
- mp_irq.srcbus = number;
- mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
- ioapic = mp_find_ioapic(gsi);
- mp_irq.dstapic = mpc_ioapic_id(ioapic);
- mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
-
- mp_save_irq(&mp_irq);
-#endif
- return 0;
-}
-
-static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity)
-{
- int ioapic;
- int ioapic_pin;
- struct io_apic_irq_attr irq_attr;
- int ret;
-
- if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
- return gsi;
-
- /* Don't set up the ACPI SCI because it's already set up */
- if (acpi_gbl_FADT.sci_interrupt == gsi)
- return gsi;
-
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0) {
- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
- return gsi;
- }
-
- ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-
- if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mpc_ioapic_id(ioapic),
- ioapic_pin);
- return gsi;
- }
-
- if (enable_update_mptable)
- mp_config_acpi_gsi(dev, gsi, trigger, polarity);
-
- set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
- trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
- if (ret < 0)
- gsi = INT_MIN;
-
- return gsi;
-}
-
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
--
1.7.10.4

2014-06-09 08:18:10

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 06/42] x86, acpi, irq: kill static function irq_to_gsi()

Static function irq_to_gsi() is only called by acpi_isa_irq_to_gsi(),
so kill function irq_to_gsi() and simplify acpi_isa_irq_to_gsi().

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 26 ++++++--------------------
1 file changed, 6 insertions(+), 20 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index ceb3b36f2b2c..09682766d56a 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -120,22 +120,6 @@ static unsigned int gsi_to_irq(unsigned int gsi)
return irq;
}

-static u32 irq_to_gsi(int irq)
-{
- unsigned int gsi;
-
- if (irq < NR_IRQS_LEGACY)
- gsi = isa_irq_to_gsi[irq];
- else if (irq < gsi_top)
- gsi = irq;
- else if (irq < (gsi_top + NR_IRQS_LEGACY))
- gsi = irq - gsi_top;
- else
- gsi = 0xffffffff;
-
- return gsi;
-}
-
/*
* This is just a simple wrapper around early_ioremap(),
* with sanity checks for phys == 0 and size == 0.
@@ -640,10 +624,12 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq >= 16)
- return -1;
- *gsi = irq_to_gsi(isa_irq);
- return 0;
+ if (isa_irq < NR_IRQS_LEGACY) {
+ *gsi = isa_irq_to_gsi[isa_irq];
+ return 0;
+ }
+
+ return -1;
}

static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
--
1.7.10.4

2014-06-09 08:18:25

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 07/42] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c

1) Remove out-of-date comment
2) Kill unused function acpi_set_irq_model_pic()
3) Use NR_IRQS_LEGACY instead of hard-coded 16
4) Trivial syntax improvements

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 50 ++++++++++++++-----------------------------
1 file changed, 16 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 09682766d56a..392360c607dc 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -483,11 +483,6 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;

- /*
- * mp_config_acpi_legacy_irqs() already setup IRQs < 16
- * If GSI is < 16, this will update its flags,
- * else it will create a new mp_irqs[] entry.
- */
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);

/*
@@ -686,14 +681,7 @@ void acpi_unregister_gsi(u32 gsi)
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);

-void __init acpi_set_irq_model_pic(void)
-{
- acpi_irq_model = ACPI_IRQ_MODEL_PIC;
- __acpi_register_gsi = acpi_register_gsi_pic;
- acpi_ioapic = 0;
-}
-
-void __init acpi_set_irq_model_ioapic(void)
+static void __init acpi_set_irq_model_ioapic(void)
{
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
__acpi_register_gsi = acpi_register_gsi_ioapic;
@@ -932,9 +920,8 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -959,9 +946,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -989,11 +975,10 @@ static int __init acpi_parse_madt_lapic_entries(void)
return count;
}

- x2count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
- acpi_parse_x2apic_nmi, 0);
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
+ x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
+ acpi_parse_x2apic_nmi, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI,
+ acpi_parse_lapic_nmi, 0);
if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -1022,7 +1007,7 @@ static void __init mp_config_acpi_legacy_irqs(void)
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < NR_IRQS_LEGACY; i++) {
int ioapic, pin;
unsigned int dstapic;
int idx;
@@ -1099,9 +1084,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return -ENODEV;
}

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
- MAX_IO_APICS);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
+ MAX_IO_APICS);
if (!count) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV;
@@ -1110,9 +1094,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return count;
}

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+ acpi_parse_int_src_ovr, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing interrupt source overrides entry\n");
@@ -1131,9 +1114,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
/* Fill in identity legacy mappings where no override */
mp_config_acpi_legacy_irqs();

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
+ acpi_parse_nmi_src, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
--
1.7.10.4

2014-06-09 08:18:49

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 08/42] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()

Function mp_register_gsi() may return invalid GSI if error happens,
so enhance acpi_register_gsi() to handle possible error cases.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 392360c607dc..f201579cd0df 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -97,6 +97,8 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};

+#define ACPI_INVALID_GSI INT_MIN
+
static unsigned int gsi_to_irq(unsigned int gsi)
{
unsigned int irq = gsi + NR_IRQS_LEGACY;
@@ -441,7 +443,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
if (ret < 0)
- gsi = INT_MIN;
+ gsi = ACPI_INVALID_GSI;

return gsi;
}
@@ -666,13 +668,13 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int irq;
unsigned int plat_gsi = gsi;

plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
- irq = gsi_to_irq(plat_gsi);
+ if (plat_gsi != ACPI_INVALID_GSI)
+ return gsi_to_irq(plat_gsi);

- return irq;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

--
1.7.10.4

2014-06-09 08:18:56

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 10/42] x86, irq, trivial: minor improvements of IRQ related code

1) Kill unused MAX_HARDIRQS_PER_CPU.
2) Improve function prototype declararions.
3) Simple typo fix, change "gsit" to "gsi".
4) Use macro VECTOR_UNDEFINED instead of hard-coded -1.
5) Kill redundant comments.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/hardirq.h | 3 ---
arch/x86/include/asm/io_apic.h | 16 +++++++---------
arch/x86/kernel/apic/io_apic.c | 21 +++++----------------
3 files changed, 12 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 230853da4ec0..0f5fb6b6567e 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -40,9 +40,6 @@ typedef struct {

DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);

-/* We can have at most NR_VECTORS irqs routed to a cpu at a time */
-#define MAX_HARDIRQS_PER_CPU NR_VECTORS
-
#define __ARCH_IRQ_STAT

#define inc_irq_stat(member) this_cpu_inc(irq_stat.member)
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 9121abbc8c8f..8dd1e13f2989 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -144,22 +144,20 @@ struct io_apic_irq_attr;
struct irq_cfg;
extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+extern void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_insert_resources(void);

extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
unsigned int, int,
struct io_apic_irq_attr *);
-extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
- unsigned int, int,
- struct io_apic_irq_attr *);
extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg);

extern void native_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id);
extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
-int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
+extern int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+ struct io_apic_irq_attr *attr);

extern int save_ioapic_entries(void);
extern void mask_ioapic_entries(void);
@@ -172,11 +170,11 @@ struct mp_ioapic_gsi{
u32 gsi_base;
u32 gsi_end;
};
-extern struct mp_ioapic_gsi mp_gsi_routing[];
extern u32 gsi_top;
-int mp_find_ioapic(u32 gsi);
-int mp_find_ioapic_pin(int ioapic, u32 gsi);
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+
+extern int mp_find_ioapic(u32 gsi);
+extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
+extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

extern void mp_save_irq(struct mpc_intsrc *m);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 2de992501a1b..d4aba16e6bbf 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1010,7 +1010,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
break;

if (!test_bit(lbus, mp_bus_not_pci) &&
- !mp_irqs[i].irqtype &&
+ mp_irqs[i].irqtype == mp_INT &&
(bus == lbus) &&
(slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
@@ -1359,7 +1359,7 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)

irq = pin_2_irq(idx, ioapic_idx, pin);

- if ((ioapic_idx > 0) && (irq > 16))
+ if ((ioapic_idx > 0) && (irq > NR_IRQS_LEGACY))
continue;

/*
@@ -1388,7 +1388,7 @@ static void __init setup_IO_APIC_irqs(void)
}

/*
- * for the gsit that is not in first ioapic
+ * for the gsi that is not in first ioapic
* but could not use acpi_register_gsi()
* like some special sci in IBM x3330
*/
@@ -2225,7 +2225,7 @@ asmlinkage __visible void smp_irq_move_cleanup_interrupt(void)
apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
goto unlock;
}
- __this_cpu_write(vector_irq[vector], -1);
+ __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
unlock:
raw_spin_unlock(&desc->lock);
}
@@ -2514,17 +2514,6 @@ static inline void init_IO_APIC_traps(void)
struct irq_cfg *cfg;
unsigned int irq;

- /*
- * NOTE! The local APIC isn't very good at handling
- * multiple interrupts at the same interrupt level.
- * As the interrupt level is determined by taking the
- * vector number and shifting that right by 4, we
- * want to spread these out a bit so that they don't
- * all fall in the same interrupt level.
- *
- * Also, we've got to be careful not to trash gate
- * 0x80, because int 0x80 is hm, kind of importantish. ;)
- */
for_each_active_irq(irq) {
cfg = irq_get_chip_data(irq);
if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
@@ -3546,7 +3535,7 @@ void __init setup_ioapic_dest(void)
continue;
irq = pin_2_irq(irq_entry, ioapic, pin);

- if ((ioapic > 0) && (irq > 16))
+ if ((ioapic > 0) && (irq > NR_IRQS_LEGACY))
continue;

idata = irq_get_irq_data(irq);
--
1.7.10.4

2014-06-09 08:19:05

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 11/42] x86, ioapic: kill unused global variable timer_through_8259

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/io_apic.h | 4 ----
arch/x86/kernel/apic/io_apic.c | 3 ---
2 files changed, 7 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 8dd1e13f2989..de3d8b04cf64 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -130,9 +130,6 @@ extern int noioapicquirk;
/* -1 if "noapic" boot option passed */
extern int noioapicreroute;

-/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
-extern int timer_through_8259;
-
/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
@@ -212,7 +209,6 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);

#define io_apic_assign_pci_irqs 0
#define setup_ioapic_ids_from_mpc x86_init_noop
-static const int timer_through_8259 = 0;
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index d4aba16e6bbf..94a56c233e87 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2638,8 +2638,6 @@ static int __init disable_timer_pin_setup(char *arg)
}
early_param("disable_timer_pin_1", disable_timer_pin_setup);

-int timer_through_8259 __initdata;
-
/*
* This code may look a bit paranoid, but it's supposed to cooperate with
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
@@ -2744,7 +2742,6 @@ static inline void __init check_timer(void)
legacy_pic->unmask(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
- timer_through_8259 = 1;
goto out;
}
/*
--
1.7.10.4

2014-06-09 08:19:28

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 14/42] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability

Use defined helper function irq_cfg() instead of irq_get_chip_data() for
better readability.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 8de9a837790b..0b2fb2aac7a6 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -230,7 +230,7 @@ int __init arch_early_irq_init(void)
return 0;
}

-static struct irq_cfg *irq_cfg(unsigned int irq)
+static inline struct irq_cfg *irq_cfg(unsigned int irq)
{
return irq_get_chip_data(irq);
}
@@ -272,7 +272,7 @@ static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
if (res < 0) {
if (res != -EEXIST)
return NULL;
- cfg = irq_get_chip_data(at);
+ cfg = irq_cfg(at);
if (cfg)
return cfg;
}
@@ -1204,7 +1204,7 @@ void __setup_vector_irq(int cpu)
raw_spin_lock(&vector_lock);
/* Mark the inuse vectors */
for_each_active_irq(irq) {
- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (!cfg)
continue;

@@ -1612,7 +1612,7 @@ __apicdebuginit(void) print_IO_APICs(void)
if (chip != &ioapic_chip)
continue;

- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (!cfg)
continue;
entry = cfg->irq_2_pin;
@@ -2253,7 +2253,7 @@ static void irq_complete_move(struct irq_cfg *cfg)

void irq_force_complete_move(int irq)
{
- struct irq_cfg *cfg = irq_get_chip_data(irq);
+ struct irq_cfg *cfg = irq_cfg(irq);

if (!cfg)
return;
@@ -2515,7 +2515,7 @@ static inline void init_IO_APIC_traps(void)
unsigned int irq;

for_each_active_irq(irq) {
- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
/*
* Hmm.. We don't have an entry for this,
@@ -2648,7 +2648,7 @@ early_param("disable_timer_pin_1", disable_timer_pin_setup);
*/
static inline void __init check_timer(void)
{
- struct irq_cfg *cfg = irq_get_chip_data(0);
+ struct irq_cfg *cfg = irq_cfg(0);
int node = cpu_to_node(0);
int apic1, pin1, apic2, pin2;
unsigned long flags;
@@ -2912,7 +2912,7 @@ int arch_setup_hwirq(unsigned int irq, int node)

void arch_teardown_hwirq(unsigned int irq)
{
- struct irq_cfg *cfg = irq_get_chip_data(irq);
+ struct irq_cfg *cfg = irq_cfg(irq);
unsigned long flags;

free_remapped_irq(irq);
@@ -3041,7 +3041,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
if (!irq_offset)
write_msi_msg(irq, &msg);

- setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+ setup_remapped_irq(irq, irq_cfg(irq), chip);

irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");

@@ -3176,7 +3176,7 @@ int default_setup_hpet_msi(unsigned int irq, unsigned int id)

hpet_msi_write(irq_get_handler_data(irq), &msg);
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
- setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+ setup_remapped_irq(irq, irq_cfg(irq), chip);

irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
return 0;
--
1.7.10.4

2014-06-09 08:19:35

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 13/42] x86, ioapic: introduce helper utilities to walk ioapics and pins

Introduce helper utilities for_each_ioapic(), for_each_ioapic_reverse(),
for_each_pin() and for_each_ioapic_pin() to walk ioapics and pins.
They will be rewritten e will rewrite later to support IOAPIC hotplug.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 120 +++++++++++++++++++++-------------------
1 file changed, 62 insertions(+), 58 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e8cd0bf0ee82..8de9a837790b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -62,6 +62,16 @@

#define __apicdebuginit(type) static type __init

+#define for_each_ioapic(idx) \
+ for ((idx) = 0; (idx) < nr_ioapics; (idx)++)
+#define for_each_ioapic_reverse(idx) \
+ for ((idx) = nr_ioapics - 1; (idx) >= 0; (idx)--)
+#define for_each_pin(idx, pin) \
+ for ((pin) = 0; (pin) < ioapics[(idx)].nr_registers; (pin)++)
+#define for_each_ioapic_pin(idx, pin) \
+ for_each_ioapic((idx)) \
+ for_each_pin((idx), (pin))
+
#define for_each_irq_pin(entry, head) \
for (entry = head; entry; entry = entry->next)

@@ -191,7 +201,7 @@ int __init arch_early_irq_init(void)
if (!legacy_pic->nr_legacy_irqs)
io_apic_irqs = ~0UL;

- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
ioapics[i].saved_registers =
kzalloc(sizeof(struct IO_APIC_route_entry) *
ioapics[i].nr_registers, GFP_KERNEL);
@@ -624,9 +634,8 @@ static void clear_IO_APIC (void)
{
int apic, pin;

- for (apic = 0; apic < nr_ioapics; apic++)
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
- clear_IO_APIC_pin(apic, pin);
+ for_each_ioapic_pin(apic, pin)
+ clear_IO_APIC_pin(apic, pin);
}

#ifdef CONFIG_X86_32
@@ -675,13 +684,13 @@ int save_ioapic_entries(void)
int apic, pin;
int err = 0;

- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers) {
err = -ENOMEM;
continue;
}

- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+ for_each_pin(apic, pin)
ioapics[apic].saved_registers[pin] =
ioapic_read_entry(apic, pin);
}
@@ -696,11 +705,11 @@ void mask_ioapic_entries(void)
{
int apic, pin;

- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers)
continue;

- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
+ for_each_pin(apic, pin) {
struct IO_APIC_route_entry entry;

entry = ioapics[apic].saved_registers[pin];
@@ -719,11 +728,11 @@ int restore_ioapic_entries(void)
{
int apic, pin;

- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers)
continue;

- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+ for_each_pin(apic, pin)
ioapic_write_entry(apic, pin,
ioapics[apic].saved_registers[pin]);
}
@@ -782,7 +791,7 @@ static int __init find_isa_irq_apic(int irq, int type)
if (i < mp_irq_entries) {
int ioapic_idx;

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic)
return ioapic_idx;
}
@@ -1001,7 +1010,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].srcbus;

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
mp_irqs[i].dstapic == MP_APIC_ALL)
break;
@@ -1224,12 +1233,10 @@ static inline int IO_APIC_irq_trigger(int irq)
{
int apic, idx, pin;

- for (apic = 0; apic < nr_ioapics; apic++) {
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
- idx = find_irq_entry(apic, pin, mp_INT);
- if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
- return irq_trigger(idx);
- }
+ for_each_ioapic_pin(apic, pin) {
+ idx = find_irq_entry(apic, pin, mp_INT);
+ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+ return irq_trigger(idx);
}
/*
* nonexistent IRQs are edge default
@@ -1349,7 +1356,7 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
struct io_apic_irq_attr attr;
unsigned int pin, irq;

- for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) {
+ 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;
@@ -1380,7 +1387,7 @@ static void __init setup_IO_APIC_irqs(void)

apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
__io_apic_setup_irqs(ioapic_idx);
}

@@ -1583,7 +1590,7 @@ __apicdebuginit(void) print_IO_APICs(void)
struct irq_chip *chip;

printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
mpc_ioapic_id(ioapic_idx),
ioapics[ioapic_idx].nr_registers);
@@ -1594,7 +1601,7 @@ __apicdebuginit(void) print_IO_APICs(void)
*/
printk(KERN_INFO "testing the IO APIC.......................\n");

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
print_IO_APIC(ioapic_idx);

printk(KERN_DEBUG "IRQ to pin mappings:\n");
@@ -1825,26 +1832,22 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
void __init enable_IO_APIC(void)
{
int i8259_apic, i8259_pin;
- int apic;
+ int apic, pin;

if (!legacy_pic->nr_legacy_irqs)
return;

- for(apic = 0; apic < nr_ioapics; apic++) {
- int pin;
+ for_each_ioapic_pin(apic, pin) {
/* See if any of the pins is in ExtINT mode */
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
- struct IO_APIC_route_entry entry;
- entry = ioapic_read_entry(apic, pin);
+ struct IO_APIC_route_entry entry = ioapic_read_entry(apic, pin);

- /* If the interrupt line is enabled and in ExtInt mode
- * I have found the pin where the i8259 is connected.
- */
- if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
- ioapic_i8259.apic = apic;
- ioapic_i8259.pin = pin;
- goto found_i8259;
- }
+ /* If the interrupt line is enabled and in ExtInt mode
+ * I have found the pin where the i8259 is connected.
+ */
+ if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+ ioapic_i8259.apic = apic;
+ ioapic_i8259.pin = pin;
+ goto found_i8259;
}
}
found_i8259:
@@ -1947,7 +1950,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
/*
* Set the IOAPIC ID to the value stored in the MPC table.
*/
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
+ for_each_ioapic(ioapic_idx) {
/* Read the register 0 value */
raw_spin_lock_irqsave(&ioapic_lock, flags);
reg_00.raw = io_apic_read(ioapic_idx, 0);
@@ -2863,7 +2866,7 @@ static void ioapic_resume(void)
{
int ioapic_idx;

- for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--)
+ for_each_ioapic_reverse(ioapic_idx)
resume_ioapic_id(ioapic_idx);

restore_ioapic_entries();
@@ -3453,9 +3456,8 @@ static u8 __init io_apic_unique_id(u8 id)
DECLARE_BITMAP(used, 256);

bitmap_zero(used, 256);
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i)
__set_bit(mpc_ioapic_id(i), used);
- }
if (!test_bit(id, used))
return id;
return find_first_zero_bit(used, 256);
@@ -3513,8 +3515,7 @@ void __init setup_ioapic_dest(void)
if (skip_ioapic_setup == 1)
return;

- for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
- for (pin = 0; pin < ioapics[ioapic].nr_registers; pin++) {
+ for_each_ioapic_pin(ioapic, pin) {
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
@@ -3543,29 +3544,33 @@ void __init setup_ioapic_dest(void)

static struct resource *ioapic_resources;

-static struct resource * __init ioapic_setup_resources(int nr_ioapics)
+static struct resource * __init ioapic_setup_resources(void)
{
unsigned long n;
struct resource *res;
char *mem;
- int i;
+ int i, num = 0;

- if (nr_ioapics <= 0)
+ for_each_ioapic(i)
+ num++;
+ if (num == 0)
return NULL;

n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
- n *= nr_ioapics;
+ n *= num;

mem = alloc_bootmem(n);
res = (void *)mem;

- mem += sizeof(struct resource) * nr_ioapics;
+ mem += sizeof(struct resource) * num;

- for (i = 0; i < nr_ioapics; i++) {
- res[i].name = mem;
- res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ num = 0;
+ for_each_ioapic(i) {
+ res[num].name = mem;
+ res[num].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
mem += IOAPIC_RESOURCE_NAME_SIZE;
+ num++;
}

ioapic_resources = res;
@@ -3579,8 +3584,8 @@ void __init native_io_apic_init_mappings(void)
struct resource *ioapic_res;
int i;

- ioapic_res = ioapic_setup_resources(nr_ioapics);
- for (i = 0; i < nr_ioapics; i++) {
+ ioapic_res = ioapic_setup_resources();
+ for_each_ioapic(i) {
if (smp_found_config) {
ioapic_phys = mpc_ioapic_addr(i);
#ifdef CONFIG_X86_32
@@ -3625,7 +3630,7 @@ void __init ioapic_insert_resources(void)
return;
}

- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
insert_resource(&iomem_resource, r);
r++;
}
@@ -3633,16 +3638,15 @@ void __init ioapic_insert_resources(void)

int mp_find_ioapic(u32 gsi)
{
- int i = 0;
+ int i;

if (nr_ioapics == 0)
return -1;

/* Find the IOAPIC that manages this GSI. */
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(i);
- if ((gsi >= gsi_cfg->gsi_base)
- && (gsi <= gsi_cfg->gsi_end))
+ if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end)
return i;
}

@@ -3654,7 +3658,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
{
struct mp_ioapic_gsi *gsi_cfg;

- if (WARN_ON(ioapic == -1))
+ if (WARN_ON(ioapic < 0))
return -1;

gsi_cfg = mp_ioapic_gsi_routing(ioapic);
--
1.7.10.4

2014-06-09 08:19:49

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 16/42] x86, irq: introduce some helper utilities to improve readability

It also fixes an off by one bug in
if ((ioapic_idx > 0) && (irq > NR_IRQS_LEGACY))
It should be
if ((ioapic_idx > 0) && (irq >= NR_IRQS_LEGACY))

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/io_apic.h | 2 ++
arch/x86/kernel/apic/io_apic.c | 29 ++++++++++++++++++++++-------
2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index de3d8b04cf64..b775cf3622c3 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -171,6 +171,7 @@ extern u32 gsi_top;

extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
+extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

@@ -212,6 +213,7 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
+static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }

struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 4ca3151d26f9..02faa7104aa5 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -117,6 +117,24 @@ struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx)
return &ioapics[ioapic_idx].gsi_config;
}

+static inline int mp_ioapic_pin_count(int ioapic)
+{
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+ return gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
+}
+
+u32 mp_pin_to_gsi(int ioapic, int pin)
+{
+ return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin;
+}
+
+/* Initialize all legacy IRQs and all pins on the first IOAPIC at boot */
+static inline int mp_init_irq_at_boot(int ioapic, int irq)
+{
+ return ioapic == 0 || (irq >= 0 && irq < NR_IRQS_LEGACY);
+}
+
int nr_ioapics;

/* The one past the highest gsi number used */
@@ -1367,8 +1385,7 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
continue;

irq = pin_2_irq(idx, ioapic_idx, pin);
-
- if ((ioapic_idx > 0) && (irq > NR_IRQS_LEGACY))
+ if (!mp_init_irq_at_boot(ioapic_idx, irq))
continue;

/*
@@ -1419,9 +1436,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
return;

irq = pin_2_irq(idx, ioapic_idx, pin);
-
- /* Only handle the non legacy irqs on secondary ioapics */
- if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY)
+ if (mp_init_irq_at_boot(ioapic_idx, irq))
return;

set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
@@ -3524,9 +3539,9 @@ void __init setup_ioapic_dest(void)
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
- irq = pin_2_irq(irq_entry, ioapic, pin);

- if ((ioapic > 0) && (irq > NR_IRQS_LEGACY))
+ irq = pin_2_irq(irq_entry, ioapic, pin);
+ if (!mp_init_irq_at_boot(ioapic, irq))
continue;

idata = irq_get_irq_data(irq);
--
1.7.10.4

2014-06-09 08:20:04

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 18/42] ce4100, irq: do not set legacy_pic to null_legacy_pic

Intel CE4100 platforms has i8259 legacy interrupt controllers, so don't
set legacy_pic to null_legacy_pic in late booting stage because we need
legacy_pic to mask i8259 pins when enabling IOAPIC pins for safety.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/platform/ce4100/ce4100.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 0a54a586559b..701fd5843c87 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -138,8 +138,6 @@ static void __init sdv_arch_setup(void)
static void sdv_pci_init(void)
{
x86_of_pci_init();
- /* We can't set this earlier, because we need to calibrate the timer */
- legacy_pic = &null_legacy_pic;
}

/*
--
1.7.10.4

2014-06-09 08:20:00

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 17/42] ce4100, irq: make CE4100 depend on CONFIG_X86_IO_APIC

Intel CE4100 platforms need IOAPIC support becasue some devices are
always connected to the second IOAPIC, so make CONFIG_CE depends on
CONFIG_X86_IO_APIC.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/Kconfig | 1 +
arch/x86/platform/ce4100/ce4100.c | 9 ++-------
2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 47247708c9eb..55ec58b0b373 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -426,6 +426,7 @@ config X86_INTEL_CE
bool "CE4100 TV platform"
depends on PCI
depends on PCI_GODIRECT
+ depends on X86_IO_APIC
depends on X86_32
depends on X86_EXTENDED_PLATFORM
select X86_REBOOTFIXUPS
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 8244f5ec2f4c..0a54a586559b 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -135,14 +135,12 @@ static void __init sdv_arch_setup(void)
sdv_serial_fixup();
}

-#ifdef CONFIG_X86_IO_APIC
static void sdv_pci_init(void)
{
x86_of_pci_init();
/* We can't set this earlier, because we need to calibrate the timer */
legacy_pic = &null_legacy_pic;
}
-#endif

/*
* CE4100 specific x86_init function overrides and early setup
@@ -155,7 +153,9 @@ void __init x86_ce4100_early_setup(void)
x86_init.resources.probe_roms = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
x86_init.mpparse.find_smp_config = x86_init_noop;
+ x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
x86_init.pci.init = ce4100_pci_init;
+ x86_init.pci.init_irq = sdv_pci_init;

/*
* By default, the reboot method is ACPI which is supported by the
@@ -166,10 +166,5 @@ void __init x86_ce4100_early_setup(void)
*/
reboot_type = BOOT_KBD;

-#ifdef CONFIG_X86_IO_APIC
- x86_init.pci.init_irq = sdv_pci_init;
- x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
-#endif
-
pm_power_off = ce4100_power_off;
}
--
1.7.10.4

2014-06-09 08:20:27

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 19/42] x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY

Some platforms, such as Intel MID and mshypv, do not support legacy
interrupt controllers. So count legacy IRQs by legacy_pic->nr_legacy_irqs
instead of hard-coded NR_IRQS_LEGACY.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/i8259.h | 5 +++++
arch/x86/kernel/acpi/boot.c | 13 ++++++------
arch/x86/kernel/apic/io_apic.c | 43 +++++++++++++++++++++++-----------------
arch/x86/kernel/devicetree.c | 13 ++++++------
arch/x86/kernel/irqinit.c | 6 +++---
arch/x86/pci/xen.c | 7 ++++---
6 files changed, 51 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index a20365953bf8..ccffa53750a8 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -67,4 +67,9 @@ struct legacy_pic {
extern struct legacy_pic *legacy_pic;
extern struct legacy_pic null_legacy_pic;

+static inline int nr_legacy_irqs(void)
+{
+ return legacy_pic->nr_legacy_irqs;
+}
+
#endif /* _ASM_X86_I8259_H */
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index d6493863bd4b..8b09249bb253 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -43,6 +43,7 @@
#include <asm/io.h>
#include <asm/mpspec.h>
#include <asm/smp.h>
+#include <asm/i8259.h>

#include "sleep.h" /* To include x86_acpi_suspend_lowlevel */
static int __initdata acpi_force = 0;
@@ -101,10 +102,10 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

static unsigned int gsi_to_irq(unsigned int gsi)
{
- unsigned int irq = gsi + NR_IRQS_LEGACY;
+ unsigned int irq = gsi + nr_legacy_irqs();
unsigned int i;

- for (i = 0; i < NR_IRQS_LEGACY; i++) {
+ for (i = 0; i < nr_legacy_irqs(); i++) {
if (isa_irq_to_gsi[i] == gsi) {
return i;
}
@@ -114,7 +115,7 @@ static unsigned int gsi_to_irq(unsigned int gsi)
* except on truly weird platforms that have
* non isa irqs in the first 16 gsis.
*/
- if (gsi >= NR_IRQS_LEGACY)
+ if (gsi >= nr_legacy_irqs())
irq = gsi;
else
irq = gsi_top + gsi;
@@ -371,7 +372,7 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
* otherwise there will be more than one entry with the same GSI
* and acpi_isa_irq_to_gsi() may give wrong result.
*/
- if (gsi < NR_IRQS_LEGACY && isa_irq_to_gsi[gsi] == gsi)
+ if (gsi < nr_legacy_irqs() && isa_irq_to_gsi[gsi] == gsi)
isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
isa_irq_to_gsi[bus_irq] = gsi;
}
@@ -628,7 +629,7 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq < NR_IRQS_LEGACY &&
+ if (isa_irq < nr_legacy_irqs() &&
isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
*gsi = isa_irq_to_gsi[isa_irq];
return 0;
@@ -1017,7 +1018,7 @@ static void __init mp_config_acpi_legacy_irqs(void)
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
- for (i = 0; i < NR_IRQS_LEGACY; i++) {
+ for (i = 0; i < nr_legacy_irqs(); i++) {
int ioapic, pin;
unsigned int dstapic;
int idx;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 02faa7104aa5..72cbb92ca401 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -129,10 +129,17 @@ u32 mp_pin_to_gsi(int ioapic, int pin)
return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin;
}

-/* Initialize all legacy IRQs and all pins on the first IOAPIC at boot */
+/*
+ * Initialize all legacy IRQs and all pins on the first IOAPIC
+ * if we have legacy interrupt controller. Kernel boot option "pirq="
+ * may rely on non-legacy pins on the first IOAPIC.
+ */
static inline int mp_init_irq_at_boot(int ioapic, int irq)
{
- return ioapic == 0 || (irq >= 0 && irq < NR_IRQS_LEGACY);
+ if (!nr_legacy_irqs())
+ return 0;
+
+ return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
}

int nr_ioapics;
@@ -216,7 +223,7 @@ int __init arch_early_irq_init(void)
struct irq_cfg *cfg;
int count, node, i;

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
io_apic_irqs = ~0UL;

for_each_ioapic(i) {
@@ -239,7 +246,7 @@ int __init arch_early_irq_init(void)
* For legacy IRQ's, start with assigning irq0 to irq15 to
* IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
*/
- if (i < legacy_pic->nr_legacy_irqs) {
+ if (i < nr_legacy_irqs()) {
cfg[i].vector = IRQ0_VECTOR + i;
cpumask_setall(cfg[i].domain);
}
@@ -823,7 +830,7 @@ static int __init find_isa_irq_apic(int irq, int type)
*/
static int EISA_ELCR(unsigned int irq)
{
- if (irq < legacy_pic->nr_legacy_irqs) {
+ if (irq < nr_legacy_irqs()) {
unsigned int port = 0x4d0 + (irq >> 3);
return (inb(port) >> (irq & 7)) & 1;
}
@@ -980,7 +987,7 @@ static int pin_2_irq(int idx, int apic, int pin)
} else {
u32 gsi = gsi_cfg->gsi_base + pin;

- if (gsi >= NR_IRQS_LEGACY)
+ if (gsi >= nr_legacy_irqs())
irq = gsi;
else
irq = gsi_top + gsi;
@@ -1357,7 +1364,7 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
}

ioapic_register_intr(irq, cfg, attr->trigger);
- if (irq < legacy_pic->nr_legacy_irqs)
+ if (irq < nr_legacy_irqs())
legacy_pic->mask(irq);

ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry);
@@ -1782,7 +1789,7 @@ __apicdebuginit(void) print_PIC(void)
unsigned int v;
unsigned long flags;

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;

printk(KERN_DEBUG "\nprinting PIC contents\n");
@@ -1854,7 +1861,7 @@ void __init enable_IO_APIC(void)
int i8259_apic, i8259_pin;
int apic, pin;

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;

for_each_ioapic_pin(apic, pin) {
@@ -1939,7 +1946,7 @@ void disable_IO_APIC(void)
*/
clear_IO_APIC();

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;

x86_io_apic_ops.disable();
@@ -2143,7 +2150,7 @@ static unsigned int startup_ioapic_irq(struct irq_data *data)
unsigned long flags;

raw_spin_lock_irqsave(&ioapic_lock, flags);
- if (irq < legacy_pic->nr_legacy_irqs) {
+ if (irq < nr_legacy_irqs()) {
legacy_pic->mask(irq);
if (legacy_pic->irq_pending(irq))
was_pending = 1;
@@ -2542,7 +2549,7 @@ static inline void init_IO_APIC_traps(void)
* so default to an old-fashioned 8259
* interrupt if we can..
*/
- if (irq < legacy_pic->nr_legacy_irqs)
+ if (irq < nr_legacy_irqs())
legacy_pic->make_irq(irq);
else
/* Strange. Oh, well.. */
@@ -2839,7 +2846,7 @@ void __init setup_IO_APIC(void)
/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
*/
- io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+ io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;

apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
/*
@@ -2850,7 +2857,7 @@ void __init setup_IO_APIC(void)
sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
- if (legacy_pic->nr_legacy_irqs)
+ if (nr_legacy_irqs())
check_timer();
}

@@ -3344,7 +3351,7 @@ static int __init io_apic_get_redir_entries(int ioapic)

unsigned int arch_dynirq_lower_bound(unsigned int from)
{
- unsigned int min = gsi_top + NR_IRQS_LEGACY;
+ unsigned int min = gsi_top + nr_legacy_irqs();

return from < min ? min : from;
}
@@ -3356,17 +3363,17 @@ int __init arch_probe_nr_irqs(void)
if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
nr_irqs = NR_VECTORS * nr_cpu_ids;

- nr = (gsi_top + NR_IRQS_LEGACY) + 8 * nr_cpu_ids;
+ nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids;
#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
/*
* for MSI and HT dyn irq
*/
- nr += (gsi_top + NR_IRQS_LEGACY) * 16;
+ nr += gsi_top * 16;
#endif
if (nr < nr_irqs)
nr_irqs = nr;

- return NR_IRQS_LEGACY;
+ return nr_legacy_irqs();
}

int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index d35078ea1446..e08a007bdacf 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -21,6 +21,7 @@
#include <asm/apic.h>
#include <asm/pci_x86.h>
#include <asm/setup.h>
+#include <asm/i8259.h>

__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
@@ -316,7 +317,7 @@ static void dt_add_ioapic_domain(unsigned int ioapic_num,
struct irq_domain *id;
struct mp_ioapic_gsi *gsi_cfg;
int ret;
- int num;
+ int num, legacy_irqs = nr_legacy_irqs();

gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
@@ -326,17 +327,17 @@ static void dt_add_ioapic_domain(unsigned int ioapic_num,
BUG_ON(!id);
if (gsi_cfg->gsi_base == 0) {
/*
- * The first NR_IRQS_LEGACY irq descs are allocated in
+ * The first nr_legacy_irqs() irq descs are allocated in
* early_irq_init() and need just a mapping. The
* remaining irqs need both. All of them are preallocated
* and assigned so we can keep the 1:1 mapping which the ioapic
* is having.
*/
- irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
+ irq_domain_associate_many(id, 0, 0, legacy_irqs);

- if (num > NR_IRQS_LEGACY) {
- ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
- NR_IRQS_LEGACY, num - NR_IRQS_LEGACY);
+ if (num > legacy_irqs) {
+ ret = irq_create_strict_mappings(id, legacy_irqs,
+ legacy_irqs, num - legacy_irqs);
if (ret)
pr_err("Error creating mapping for the "
"remaining IRQs: %d\n", ret);
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 7f50156542fb..a0111e91eb4b 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -78,7 +78,7 @@ void __init init_ISA_irqs(void)
#endif
legacy_pic->init(0);

- for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+ for (i = 0; i < nr_legacy_irqs(); i++)
irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
}

@@ -100,7 +100,7 @@ void __init init_IRQ(void)
* then this vector space can be freed and re-used dynamically as the
* irq's migrate etc.
*/
- for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+ for (i = 0; i < nr_legacy_irqs(); i++)
per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;

x86_init.irqs.intr_init();
@@ -121,7 +121,7 @@ void setup_vector_irq(int cpu)
* legacy PIC, for the new cpu that is coming online, setup the static
* legacy vector to irq mapping:
*/
- for (irq = 0; irq < legacy_pic->nr_legacy_irqs; irq++)
+ for (irq = 0; irq < nr_legacy_irqs(); irq++)
per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq;
#endif

diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 905956f16465..093f5f4272d3 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -23,6 +23,7 @@
#include <xen/features.h>
#include <xen/events.h>
#include <asm/xen/pci.h>
+#include <asm/i8259.h>

static int xen_pcifront_enable_irq(struct pci_dev *dev)
{
@@ -40,7 +41,7 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev)
/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
pirq = gsi;

- if (gsi < NR_IRQS_LEGACY)
+ if (gsi < nr_legacy_irqs())
share = 0;

rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
@@ -511,7 +512,7 @@ int __init pci_xen_initial_domain(void)
xen_setup_acpi_sci();
__acpi_register_gsi = acpi_register_gsi_xen;
/* Pre-allocate legacy irqs */
- for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
+ for (irq = 0; irq < nr_legacy_irqs(); irq++) {
int trigger, polarity;

if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
@@ -522,7 +523,7 @@ int __init pci_xen_initial_domain(void)
true /* Map GSI to PIRQ */);
}
if (0 == nr_ioapics) {
- for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
+ for (irq = 0; irq < nr_legacy_irqs(); irq++)
xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
}
return 0;
--
1.7.10.4

2014-06-09 08:20:38

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 20/42] x86, irq: simplify arch_early_irq_init()

Simplify function arch_early_irq_init() and kill static array irq_cfgx[].

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 33 +++++++++++----------------------
1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 72cbb92ca401..12d12f897107 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -183,6 +183,7 @@ 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 */
void mp_save_irq(struct mpc_intsrc *m)
@@ -214,14 +215,10 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
}

-
-/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
-
int __init arch_early_irq_init(void)
{
struct irq_cfg *cfg;
- int count, node, i;
+ int i, node = cpu_to_node(0);

if (!nr_legacy_irqs())
io_apic_irqs = ~0UL;
@@ -234,22 +231,14 @@ int __init arch_early_irq_init(void)
pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
}

- cfg = irq_cfgx;
- count = ARRAY_SIZE(irq_cfgx);
- node = cpu_to_node(0);
-
- for (i = 0; i < count; i++) {
- irq_set_chip_data(i, &cfg[i]);
- zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
- zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
- /*
- * For legacy IRQ's, start with assigning irq0 to irq15 to
- * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
- */
- if (i < nr_legacy_irqs()) {
- cfg[i].vector = IRQ0_VECTOR + i;
- cpumask_setall(cfg[i].domain);
- }
+ /*
+ * For legacy IRQ's, start with assigning irq0 to irq15 to
+ * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
+ */
+ for (i = 0; i < nr_legacy_irqs(); i++) {
+ cfg = alloc_irq_and_cfg_at(i, node);
+ cfg->vector = IRQ0_VECTOR + i;
+ cpumask_setall(cfg->domain);
}

return 0;
@@ -3373,7 +3362,7 @@ int __init arch_probe_nr_irqs(void)
if (nr < nr_irqs)
nr_irqs = nr;

- return nr_legacy_irqs();
+ return 0;
}

int io_apic_set_pci_routing(struct device *dev, int irq,
--
1.7.10.4

2014-06-09 08:20:55

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 21/42] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number

Currently ACPI and ioapic both implement algorithms to map (ioapic, pin)
to IRQ number. So consolidate the common part into one place, which is
also preparing for irqdomain support.

It introduces mp_map_gsi_to_irq(), which will be used to allocate IRQ
number IOAPIC pins when irqdomain is enabled.

Also rename gsi_to_irq() to map_gsi_to_irq(), later we will introduce
unmap_gsi_to_irq() when enabling IOAPIC hotplug.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/io_apic.h | 2 ++
arch/x86/kernel/acpi/boot.c | 47 +++++++++++++++++++---------------------
arch/x86/kernel/apic/io_apic.c | 27 +++++++++++++----------
3 files changed, 39 insertions(+), 37 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index b775cf3622c3..978e51fdcb59 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -172,6 +172,7 @@ extern u32 gsi_top;
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
+extern int mp_map_gsi_to_irq(u32 gsi);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

@@ -214,6 +215,7 @@ static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
+static inline int mp_map_gsi_to_irq(u32 gsi) { return gsi; }

struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8b09249bb253..e5e645fdd690 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -100,27 +100,15 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

#define ACPI_INVALID_GSI INT_MIN

-static unsigned int gsi_to_irq(unsigned int gsi)
+static int map_gsi_to_irq(unsigned int gsi)
{
- unsigned int irq = gsi + nr_legacy_irqs();
- unsigned int i;
+ int i;

- for (i = 0; i < nr_legacy_irqs(); i++) {
- if (isa_irq_to_gsi[i] == gsi) {
+ for (i = 0; i < nr_legacy_irqs(); i++)
+ if (isa_irq_to_gsi[i] == gsi)
return i;
- }
- }
-
- /* Provide an identity mapping of gsi == irq
- * except on truly weird platforms that have
- * non isa irqs in the first 16 gsis.
- */
- if (gsi >= nr_legacy_irqs())
- irq = gsi;
- else
- irq = gsi_top + gsi;

- return irq;
+ return mp_map_gsi_to_irq(gsi);
}

/*
@@ -416,6 +404,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
+ int irq;
int ioapic;
int ioapic_pin;
struct io_apic_irq_attr irq_attr;
@@ -428,6 +417,10 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;

+ irq = map_gsi_to_irq(gsi);
+ if (irq < 0)
+ return ACPI_INVALID_GSI;
+
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
@@ -449,7 +442,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
if (ret < 0)
gsi = ACPI_INVALID_GSI;

@@ -614,16 +607,20 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
outb(new >> 8, 0x4d1);
}

-int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- *irq = gsi_to_irq(gsi);
+ int irq = map_gsi_to_irq(gsi);

+ if (irq >= 0) {
#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
+ if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+ setup_IO_APIC_irq_extra(gsi);
#endif
+ *irqp = irq;
+ return 0;
+ }

- return 0;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

@@ -677,11 +674,11 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int plat_gsi = gsi;
+ unsigned int plat_gsi;

plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
if (plat_gsi != ACPI_INVALID_GSI)
- return gsi_to_irq(plat_gsi);
+ return map_gsi_to_irq(plat_gsi);

return -1;
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 12d12f897107..ed159cd36971 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -959,11 +959,19 @@ static int irq_trigger(int idx)
return trigger;
}

+int mp_map_gsi_to_irq(u32 gsi)
+{
+ /*
+ * 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;
+}
+
static int pin_2_irq(int idx, int apic, int pin)
{
int irq;
int bus = mp_irqs[idx].srcbus;
- struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);

/*
* Debugging check, we are in big trouble if this message pops up!
@@ -971,17 +979,6 @@ static int pin_2_irq(int idx, int apic, int pin)
if (mp_irqs[idx].dstirq != pin)
pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");

- if (test_bit(bus, mp_bus_not_pci)) {
- irq = mp_irqs[idx].srcbusirq;
- } else {
- u32 gsi = gsi_cfg->gsi_base + pin;
-
- if (gsi >= nr_legacy_irqs())
- irq = gsi;
- else
- irq = gsi_top + gsi;
- }
-
#ifdef CONFIG_X86_32
/*
* PCI IRQ command line redirection. Yes, limits are hardcoded.
@@ -996,11 +993,17 @@ static int pin_2_irq(int idx, int apic, int pin)
apic_printk(APIC_VERBOSE, KERN_DEBUG
"using PIRQ%d -> IRQ %d\n",
pin-16, irq);
+ return irq;
}
}
}
#endif

+ if (test_bit(bus, mp_bus_not_pci))
+ irq = mp_irqs[idx].srcbusirq;
+ else
+ irq = mp_map_gsi_to_irq(mp_pin_to_gsi(apic, pin));
+
return irq;
}

--
1.7.10.4

2014-06-09 08:21:11

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 23/42] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC

Currently x86 support identity mapping between GSI(IOAPIC pin) and IRQ
number, so continous IRQs at low end are statically allocated to IOAPICs
at boot time. This design causes trouble to support IOAPIC hotplug.

This patch implements basic mechanism to dynamically allocate IRQ on
demand for IOAPIC pins by using irqdomain framework.

It first adds several fields into struct ioapic to support irqdomain.
Then it implements an algorithm to dynamically allocate IRQ number
for IOAPIC pins on demand.

Currently it supports three types of irqdomain:
1) LEGACY: used to support IOAPIC hosting legacy IRQs and building
identity mapping for legacy IRQs. A speical case, we dynamically
allocate IRQ number for IOAPIC pin which has GSI number below
nr_legacy_irqs() but isn't legacy IRQ. This is for backward
compatibility and avoid regression.
2) STRICT: build identity mapping between GSI and IRQ nubmer.
3) DYNAMIC: dynamically allocate IRQ number for IOAPIC pin on demand.

Legacy(ISA) IRQs is not managed by irqdomain because there may be
multiple pins sharing the same IRQ number and current irqdomain only
supports 1:1 mapping between pins and IRQ.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/io_apic.h | 21 +++++-
arch/x86/kernel/acpi/boot.c | 8 +-
arch/x86/kernel/apic/io_apic.c | 158 +++++++++++++++++++++++++++++++---------
4 files changed, 147 insertions(+), 41 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 55ec58b0b373..966f5111e213 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -833,6 +833,7 @@ config X86_IO_APIC
def_bool y
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+ select IRQ_DOMAIN

config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
bool "Reroute for broken boot IRQs"
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 978e51fdcb59..64c6e344399b 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -98,6 +98,8 @@ struct IR_IO_APIC_route_entry {
#define IOAPIC_AUTO -1
#define IOAPIC_EDGE 0
#define IOAPIC_LEVEL 1
+#define IOAPIC_MAP_ALLOC 0x1
+#define IOAPIC_MAP_CHECK 0x2

#ifdef CONFIG_X86_IO_APIC

@@ -163,6 +165,21 @@ extern int restore_ioapic_entries(void);
extern void setup_ioapic_ids_from_mpc(void);
extern void setup_ioapic_ids_from_mpc_nocheck(void);

+enum ioapic_domain_type {
+ IOAPIC_DOMAIN_INVALID,
+ IOAPIC_DOMAIN_LEGACY,
+ IOAPIC_DOMAIN_STRICT,
+ IOAPIC_DOMAIN_DYNAMIC,
+};
+
+struct device_node;
+struct irq_domain_ops;
+struct ioapic_domain_cfg {
+ enum ioapic_domain_type type;
+ const struct irq_domain_ops *ops;
+ struct device_node *dev;
+};
+
struct mp_ioapic_gsi{
u32 gsi_base;
u32 gsi_end;
@@ -172,7 +189,7 @@ extern u32 gsi_top;
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
-extern int mp_map_gsi_to_irq(u32 gsi);
+extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

@@ -215,7 +232,7 @@ static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
-static inline int mp_map_gsi_to_irq(u32 gsi) { return gsi; }
+static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }

struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 0c9dcf6824b6..96d8da83ed8b 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -100,7 +100,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

#define ACPI_INVALID_GSI INT_MIN

-static int map_gsi_to_irq(unsigned int gsi)
+static int map_gsi_to_irq(unsigned int gsi, unsigned int flags)
{
int i;

@@ -108,7 +108,7 @@ static int map_gsi_to_irq(unsigned int gsi)
if (isa_irq_to_gsi[i] == gsi)
return i;

- return mp_map_gsi_to_irq(gsi);
+ return mp_map_gsi_to_irq(gsi, flags);
}

/*
@@ -417,7 +417,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;

- irq = map_gsi_to_irq(gsi);
+ irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
if (irq < 0)
return irq;

@@ -608,7 +608,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)

int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- int irq = map_gsi_to_irq(gsi);
+ int irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);

if (irq >= 0) {
#ifdef CONFIG_X86_IO_APIC
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index ed159cd36971..9e5ca8edfccf 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -31,6 +31,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
#include <linux/msi.h>
#include <linux/htirq.h>
#include <linux/freezer.h>
@@ -83,6 +84,7 @@ int sis_apic_bug = -1;

static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
+static DEFINE_MUTEX(ioapic_mutex);

static struct ioapic {
/*
@@ -97,6 +99,8 @@ static struct ioapic {
struct mpc_ioapic mp_config;
/* IO APIC gsi routing info */
struct mp_ioapic_gsi gsi_config;
+ struct ioapic_domain_cfg irqdomain_cfg;
+ struct irq_domain *irqdomain;
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];

@@ -142,6 +146,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
}

+static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
+{
+ return ioapics[ioapic].irqdomain;
+}
+
int nr_ioapics;

/* The one past the highest gsi number used */
@@ -959,19 +968,79 @@ static int irq_trigger(int idx)
return trigger;
}

-int mp_map_gsi_to_irq(u32 gsi)
+static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
{
+ int irq = -1;
+ int ioapic = (int)(long)domain->host_data;
+ int type = ioapics[ioapic].irqdomain_cfg.type;
+
+ switch (type) {
+ case IOAPIC_DOMAIN_LEGACY:
+ /*
+ * Dynamically allocate IRQ number for non-ISA IRQs in the first 16
+ * GSIs on some weird platforms.
+ */
+ if (gsi < nr_legacy_irqs())
+ irq = irq_create_mapping(domain, pin);
+ else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+ irq = gsi;
+ break;
+ case IOAPIC_DOMAIN_STRICT:
+ if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+ irq = gsi;
+ break;
+ case IOAPIC_DOMAIN_DYNAMIC:
+ irq = irq_create_mapping(domain, pin);
+ break;
+ default:
+ WARN(1, "ioapic: unknown irqdomain type %d\n", type);
+ break;
+ }
+
+ return irq > 0 ? irq : -1;
+}
+
+static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
+ unsigned int flags)
+{
+ int irq;
+ struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+
/*
- * Provide an identity mapping of gsi == irq except on truly weird
- * platforms that have non isa irqs in the first 16 gsis.
+ * Don't use irqdomain to manage ISA IRQs because there may be
+ * multiple IOAPIC pins sharing the same ISA IRQ number and
+ * irqdomain only supports 1:1 mapping between IOAPIC pin and
+ * IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are used
+ * for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H).
+ * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are
+ * available, and some BIOSes may use MP Interrupt Source records
+ * to override IRQ numbers for PIRQs instead of reprogramming
+ * the interrupt routing logic. Thus there may be multiple pins
+ * sharing the same legacy IRQ number when ACPI is disabled.
*/
- return gsi >= nr_legacy_irqs() ? gsi : gsi_top + gsi;
+ 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;
+ }
+
+ 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);
+ mutex_unlock(&ioapic_mutex);
+
+ return irq > 0 ? irq : -1;
}

-static int pin_2_irq(int idx, int apic, int pin)
+static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
{
- int irq;
- int bus = mp_irqs[idx].srcbus;
+ u32 gsi = mp_pin_to_gsi(ioapic, pin);

/*
* Debugging check, we are in big trouble if this message pops up!
@@ -989,7 +1058,7 @@ static int pin_2_irq(int idx, int apic, int pin)
apic_printk(APIC_VERBOSE, KERN_DEBUG
"disabling PIRQ%d\n", pin-16);
} else {
- irq = pirq_entries[pin-16];
+ int irq = pirq_entries[pin-16];
apic_printk(APIC_VERBOSE, KERN_DEBUG
"using PIRQ%d -> IRQ %d\n",
pin-16, irq);
@@ -999,12 +1068,23 @@ static int pin_2_irq(int idx, int apic, int pin)
}
#endif

- if (test_bit(bus, mp_bus_not_pci))
- irq = mp_irqs[idx].srcbusirq;
- else
- irq = mp_map_gsi_to_irq(mp_pin_to_gsi(apic, pin));
+ return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+}

- return irq;
+int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
+{
+ int ioapic, pin, idx;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return -1;
+
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ idx = find_irq_entry(ioapic, pin, mp_INT);
+ if ((flags & IOAPIC_MAP_CHECK) && idx < 0)
+ return -1;
+
+ return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
}

/*
@@ -1014,7 +1094,7 @@ static int pin_2_irq(int idx, int apic, int pin)
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
struct io_apic_irq_attr *irq_attr)
{
- int irq, i, best_guess = -1;
+ int irq, i, best_ioapic = -1, best_idx = -1;

apic_printk(APIC_DEBUG,
"querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1043,30 +1123,37 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
continue;

/* Skip ISA IRQs */
- irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
- if (ioapic_idx == 0 && !IO_APIC_IRQ(irq))
+ irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq, 0);
+ if (irq > 0 && !IO_APIC_IRQ(irq))
continue;

if (pin == (mp_irqs[i].srcbusirq & 3)) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- return irq;
+ best_idx = i;
+ best_ioapic = ioapic_idx;
+ goto out;
}
+
/*
* Use the first all-but-pin matching entry as a
* best-guess fuzzy result for broken mptables.
*/
- if (best_guess < 0) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- best_guess = irq;
+ if (best_idx < 0) {
+ best_idx = i;
+ best_ioapic = ioapic_idx;
}
}
- return best_guess;
+ if (best_idx < 0)
+ return -1;
+
+out:
+ irq = pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq,
+ IOAPIC_MAP_ALLOC);
+ if (irq > 0)
+ set_io_apic_irq_attr(irq_attr, best_ioapic,
+ mp_irqs[best_idx].dstirq,
+ irq_trigger(best_idx),
+ irq_polarity(best_idx));
+ return irq;
}
EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);

@@ -1257,7 +1344,7 @@ static inline int IO_APIC_irq_trigger(int irq)

for_each_ioapic_pin(apic, pin) {
idx = find_irq_entry(apic, pin, mp_INT);
- if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin, 0)))
return irq_trigger(idx);
}
/*
@@ -1383,8 +1470,9 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
continue;

- irq = pin_2_irq(idx, ioapic_idx, pin);
- if (!mp_init_irq_at_boot(ioapic_idx, irq))
+ 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;

/*
@@ -1434,8 +1522,8 @@ void setup_IO_APIC_irq_extra(u32 gsi)
if (idx == -1)
return;

- irq = pin_2_irq(idx, ioapic_idx, pin);
- if (mp_init_irq_at_boot(ioapic_idx, irq))
+ irq = pin_2_irq(idx, ioapic_idx, pin, IOAPIC_MAP_ALLOC);
+ if (irq < 0 || mp_init_irq_at_boot(ioapic_idx, irq))
return;

set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
@@ -3539,8 +3627,8 @@ void __init setup_ioapic_dest(void)
if (irq_entry == -1)
continue;

- irq = pin_2_irq(irq_entry, ioapic, pin);
- if (!mp_init_irq_at_boot(ioapic, irq))
+ irq = pin_2_irq(irq_entry, ioapic, pin, 0);
+ if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
continue;

idata = irq_get_irq_data(irq);
--
1.7.10.4

2014-06-09 08:21:33

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 24/42] x86, irq: enhance mp_register_ioapic() to support irqdomain

Enhance function mp_register_ioapic() to support irqdomain.
When registering IOAPIC, caller may provide callbacks and parameters
for creating irqdomain. The IOAPIC core will create irqdomain later
if caller has passed in corresponding parameters.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/io_apic.h | 3 ++-
arch/x86/kernel/acpi/boot.c | 2 +-
arch/x86/kernel/apic/io_apic.c | 42 +++++++++++++++++++++++++++++++++++++++-
arch/x86/kernel/devicetree.c | 2 +-
arch/x86/kernel/mpparse.c | 2 +-
arch/x86/platform/sfi/sfi.c | 2 +-
6 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 64c6e344399b..3e4bea3a52b1 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -190,7 +190,8 @@ extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ struct ioapic_domain_cfg *cfg);
extern void __init pre_init_apic_IRQ0(void);

extern void mp_save_irq(struct mpc_intsrc *m);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 96d8da83ed8b..15d988cfa335 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -462,7 +462,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
acpi_table_print_madt_entry(header);

mp_register_ioapic(ioapic->id,
- ioapic->address, ioapic->global_irq_base);
+ ioapic->address, ioapic->global_irq_base, NULL);

return 0;
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 9e5ca8edfccf..9c5f70699a80 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -85,6 +85,7 @@ int sis_apic_bug = -1;
static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
static DEFINE_MUTEX(ioapic_mutex);
+static unsigned int ioapic_dynirq_base;

static struct ioapic {
/*
@@ -2920,8 +2921,35 @@ out:
*/
#define PIC_IRQS (1UL << PIC_CASCADE_IR)

+static int mp_irqdomain_create(int ioapic)
+{
+ int hwirqs = mp_ioapic_pin_count(ioapic);
+ struct ioapic *ip = &ioapics[ioapic];
+ struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg;
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+ if (cfg->type == IOAPIC_DOMAIN_INVALID)
+ return 0;
+
+ ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops,
+ (void *)(long)ioapic);
+ if(!ip->irqdomain)
+ return -ENOMEM;
+
+ if (cfg->type == IOAPIC_DOMAIN_LEGACY ||
+ cfg->type == IOAPIC_DOMAIN_STRICT)
+ ioapic_dynirq_base = max(ioapic_dynirq_base,
+ gsi_cfg->gsi_end + 1);
+
+ if (gsi_cfg->gsi_base == 0)
+ irq_set_default_host(ip->irqdomain);
+
+ return 0;
+}
+
void __init setup_IO_APIC(void)
{
+ int ioapic;

/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
@@ -2929,6 +2957,9 @@ void __init setup_IO_APIC(void)
io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;

apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+ for_each_ioapic(ioapic)
+ BUG_ON(mp_irqdomain_create(ioapic));
+
/*
* Set up IO-APIC IRQ routing.
*/
@@ -3433,6 +3464,9 @@ unsigned int arch_dynirq_lower_bound(unsigned int from)
{
unsigned int min = gsi_top + nr_legacy_irqs();

+ if (ioapic_dynirq_base)
+ return ioapic_dynirq_base;
+
return from < min ? min : from;
}

@@ -3808,7 +3842,8 @@ static __init int bad_ioapic_register(int idx)
return 0;
}

-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
+void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ struct ioapic_domain_cfg *cfg)
{
int idx = 0;
int entries;
@@ -3822,6 +3857,11 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
ioapics[idx].mp_config.type = MP_IOAPIC;
ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
ioapics[idx].mp_config.apicaddr = address;
+ ioapics[idx].irqdomain = NULL;
+ if (cfg)
+ ioapics[idx].irqdomain_cfg = *cfg;
+ else
+ ioapics[idx].irqdomain_cfg.type = IOAPIC_DOMAIN_INVALID;

set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index e08a007bdacf..dd6936818330 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -177,7 +177,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
dn->full_name);
return;
}
- mp_register_ioapic(++ioapic_id, r.start, gsi_top);
+ mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL);
}

static void __init dtb_ioapic_setup(void)
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index b10e1132f316..ea8595e4cbd5 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -115,7 +115,7 @@ static void __init MP_bus_info(struct mpc_bus *m)
static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
if (m->flags & MPC_APIC_USABLE)
- mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, NULL);
}

static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index bcd1a703e3e6..8f2f789c6f04 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -82,7 +82,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table)
pentry = (struct sfi_apic_table_entry *)sb->pentry;

for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_top);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_top, NULL);
pentry++;
}

--
1.7.10.4

2014-06-09 08:21:47

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 26/42] x86, mpparse, irq: provide basic irqdomain support

Enhance mpparse to provide basic support of irqdomain.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/mpparse.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index ea8595e4cbd5..13c8e1f864fc 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/pci.h>
+#include <linux/irqdomain.h>

#include <asm/mtrr.h>
#include <asm/mpspec.h>
@@ -112,10 +113,17 @@ static void __init MP_bus_info(struct mpc_bus *m)
pr_warn("Unknown bustype %s - ignoring\n", str);
}

+static struct irq_domain_ops mp_ioapic_irqdomain_ops;
+
static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_LEGACY,
+ .ops = &mp_ioapic_irqdomain_ops,
+ };
+
if (m->flags & MPC_APIC_USABLE)
- mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, NULL);
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, &cfg);
}

static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
--
1.7.10.4

2014-06-09 08:22:02

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 27/42] x86, SFI, irq: provide basic irqdomain support

Enhance SFI to provide basic support of irqdomain with identity mapping
between GSIs and IRQs.

Some Intel MID platforms assumes identity mapping between GSI and IRQ,
so we can't dynamically allocate IRQ number on demand.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/pci/intel_mid_pci.c | 3 +++
arch/x86/platform/intel-mid/sfi.c | 2 ++
arch/x86/platform/sfi/sfi.c | 8 +++++++-
3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 84b9d672843d..fcbdc5fac2c6 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -217,6 +217,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
* IOAPIC RTE entries, so we just enable RTE for the device.
*/
+ if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
+ return -EBUSY;
+
irq_attr.ioapic = mp_find_ioapic(dev->irq);
irq_attr.ioapic_pin = dev->irq;
irq_attr.trigger = 1; /* level */
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
index 994c40bd7cb7..7161395e7de7 100644
--- a/arch/x86/platform/intel-mid/sfi.c
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -473,6 +473,8 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
/* PNW and CLV go with active low */
irq_attr.polarity = 1;
}
+ WARN_ON(mp_map_gsi_to_irq(irq,
+ IOAPIC_MAP_ALLOC) < 0);
io_apic_set_pci_routing(NULL, irq, &irq_attr);
}
} else {
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index 8f2f789c6f04..1fdaa57f41a5 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/io.h>
+#include <linux/irqdomain.h>

#include <asm/io_apic.h>
#include <asm/mpspec.h>
@@ -70,19 +71,24 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
#endif /* CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
+static struct irq_domain_ops sfi_ioapic_irqdomain_ops;

static int __init sfi_parse_ioapic(struct sfi_table_header *table)
{
struct sfi_table_simple *sb;
struct sfi_apic_table_entry *pentry;
int i, num;
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_STRICT,
+ .ops = &sfi_ioapic_irqdomain_ops,
+ };

sb = (struct sfi_table_simple *)table;
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry);
pentry = (struct sfi_apic_table_entry *)sb->pentry;

for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_top, NULL);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg);
pentry++;
}

--
1.7.10.4

2014-06-09 08:22:19

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 28/42] x86, devicetree, irq: use common mechanism to support irqdomain

Now the ioapic driver provides a common interface to create irqdomain,
so replace the private implementation.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/prom.h | 2 -
arch/x86/kernel/devicetree.c | 195 +++++++++++++-----------------------------
arch/x86/kernel/irqinit.c | 6 --
3 files changed, 61 insertions(+), 142 deletions(-)

diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index fbeb06ed0eaa..1d081ac1cd69 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -26,12 +26,10 @@
extern int of_ioapic;
extern u64 initial_dtb;
extern void add_dtb(u64 data);
-extern void x86_add_irq_domains(void);
void x86_of_pci_init(void);
void x86_dtb_init(void);
#else
static inline void add_dtb(u64 data) { }
-static inline void x86_add_irq_domains(void) { }
static inline void x86_of_pci_init(void) { }
static inline void x86_dtb_init(void) { }
#define of_ioapic 0
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index dd6936818330..ee4737f4a1af 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -166,84 +166,6 @@ static void __init dtb_lapic_setup(void)
#ifdef CONFIG_X86_IO_APIC
static unsigned int ioapic_id;

-static void __init dtb_add_ioapic(struct device_node *dn)
-{
- struct resource r;
- int ret;
-
- ret = of_address_to_resource(dn, 0, &r);
- if (ret) {
- printk(KERN_ERR "Can't obtain address from node %s.\n",
- dn->full_name);
- return;
- }
- mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL);
-}
-
-static void __init dtb_ioapic_setup(void)
-{
- struct device_node *dn;
-
- for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
- dtb_add_ioapic(dn);
-
- if (nr_ioapics) {
- of_ioapic = 1;
- return;
- }
- printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
-}
-#else
-static void __init dtb_ioapic_setup(void) {}
-#endif
-
-static void __init dtb_apic_setup(void)
-{
- dtb_lapic_setup();
- dtb_ioapic_setup();
-}
-
-#ifdef CONFIG_OF_FLATTREE
-static void __init x86_flattree_get_config(void)
-{
- u32 size, map_len;
- struct boot_param_header *dt;
-
- if (!initial_dtb)
- return;
-
- map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
- (u64)sizeof(struct boot_param_header));
-
- dt = early_memremap(initial_dtb, map_len);
- size = be32_to_cpu(dt->totalsize);
- if (map_len < size) {
- early_iounmap(dt, map_len);
- dt = early_memremap(initial_dtb, size);
- map_len = size;
- }
-
- initial_boot_params = dt;
- unflatten_and_copy_device_tree();
- early_iounmap(dt, map_len);
-}
-#else
-static inline void x86_flattree_get_config(void) { }
-#endif
-
-void __init x86_dtb_init(void)
-{
- x86_flattree_get_config();
-
- if (!of_have_populated_dt())
- return;
-
- dtb_setup_hpet();
- dtb_apic_setup();
-}
-
-#ifdef CONFIG_X86_IO_APIC
-
struct of_ioapic_type {
u32 out_type;
u32 trigger;
@@ -294,7 +216,7 @@ static int ioapic_xlate(struct irq_domain *domain,

it = &of_ioapic_type[intspec[1]];

- idx = (u32) domain->host_data;
+ idx = (u32)(long)domain->host_data;
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);

rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
@@ -311,78 +233,83 @@ const struct irq_domain_ops ioapic_irq_domain_ops = {
.xlate = ioapic_xlate,
};

-static void dt_add_ioapic_domain(unsigned int ioapic_num,
- struct device_node *np)
+static void __init dtb_add_ioapic(struct device_node *dn)
{
- struct irq_domain *id;
- struct mp_ioapic_gsi *gsi_cfg;
+ struct resource r;
int ret;
- int num, legacy_irqs = nr_legacy_irqs();
-
- gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
- num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
-
- id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
- (void *)ioapic_num);
- BUG_ON(!id);
- if (gsi_cfg->gsi_base == 0) {
- /*
- * The first nr_legacy_irqs() irq descs are allocated in
- * early_irq_init() and need just a mapping. The
- * remaining irqs need both. All of them are preallocated
- * and assigned so we can keep the 1:1 mapping which the ioapic
- * is having.
- */
- irq_domain_associate_many(id, 0, 0, legacy_irqs);
-
- if (num > legacy_irqs) {
- ret = irq_create_strict_mappings(id, legacy_irqs,
- legacy_irqs, num - legacy_irqs);
- if (ret)
- pr_err("Error creating mapping for the "
- "remaining IRQs: %d\n", ret);
- }
- irq_set_default_host(id);
- } else {
- ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
- if (ret)
- pr_err("Error creating IRQ mapping: %d\n", ret);
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_DYNAMIC,
+ .ops = &ioapic_irq_domain_ops,
+ .dev = dn,
+ };
+
+ ret = of_address_to_resource(dn, 0, &r);
+ if (ret) {
+ printk(KERN_ERR "Can't obtain address from node %s.\n",
+ dn->full_name);
+ return;
}
+ mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
}

-static void __init ioapic_add_ofnode(struct device_node *np)
+static void __init dtb_ioapic_setup(void)
{
- struct resource r;
- int i, ret;
+ struct device_node *dn;

- ret = of_address_to_resource(np, 0, &r);
- if (ret) {
- printk(KERN_ERR "Failed to obtain address for %s\n",
- np->full_name);
+ for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
+ dtb_add_ioapic(dn);
+
+ if (nr_ioapics) {
+ of_ioapic = 1;
return;
}
+ printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif

- for (i = 0; i < nr_ioapics; i++) {
- if (r.start == mpc_ioapic_addr(i)) {
- dt_add_ioapic_domain(i, np);
- return;
- }
- }
- printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
+static void __init dtb_apic_setup(void)
+{
+ dtb_lapic_setup();
+ dtb_ioapic_setup();
}

-void __init x86_add_irq_domains(void)
+#ifdef CONFIG_OF_FLATTREE
+static void __init x86_flattree_get_config(void)
{
- struct device_node *dp;
+ u32 size, map_len;
+ struct boot_param_header *dt;

- if (!of_have_populated_dt())
+ if (!initial_dtb)
return;

- for_each_node_with_property(dp, "interrupt-controller") {
- if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
- ioapic_add_ofnode(dp);
+ map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
+ (u64)sizeof(struct boot_param_header));
+
+ dt = early_memremap(initial_dtb, map_len);
+ size = be32_to_cpu(dt->totalsize);
+ if (map_len < size) {
+ early_iounmap(dt, map_len);
+ dt = early_memremap(initial_dtb, size);
+ map_len = size;
}
+
+ initial_boot_params = dt;
+ unflatten_and_copy_device_tree();
+ early_iounmap(dt, map_len);
}
#else
-void __init x86_add_irq_domains(void) { }
+static inline void x86_flattree_get_config(void) { }
#endif
+
+void __init x86_dtb_init(void)
+{
+ x86_flattree_get_config();
+
+ if (!of_have_populated_dt())
+ return;
+
+ dtb_setup_hpet();
+ dtb_apic_setup();
+}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index a0111e91eb4b..1e6cff5814fa 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -87,12 +87,6 @@ void __init init_IRQ(void)
int i;

/*
- * We probably need a better place for this, but it works for
- * now ...
- */
- x86_add_irq_domains();
-
- /*
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
* If these IRQ's are handled by legacy interrupt-controllers like PIC,
* then this configuration will likely be static after the boot. If
--
1.7.10.4

2014-06-09 08:22:33

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 29/42] x86, irq: introduce two helper functions to support irqdomain map operation

Currently there are multiple entries to program IOAPIC pins, such as
io_apic_setup_irq_pin_once(), io_apic_set_pci_routing() and
setup_IO_APIC_irq_extra() etc.

This patch introduces two functions to help consolidate the code to
program IOAPIC pins. Function mp_set_pin_attr() is used to optionally
set trigger, polarity and NUMA node property for an IOAPIC pin.
If mp_set_pin_attr() is not invoked for a pin, the default configuration
from BIOS will be used.

Function mp_irqdomain_map() is an common implementation of irqdomain map()
operation. It figures out attribures for pin and then actually programs
the IOAPIC pin. We hope this will be the only entrance for programming
IOAPIC pin.

And the flow will:
1) caller such as xxx_pci_irq_enable figures out pin attributes.
2) Invoke mp_set_pin_attr() to set attributes for a pin. If the pin has
already bin programmed, mp_set_pin_attr() will aslo detects attribute
confictions.
3) Invoke mp_map_pin_to_irq()
3.1) If IRQ has already been assigned, return irq_find_mapping()
3.2) Else irq_create_mapping()
->irq_domain_associate()
->mp_irqdomain_map()
->io_apic_setup_irq_pin()

So every pin will only programmed once by mp_irqdomain_map(), so we
could kill io_apic_setup_irq_pin_once(), io_apic_set_pci_routing() and
setup_IO_APIC_irq_extra() etc.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/io_apic.h | 5 ++
arch/x86/kernel/apic/io_apic.c | 99 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 3e4bea3a52b1..c53587868590 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -173,7 +173,9 @@ enum ioapic_domain_type {
};

struct device_node;
+struct irq_domain;
struct irq_domain_ops;
+
struct ioapic_domain_cfg {
enum ioapic_domain_type type;
const struct irq_domain_ops *ops;
@@ -192,6 +194,9 @@ extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
struct ioapic_domain_cfg *cfg);
+extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq);
+extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
extern void __init pre_init_apic_IRQ0(void);

extern void mp_save_irq(struct mpc_intsrc *m);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 9c5f70699a80..61aae90f7e23 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -87,6 +87,14 @@ static DEFINE_RAW_SPINLOCK(vector_lock);
static DEFINE_MUTEX(ioapic_mutex);
static unsigned int ioapic_dynirq_base;

+struct mp_pin_info {
+ int trigger;
+ int polarity;
+ int node;
+ int set;
+ u32 count;
+};
+
static struct ioapic {
/*
* # of IRQ routing registers
@@ -102,6 +110,7 @@ static struct ioapic {
struct mp_ioapic_gsi gsi_config;
struct ioapic_domain_cfg irqdomain_cfg;
struct irq_domain *irqdomain;
+ struct mp_pin_info *pin_info;
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];

@@ -147,6 +156,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
}

+static inline struct mp_pin_info *mp_pin_info(int ioapic_idx, int pin)
+{
+ return ioapics[ioapic_idx].pin_info + pin;
+}
+
static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
{
return ioapics[ioapic].irqdomain;
@@ -1006,6 +1020,7 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
{
int irq;
struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+ struct mp_pin_info *info = mp_pin_info(ioapic, pin);

/*
* Don't use irqdomain to manage ISA IRQs because there may be
@@ -1034,6 +1049,13 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
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;
@@ -2923,18 +2945,27 @@ out:

static int mp_irqdomain_create(int ioapic)
{
+ size_t size;
int hwirqs = mp_ioapic_pin_count(ioapic);
struct ioapic *ip = &ioapics[ioapic];
struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg;
struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);

+ size = sizeof(struct mp_pin_info) * mp_ioapic_pin_count(ioapic);
+ ip->pin_info = kzalloc(size, GFP_KERNEL);
+ if (!ip->pin_info)
+ return -ENOMEM;
+
if (cfg->type == IOAPIC_DOMAIN_INVALID)
return 0;

ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops,
(void *)(long)ioapic);
- if(!ip->irqdomain)
+ if(!ip->irqdomain) {
+ kfree(ip->pin_info);
+ ip->pin_info = NULL;
return -ENOMEM;
+ }

if (cfg->type == IOAPIC_DOMAIN_LEGACY ||
cfg->type == IOAPIC_DOMAIN_STRICT)
@@ -3898,6 +3929,72 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
nr_ioapics++;
}

+int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq)
+{
+ int ioapic = (int)(long)domain->host_data;
+ struct mp_pin_info *info = mp_pin_info(ioapic, hwirq);
+ struct io_apic_irq_attr attr;
+
+ /*
+ * 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, virq))
+ return 0;
+
+ /* Get default attribute if not set by caller yet */
+ if (!info->set) {
+ u32 gsi = mp_pin_to_gsi(ioapic, hwirq);
+
+ if (acpi_get_override_irq(gsi, &info->trigger,
+ &info->polarity) < 0) {
+ /*
+ * PCI interrupts are always polarity one level
+ * triggered.
+ */
+ info->trigger = 1;
+ info->polarity = 1;
+ }
+ info->node = NUMA_NO_NODE;
+ info->set = 1;
+ }
+ set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger,
+ info->polarity);
+
+ return io_apic_setup_irq_pin(virq, info->node, &attr);
+}
+
+int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
+{
+ int ret = 0;
+ int ioapic, pin;
+ struct mp_pin_info *info;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return -ENODEV;
+
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ info = mp_pin_info(ioapic, pin);
+ trigger = trigger ? 1 : 0;
+ polarity = polarity ? 1 : 0;
+
+ mutex_lock(&ioapic_mutex);
+ if (!info->set) {
+ info->trigger = trigger;
+ info->polarity = polarity;
+ info->node = node;
+ info->set = 1;
+ } else if (info->trigger != trigger || info->polarity != polarity) {
+ ret = -EBUSY;
+ }
+ mutex_unlock(&ioapic_mutex);
+
+ return ret;
+}
+
/* Enable IOAPIC early just for system timer */
void __init pre_init_apic_IRQ0(void)
{
--
1.7.10.4

2014-06-09 08:22:43

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 31/42] x86, irq, mpparse: use common irqdomain map interface to program IOAPIC pins

Refine mpparse to use common irqdomain map interface to program IOAPIC pins,
so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/mpparse.c | 4 +++-
arch/x86/pci/irq.c | 2 --
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 13c8e1f864fc..faf503aa3b70 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -113,7 +113,9 @@ static void __init MP_bus_info(struct mpc_bus *m)
pr_warn("Unknown bustype %s - ignoring\n", str);
}

-static struct irq_domain_ops mp_ioapic_irqdomain_ops;
+static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};

static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 84112f55dd7a..e4200e5e775e 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -1227,8 +1227,6 @@ static int pirq_enable_irq(struct pci_dev *dev)
}
dev = temp_dev;
if (irq >= 0) {
- io_apic_set_pci_routing(&dev->dev, irq,
- &irq_attr);
dev->irq = irq;
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
--
1.7.10.4

2014-06-09 08:22:58

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 32/42] x86, irq, SFI: use common irqdomain map interface to program IOAPIC pins

Refine SFI to use common irqdomain map interface to program IOAPIC pins,
so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/pci/intel_mid_pci.c | 19 +++++-------
arch/x86/platform/intel-mid/sfi.c | 58 ++++++++++++++++---------------------
arch/x86/platform/sfi/sfi.c | 4 ++-
3 files changed, 35 insertions(+), 46 deletions(-)

diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index fcbdc5fac2c6..337d165c64f1 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -208,27 +208,22 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,

static int intel_mid_pci_irq_enable(struct pci_dev *dev)
{
- u8 pin;
- struct io_apic_irq_attr irq_attr;
+ int polarity;

- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
+ polarity = 0; /* active high */
+ else
+ polarity = 1; /* active low */

/*
* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
* IOAPIC RTE entries, so we just enable RTE for the device.
*/
+ if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
+ return -EBUSY;
if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
return -EBUSY;

- irq_attr.ioapic = mp_find_ioapic(dev->irq);
- irq_attr.ioapic_pin = dev->irq;
- irq_attr.trigger = 1; /* level */
- if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
- irq_attr.polarity = 0; /* active high */
- else
- irq_attr.polarity = 1; /* active low */
- io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
-
return 0;
}

diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
index 7161395e7de7..3c53a90fdb18 100644
--- a/arch/x86/platform/intel-mid/sfi.c
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -432,9 +432,8 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
struct sfi_table_simple *sb;
struct sfi_device_table_entry *pentry;
struct devs_id *dev = NULL;
- int num, i;
- int ioapic;
- struct io_apic_irq_attr irq_attr;
+ int num, i, ret;
+ int polarity;

sb = (struct sfi_table_simple *)table;
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
@@ -448,37 +447,30 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
* devices, but they have separate RTE entry in IOAPIC
* so we have to enable them one by one here
*/
- ioapic = mp_find_ioapic(irq);
- if (ioapic >= 0) {
- irq_attr.ioapic = ioapic;
- irq_attr.ioapic_pin = irq;
- irq_attr.trigger = 1;
- if (intel_mid_identify_cpu() ==
- INTEL_MID_CPU_CHIP_TANGIER) {
- if (!strncmp(pentry->name,
- "r69001-ts-i2c", 13))
- /* active low */
- irq_attr.polarity = 1;
- else if (!strncmp(pentry->name,
- "synaptics_3202", 14))
- /* active low */
- irq_attr.polarity = 1;
- else if (irq == 41)
- /* fast_int_1 */
- irq_attr.polarity = 1;
- else
- /* active high */
- irq_attr.polarity = 0;
- } else {
- /* PNW and CLV go with active low */
- irq_attr.polarity = 1;
- }
- WARN_ON(mp_map_gsi_to_irq(irq,
- IOAPIC_MAP_ALLOC) < 0);
- io_apic_set_pci_routing(NULL, irq, &irq_attr);
+ if (intel_mid_identify_cpu() ==
+ INTEL_MID_CPU_CHIP_TANGIER) {
+ if (!strncmp(pentry->name, "r69001-ts-i2c", 13))
+ /* active low */
+ polarity = 1;
+ else if (!strncmp(pentry->name,
+ "synaptics_3202", 14))
+ /* active low */
+ polarity = 1;
+ else if (irq == 41)
+ /* fast_int_1 */
+ polarity = 1;
+ else
+ /* active high */
+ polarity = 0;
+ } else {
+ /* PNW and CLV go with active low */
+ polarity = 1;
}
- } else {
- irq = 0; /* No irq */
+
+ ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
+ if (ret == 0)
+ ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC);
+ WARN_ON(ret < 0);
}

dev = get_device_id(pentry->type, pentry->name);
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index 1fdaa57f41a5..2a8a74f3bd76 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -71,7 +71,9 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
#endif /* CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
-static struct irq_domain_ops sfi_ioapic_irqdomain_ops;
+static struct irq_domain_ops sfi_ioapic_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};

static int __init sfi_parse_ioapic(struct sfi_table_header *table)
{
--
1.7.10.4

2014-06-09 08:23:24

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 33/42] x86, irq, devicetree: use common irqdomain map interface to program IOAPIC pins

Refine devicetree to use common irqdomain map interface to program
IOAPIC pins, so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/devicetree.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index ee4737f4a1af..0c938dd7b3c8 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -201,10 +201,8 @@ static int ioapic_xlate(struct irq_domain *domain,
const u32 *intspec, u32 intsize,
irq_hw_number_t *out_hwirq, u32 *out_type)
{
- struct io_apic_irq_attr attr;
struct of_ioapic_type *it;
- u32 line, idx;
- int rc;
+ u32 line, idx, gsi;

if (WARN_ON(intsize < 2))
return -EINVAL;
@@ -217,12 +215,9 @@ static int ioapic_xlate(struct irq_domain *domain,
it = &of_ioapic_type[intspec[1]];

idx = (u32)(long)domain->host_data;
- set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
-
- rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
- cpu_to_node(0), &attr);
- if (rc)
- return rc;
+ gsi = mp_pin_to_gsi(idx, line);
+ if (mp_set_gsi_attr(gsi, it->trigger, it->polarity, cpu_to_node(0)))
+ return -EBUSY;

*out_hwirq = line;
*out_type = it->out_type;
@@ -230,6 +225,7 @@ static int ioapic_xlate(struct irq_domain *domain,
}

const struct irq_domain_ops ioapic_irq_domain_ops = {
+ .map = mp_irqdomain_map,
.xlate = ioapic_xlate,
};

--
1.7.10.4

2014-06-09 08:23:41

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 34/42] x86, irq: clean up unused IOAPIC interface

Now we have converted all x86 platforms to use the common irqdomain map
interface. There's no caller of io_apic_set_pci_routing(),
setup_IO_APIC_irq_extra() and io_apic_setup_irq_pin_once() any more,
so kill them.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/io_apic.h | 9 ------
arch/x86/kernel/apic/io_apic.c | 70 ----------------------------------------
2 files changed, 79 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index c53587868590..af6f9d4309bf 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -141,9 +141,6 @@ extern int noioapicreroute;

struct io_apic_irq_attr;
struct irq_cfg;
-extern int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr);
-extern void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_insert_resources(void);

extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
@@ -155,8 +152,6 @@ extern void native_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id);
extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
-extern int io_apic_setup_irq_pin_once(unsigned int irq, int node,
- struct io_apic_irq_attr *attr);

extern int save_ioapic_entries(void);
extern void mask_ioapic_entries(void);
@@ -240,10 +235,6 @@ static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }

-struct io_apic_irq_attr;
-static inline int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr) { return 0; }
-
static inline int save_ioapic_entries(void)
{
return -ENOMEM;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 61aae90f7e23..1623f5dba6c2 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -111,7 +111,6 @@ static struct ioapic {
struct ioapic_domain_cfg irqdomain_cfg;
struct irq_domain *irqdomain;
struct mp_pin_info *pin_info;
- DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];

#define mpc_ioapic_ver(ioapic_idx) ioapics[ioapic_idx].mp_config.apicver
@@ -1524,38 +1523,6 @@ static void __init setup_IO_APIC_irqs(void)
}

/*
- * for the gsi that is not in first ioapic
- * but could not use acpi_register_gsi()
- * like some special sci in IBM x3330
- */
-void setup_IO_APIC_irq_extra(u32 gsi)
-{
- int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0);
- struct io_apic_irq_attr attr;
-
- /*
- * Convert 'gsi' to 'ioapic.pin'.
- */
- ioapic_idx = mp_find_ioapic(gsi);
- if (ioapic_idx < 0)
- return;
-
- pin = mp_find_ioapic_pin(ioapic_idx, gsi);
- idx = find_irq_entry(ioapic_idx, pin, mp_INT);
- if (idx == -1)
- return;
-
- irq = pin_2_irq(idx, ioapic_idx, pin, IOAPIC_MAP_ALLOC);
- if (irq < 0 || mp_init_irq_at_boot(ioapic_idx, irq))
- return;
-
- set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
- irq_polarity(idx));
-
- io_apic_setup_irq_pin_once(irq, node, &attr);
-}
-
-/*
* Set up the timer pin, possibly with the 8259A-master behind.
*/
static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
@@ -3454,27 +3421,6 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
return ret;
}

-int io_apic_setup_irq_pin_once(unsigned int irq, int node,
- struct io_apic_irq_attr *attr)
-{
- unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin;
- int ret;
- struct IO_APIC_route_entry orig_entry;
-
- /* Avoid redundant programming */
- if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) {
- pr_debug("Pin %d-%d already programmed\n", mpc_ioapic_id(ioapic_idx), pin);
- orig_entry = ioapic_read_entry(attr->ioapic, pin);
- if (attr->trigger == orig_entry.trigger && attr->polarity == orig_entry.polarity)
- return 0;
- return -EBUSY;
- }
- ret = io_apic_setup_irq_pin(irq, node, attr);
- if (!ret)
- set_bit(pin, ioapics[ioapic_idx].pin_programmed);
- return ret;
-}
-
static int __init io_apic_get_redir_entries(int ioapic)
{
union IO_APIC_reg_01 reg_01;
@@ -3521,22 +3467,6 @@ int __init arch_probe_nr_irqs(void)
return 0;
}

-int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr)
-{
- int node;
-
- if (!IO_APIC_IRQ(irq)) {
- apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
- irq_attr->ioapic);
- return -EINVAL;
- }
-
- node = dev ? dev_to_node(dev) : cpu_to_node(0);
-
- return io_apic_setup_irq_pin_once(irq, node, irq_attr);
-}
-
#ifdef CONFIG_X86_32
static int __init io_apic_get_unique_id(int ioapic, int apic_id)
{
--
1.7.10.4

2014-06-09 08:23:49

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 36/42] genirq: export irq_domain_disassociate() to architecture interrupt drivers

Export irq_domain_disassociate() to architecture interrupt drivers,
so it could be used to handle legacy IRQ descriptors on x86.

Signed-off-by: Jiang Liu <[email protected]>
---
include/linux/irqdomain.h | 2 ++
kernel/irq/irqdomain.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index c983ed18c332..b0f9d16e48f6 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -172,6 +172,8 @@ extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
extern void irq_domain_associate_many(struct irq_domain *domain,
unsigned int irq_base,
irq_hw_number_t hwirq_base, int count);
+extern void irq_domain_disassociate(struct irq_domain *domain,
+ unsigned int irq);

extern unsigned int irq_create_mapping(struct irq_domain *host,
irq_hw_number_t hwirq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index eb5e10e32e05..6534ff6ce02e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -231,7 +231,7 @@ void irq_set_default_host(struct irq_domain *domain)
}
EXPORT_SYMBOL_GPL(irq_set_default_host);

-static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
+void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
{
struct irq_data *irq_data = irq_get_irq_data(irq);
irq_hw_number_t hwirq;
--
1.7.10.4

2014-06-09 08:23:46

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 35/42] 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 <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 15 +-----
arch/x86/kernel/apic/io_apic.c | 98 ++++++++++++++++------------------------
2 files changed, 40 insertions(+), 73 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index edb48a8e0a0d..ef3336ab6432 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -101,17 +101,6 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

#define ACPI_INVALID_GSI INT_MIN

-static int map_gsi_to_irq(unsigned int gsi, unsigned int flags)
-{
- int i;
-
- for (i = 0; i < nr_legacy_irqs(); i++)
- if (isa_irq_to_gsi[i] == gsi)
- return i;
-
- return mp_map_gsi_to_irq(gsi, flags);
-}
-
/*
* This is just a simple wrapper around early_ioremap(),
* with sanity checks for phys == 0 and size == 0.
@@ -422,7 +411,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
return -1;
}

- irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
+ irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
if (irq < 0)
return irq;

@@ -603,7 +592,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)

int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- int irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+ int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);

if (irq >= 0) {
*irqp = irq;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 1623f5dba6c2..5fc76cf51e44 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);
+ }
}

/*
--
1.7.10.4

2014-06-09 08:24:24

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 40/42] x86, irq, SFI: release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/pci/intel_mid_pci.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 337d165c64f1..09fece368592 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -227,6 +227,12 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
return 0;
}

+static void intel_mid_pci_irq_disable(struct pci_dev *dev)
+{
+ if (dev->irq > 0)
+ mp_unmap_irq(dev->irq);
+}
+
struct pci_ops intel_mid_pci_ops = {
.read = pci_read,
.write = pci_write,
@@ -243,6 +249,7 @@ int __init intel_mid_pci_init(void)
pr_info("Intel MID platform detected, using MID PCI ops\n");
pci_mmcfg_late_init();
pcibios_enable_irq = intel_mid_pci_irq_enable;
+ pcibios_disable_irq = intel_mid_pci_irq_disable;
pci_root_ops = intel_mid_pci_ops;
pci_soc_mode = 1;
/* Continue with standard init */
--
1.7.10.4

2014-06-09 08:24:27

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 38/42] x86, irq, ACPI: release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 27 +++++++++++++++++++++++++++
drivers/acpi/pci_irq.c | 3 ++-
2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index ef3336ab6432..9306b4e87490 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -421,8 +421,24 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
return irq;
}

+static void mp_unregister_gsi(u32 gsi)
+{
+ int irq;
+
+ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ return;
+
+ if (acpi_gbl_FADT.sci_interrupt == gsi)
+ return;
+
+ irq = mp_map_gsi_to_irq(gsi, 0);
+ if (irq > 0)
+ mp_unmap_irq(irq);
+}
+
static struct irq_domain_ops acpi_irqdomain_ops = {
.map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
};

static int __init
@@ -640,8 +656,16 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
return irq;
}

+static void acpi_unregister_gsi_ioapic(u32 gsi)
+{
+#ifdef CONFIG_X86_IO_APIC
+ mp_unregister_gsi(gsi);
+#endif
+}
+
int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
int trigger, int polarity) = acpi_register_gsi_pic;
+void (*__acpi_unregister_gsi)(u32 gsi) = NULL;

#ifdef CONFIG_ACPI_SLEEP
int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel;
@@ -661,6 +685,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);

void acpi_unregister_gsi(u32 gsi)
{
+ if (__acpi_unregister_gsi)
+ (*__acpi_unregister_gsi)(gsi);
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);

@@ -668,6 +694,7 @@ static void __init acpi_set_irq_model_ioapic(void)
{
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
__acpi_register_gsi = acpi_register_gsi_ioapic;
+ __acpi_unregister_gsi = acpi_unregister_gsi_ioapic;
acpi_ioapic = 1;
}

diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 9c62340c2360..6ba463ceccc6 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -498,5 +498,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
*/

dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
- acpi_unregister_gsi(gsi);
+ if (gsi >= 0 && dev->irq > 0)
+ acpi_unregister_gsi(gsi);
}
--
1.7.10.4

2014-06-09 08:24:33

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 41/42] x86, irq, devicetree: release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/devicetree.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 0c938dd7b3c8..8dcd11b08669 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -226,6 +226,7 @@ static int ioapic_xlate(struct irq_domain *domain,

const struct irq_domain_ops ioapic_irq_domain_ops = {
.map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
.xlate = ioapic_xlate,
};

--
1.7.10.4

2014-06-09 08:25:08

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 42/42] x86, irq: clean up irqdomain transition code

Now we have completely switched to irqdomain, so clean up transition code
in IOAPIC drivers.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 28 +++++++++++-----------------
1 file changed, 11 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 60555354b331..26490336ef6f 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -86,6 +86,7 @@ static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
static DEFINE_MUTEX(ioapic_mutex);
static unsigned int ioapic_dynirq_base;
+static int ioapic_initialized;

struct mp_pin_info {
int trigger;
@@ -1034,13 +1035,8 @@ 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;
- }
+ if (!domain)
+ return -1;

mutex_lock(&ioapic_mutex);

@@ -2986,6 +2982,8 @@ void __init setup_IO_APIC(void)
init_IO_APIC_traps();
if (nr_legacy_irqs())
check_timer();
+
+ ioapic_initialized = 1;
}

/*
@@ -3457,12 +3455,11 @@ static int __init io_apic_get_redir_entries(int ioapic)

unsigned int arch_dynirq_lower_bound(unsigned int from)
{
- unsigned int min = gsi_top + nr_legacy_irqs();
-
- if (ioapic_dynirq_base)
- return ioapic_dynirq_base;
-
- return from < min ? min : from;
+ /*
+ * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
+ * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
+ */
+ return ioapic_initialized ? ioapic_dynirq_base : gsi_top;
}

int __init arch_probe_nr_irqs(void)
@@ -3837,10 +3834,7 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
ioapics[idx].mp_config.apicaddr = address;
ioapics[idx].irqdomain = NULL;
- if (cfg)
- ioapics[idx].irqdomain_cfg = *cfg;
- else
- ioapics[idx].irqdomain_cfg.type = IOAPIC_DOMAIN_INVALID;
+ ioapics[idx].irqdomain_cfg = *cfg;

set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);

--
1.7.10.4

2014-06-09 08:24:21

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 39/42] x86, irq, mpparse: release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/mpparse.c | 1 +
arch/x86/pci/irq.c | 13 +++++++++++--
2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index faf503aa3b70..fde86d2b79f8 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -115,6 +115,7 @@ static void __init MP_bus_info(struct mpc_bus *m)

static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
.map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
};

static void __init MP_ioapic_info(struct mpc_ioapic *m)
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index e4200e5e775e..748cfe8ab322 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -26,6 +26,7 @@ static int acer_tm360_irqrouting;
static struct irq_routing_table *pirq_table;

static int pirq_enable_irq(struct pci_dev *dev);
+static void pirq_disable_irq(struct pci_dev *dev);

/*
* Never use: 0, 1, 2 (timer, keyboard, and cascade)
@@ -53,7 +54,7 @@ struct irq_router_handler {
};

int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
-void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq;

/*
* Check passed address for the PCI IRQ Routing Table signature
@@ -1186,7 +1187,7 @@ void pcibios_penalize_isa_irq(int irq, int active)

static int pirq_enable_irq(struct pci_dev *dev)
{
- u8 pin;
+ u8 pin = 0;

pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin && !pcibios_lookup_irq(dev, 1)) {
@@ -1252,3 +1253,11 @@ static int pirq_enable_irq(struct pci_dev *dev)
}
return 0;
}
+
+static void pirq_disable_irq(struct pci_dev *dev)
+{
+ if (io_apic_assign_pci_irqs && dev->irq) {
+ mp_unmap_irq(dev->irq);
+ dev->irq = 0;
+ }
+}
--
1.7.10.4

2014-06-09 08:26:21

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 37/42] x86, irq: introduce helper functions to release IOAPIC pin

Introduce function mp_unmap_irq() to release IOAPIC IRQ when IRQ is not
used any more, which will typically called by pcibios_disabled_irq.

And function mp_irqdomain_unmap() is a common implementation of
irq_domain_ops.unmap for IOAPIC.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/io_apic.h | 3 ++
arch/x86/kernel/apic/io_apic.c | 61 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index af6f9d4309bf..0aeed5ca356e 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -187,10 +187,12 @@ extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
+extern void mp_unmap_irq(int irq);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
struct ioapic_domain_cfg *cfg);
extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
irq_hw_number_t hwirq);
+extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
extern void __init pre_init_apic_IRQ0(void);

@@ -234,6 +236,7 @@ static inline void ioapic_insert_resources(void) { }
static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
+static inline void mp_unmap_irq(int irq) { }

static inline int save_ioapic_entries(void)
{
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 5fc76cf51e44..60555354b331 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -467,6 +467,21 @@ static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pi
return 0;
}

+static void __remove_pin_from_irq(struct irq_cfg *cfg, int apic, int pin)
+{
+ struct irq_pin_list **last, *entry;
+
+ last = &cfg->irq_2_pin;
+ for_each_irq_pin(entry, cfg->irq_2_pin)
+ if (entry->apic == apic && entry->pin == pin) {
+ *last = entry->next;
+ kfree(entry);
+ return;
+ } else {
+ last = &entry->next;
+ }
+}
+
static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
{
if (__add_pin_to_irq_node(cfg, node, apic, pin))
@@ -1119,6 +1134,31 @@ int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
}

+void mp_unmap_irq(int irq)
+{
+ struct irq_data *data = irq_get_irq_data(irq);
+ struct mp_pin_info *info;
+ int ioapic, pin;
+
+ if (!data || !data->domain)
+ return;
+
+ ioapic = (int)(long)data->domain->host_data;
+ pin = (int)data->hwirq;
+ info = mp_pin_info(ioapic, pin);
+
+ mutex_lock(&ioapic_mutex);
+ if (--info->count == 0) {
+ info->set = 0;
+ if (irq < nr_legacy_irqs() &&
+ ioapics[ioapic].irqdomain_cfg.type == IOAPIC_DOMAIN_LEGACY)
+ mp_irqdomain_unmap(data->domain, irq);
+ else
+ irq_dispose_mapping(irq);
+ }
+ mutex_unlock(&ioapic_mutex);
+}
+
/*
* Find a specific PCI IRQ entry.
* Not an __init, possibly needed by modules
@@ -3874,6 +3914,27 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
return io_apic_setup_irq_pin(virq, info->node, &attr);
}

+void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq)
+{
+ struct irq_data *data = irq_get_irq_data(virq);
+ struct irq_cfg *cfg = irq_cfg(virq);
+ int ioapic = (int)(long)domain->host_data;
+ int pin = (int)data->hwirq;
+
+ /*
+ * 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, virq))
+ return;
+
+ ioapic_mask_entry(ioapic, pin);
+ __remove_pin_from_irq(cfg, ioapic, pin);
+ WARN_ON(cfg->irq_2_pin != NULL);
+ arch_teardown_hwirq(virq);
+}
+
int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
{
int ret = 0;
--
1.7.10.4

2014-06-09 08:27:21

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 30/42] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins

Refine ACPI to use common irqdomain map interface to program IOAPIC pins,
so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 44 ++++++++++++-------------------------------
1 file changed, 12 insertions(+), 32 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 82ec56a4c6f4..edb48a8e0a0d 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -405,11 +405,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
- int irq;
- int ioapic;
- int ioapic_pin;
- struct io_apic_irq_attr irq_attr;
- int ret;
+ int irq, node;

if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
@@ -418,39 +414,27 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;

+ trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
+ polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
+ node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
+ if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
+ pr_warn("Failed to set pin attr for GSI%d\n", gsi);
+ return -1;
+ }
+
irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
if (irq < 0)
return irq;

- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0) {
- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
- return gsi;
- }
-
- ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-
- if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mpc_ioapic_id(ioapic),
- ioapic_pin);
- return gsi;
- }
-
if (enable_update_mptable)
mp_config_acpi_gsi(dev, gsi, trigger, polarity);

- set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
- trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
- if (ret < 0)
- irq = -1;
-
return irq;
}

-static struct irq_domain_ops acpi_irqdomain_ops;
+static struct irq_domain_ops acpi_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};

static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
@@ -622,10 +606,6 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
int irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);

if (irq >= 0) {
-#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
-#endif
*irqp = irq;
return 0;
}
--
1.7.10.4

2014-06-09 08:28:16

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 25/42] x86, ACPI, irq: provide basic irqdomain support

Enhance ACPI driver to provide basic irqdomain support for IOAPIC.

We will build identity mapping for IOAPICs hosting legacy IRQs,
otherwise dynamically allocate IRQ numbers for IOAPIC pins on demand.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 15d988cfa335..82ec56a4c6f4 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
#include <linux/ioport.h>
@@ -449,10 +450,16 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
return irq;
}

+static struct irq_domain_ops acpi_irqdomain_ops;
+
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
{
struct acpi_madt_io_apic *ioapic = NULL;
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_DYNAMIC,
+ .ops = &acpi_irqdomain_ops,
+ };

ioapic = (struct acpi_madt_io_apic *)header;

@@ -461,8 +468,12 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)

acpi_table_print_madt_entry(header);

- mp_register_ioapic(ioapic->id,
- ioapic->address, ioapic->global_irq_base, NULL);
+ /* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */
+ if (ioapic->global_irq_base < nr_legacy_irqs())
+ cfg.type = IOAPIC_DOMAIN_LEGACY;
+
+ mp_register_ioapic(ioapic->id, ioapic->address, ioapic->global_irq_base,
+ &cfg);

return 0;
}
--
1.7.10.4

2014-06-09 08:29:05

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 22/42] x86, irq, ACPI: change __acpi_register_gsi to return IRQ number instead of GSI

Currently __acpi_register_gsi is defined to return GSI number and
may be set to acpi_register_gsi_pic(), acpi_register_gsi_ioapic(),
acpi_register_gsi_xen_hvm() and acpi_register_gsi_xen().

Among which, acpi_register_gsi_ioapic() returns GSI number, but
acpi_register_gsi_xen_hvm() and acpi_register_gsi_xen() actually
returns IRQ number instead of GSI. And for acpi_register_gsi_pic(),
GSI number equals to IRQ number.

So change acpi_register_gsi_ioapic() to return IRQ number, it also
simplifies the code.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index e5e645fdd690..0c9dcf6824b6 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -419,7 +419,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,

irq = map_gsi_to_irq(gsi);
if (irq < 0)
- return ACPI_INVALID_GSI;
+ return irq;

ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
@@ -444,12 +444,11 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
if (ret < 0)
- gsi = ACPI_INVALID_GSI;
+ irq = -1;

- return gsi;
+ return irq;
}

-
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
{
@@ -652,11 +651,13 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
int trigger, int polarity)
{
+ int irq = gsi;
+
#ifdef CONFIG_X86_IO_APIC
- gsi = mp_register_gsi(dev, gsi, trigger, polarity);
+ irq = mp_register_gsi(dev, gsi, trigger, polarity);
#endif

- return gsi;
+ return irq;
}

int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
@@ -674,13 +675,7 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int plat_gsi;
-
- plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
- if (plat_gsi != ACPI_INVALID_GSI)
- return map_gsi_to_irq(plat_gsi);
-
- return -1;
+ return (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

--
1.7.10.4

2014-06-09 08:29:57

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 15/42] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain

Reorganize function IO_APIC_get_PCI_irq_vector() a bit to better support
coming irqdomain.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 61 ++++++++++++++++++++++------------------
1 file changed, 33 insertions(+), 28 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 0b2fb2aac7a6..4ca3151d26f9 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -997,7 +997,7 @@ static int pin_2_irq(int idx, int apic, int pin)
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
struct io_apic_irq_attr *irq_attr)
{
- int ioapic_idx, i, best_guess = -1;
+ int irq, i, best_guess = -1;

apic_printk(APIC_DEBUG,
"querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1007,41 +1007,46 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
"PCI BIOS passed nonexistent PCI bus %d!\n", bus);
return -1;
}
+
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].srcbus;
+ int ioapic_idx, found = 0;
+
+ if (bus != lbus || mp_irqs[i].irqtype != mp_INT ||
+ slot != ((mp_irqs[i].srcbusirq >> 2) & 0x1f))
+ continue;

for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
- mp_irqs[i].dstapic == MP_APIC_ALL)
+ mp_irqs[i].dstapic == MP_APIC_ALL) {
+ found = 1;
break;
+ }
+ if (!found)
+ continue;

- if (!test_bit(lbus, mp_bus_not_pci) &&
- mp_irqs[i].irqtype == mp_INT &&
- (bus == lbus) &&
- (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
- int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
-
- if (!(ioapic_idx || IO_APIC_IRQ(irq)))
- continue;
+ /* Skip ISA IRQs */
+ irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
+ if (ioapic_idx == 0 && !IO_APIC_IRQ(irq))
+ continue;

- if (pin == (mp_irqs[i].srcbusirq & 3)) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- return irq;
- }
- /*
- * Use the first all-but-pin matching entry as a
- * best-guess fuzzy result for broken mptables.
- */
- if (best_guess < 0) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- best_guess = irq;
- }
+ if (pin == (mp_irqs[i].srcbusirq & 3)) {
+ set_io_apic_irq_attr(irq_attr, ioapic_idx,
+ mp_irqs[i].dstirq,
+ irq_trigger(i),
+ irq_polarity(i));
+ return irq;
+ }
+ /*
+ * Use the first all-but-pin matching entry as a
+ * best-guess fuzzy result for broken mptables.
+ */
+ if (best_guess < 0) {
+ set_io_apic_irq_attr(irq_attr, ioapic_idx,
+ mp_irqs[i].dstirq,
+ irq_trigger(i),
+ irq_polarity(i));
+ best_guess = irq;
}
}
return best_guess;
--
1.7.10.4

2014-06-09 08:30:26

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 12/42] x86, ioapic: kill static variable nr_irqs_gsi

Static variable nr_irqs_gsi is used to maintain the lowest dynamic
allocatable IRQ number. It may cause trouble when enabling dynamic
IRQ allocation for IOAPIC, so use arch_dynirq_lower_bound() to
avoid directly accessing nr_irqs_gsi and kill nr_irqs_gsi.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 24 +++++-------------------
1 file changed, 5 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 94a56c233e87..e8cd0bf0ee82 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -118,9 +118,6 @@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* # of MP IRQ source entries */
int mp_irq_entries;

-/* GSI interrupts */
-static int nr_irqs_gsi = NR_IRQS_LEGACY;
-
#ifdef CONFIG_EISA
int mp_bus_id_to_type[MAX_MP_BUSSES];
#endif
@@ -3322,20 +3319,11 @@ static int __init io_apic_get_redir_entries(int ioapic)
return reg_01.bits.entries + 1;
}

-static void __init probe_nr_irqs_gsi(void)
-{
- int nr;
-
- nr = gsi_top + NR_IRQS_LEGACY;
- if (nr > nr_irqs_gsi)
- nr_irqs_gsi = nr;
-
- printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
-}
-
unsigned int arch_dynirq_lower_bound(unsigned int from)
{
- return from < nr_irqs_gsi ? nr_irqs_gsi : from;
+ unsigned int min = gsi_top + NR_IRQS_LEGACY;
+
+ return from < min ? min : from;
}

int __init arch_probe_nr_irqs(void)
@@ -3345,12 +3333,12 @@ int __init arch_probe_nr_irqs(void)
if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
nr_irqs = NR_VECTORS * nr_cpu_ids;

- nr = nr_irqs_gsi + 8 * nr_cpu_ids;
+ nr = (gsi_top + NR_IRQS_LEGACY) + 8 * nr_cpu_ids;
#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
/*
* for MSI and HT dyn irq
*/
- nr += nr_irqs_gsi * 16;
+ nr += (gsi_top + NR_IRQS_LEGACY) * 16;
#endif
if (nr < nr_irqs)
nr_irqs = nr;
@@ -3623,8 +3611,6 @@ fake_ioapic_page:
ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
ioapic_res++;
}
-
- probe_nr_irqs_gsi();
}

void __init ioapic_insert_resources(void)
--
1.7.10.4

2014-06-09 08:18:46

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 09/42] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ

A default identity mapping between GSI and IRQ is built for legacy IRQs.
So when overriding the default identity mapping for legacy IRQs,
we should also invalidate isa_irq_to_gsi[gsi] when setting
isa_irq_to_gsi[irq] = gsi. Otherwise there may be two entries with the
same GSI in the isa_irq_to_gsi array, and acpi_isa_irq_to_gsi() may give
wrong result.

Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index f201579cd0df..d6493863bd4b 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -366,6 +366,13 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,

mp_save_irq(&mp_irq);

+ /*
+ * Reset default identity mapping if gsi is also an legacy IRQ,
+ * otherwise there will be more than one entry with the same GSI
+ * and acpi_isa_irq_to_gsi() may give wrong result.
+ */
+ if (gsi < NR_IRQS_LEGACY && isa_irq_to_gsi[gsi] == gsi)
+ isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
isa_irq_to_gsi[bus_irq] = gsi;
}

@@ -621,7 +628,8 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq < NR_IRQS_LEGACY) {
+ if (isa_irq < NR_IRQS_LEGACY &&
+ isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
*gsi = isa_irq_to_gsi[isa_irq];
return 0;
}
--
1.7.10.4

2014-06-09 08:31:45

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 05/42] x86, PCI, ACPI: use kmalloc_node() to optimize for performance

Use kmalloc_node() instead of kmalloc() when possible to optimize
for performance on NUMA platforms.

Acked-by: Bjorn Helgaas <[email protected]>
Acked-by: David Rientjes <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/pci/acpi.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 01edac6c5e18..91bef49df228 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -448,7 +448,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
return;

size = sizeof(*info->res) * info->res_num;
- info->res = kzalloc(size, GFP_KERNEL);
+ info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
if (!info->res) {
info->res_num = 0;
return;
@@ -456,7 +456,7 @@ static void probe_pci_root_info(struct pci_root_info *info,

size = sizeof(*info->res_offset) * info->res_num;
info->res_num = 0;
- info->res_offset = kzalloc(size, GFP_KERNEL);
+ info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
if (!info->res_offset) {
kfree(info->res);
info->res = NULL;
@@ -495,7 +495,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
if (node != NUMA_NO_NODE && !node_online(node))
node = NUMA_NO_NODE;

- info = kzalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
if (!info) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
--
1.7.10.4

2014-06-09 14:41:18

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [Patch V4 11/42] x86, ioapic: kill unused global variable timer_through_8259

On Mon, 9 Jun 2014, Jiang Liu wrote:

> index d4aba16e6bbf..94a56c233e87 100644
> --- a/arch/x86/kernel/apic/io_apic.c
> +++ b/arch/x86/kernel/apic/io_apic.c
> @@ -2638,8 +2638,6 @@ static int __init disable_timer_pin_setup(char *arg)
> }
> early_param("disable_timer_pin_1", disable_timer_pin_setup);
>
> -int timer_through_8259 __initdata;
> -
> /*
> * This code may look a bit paranoid, but it's supposed to cooperate with
> * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
> @@ -2744,7 +2742,6 @@ static inline void __init check_timer(void)
> legacy_pic->unmask(0);
> if (timer_irq_works()) {
> apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
> - timer_through_8259 = 1;
> goto out;
> }
> /*

So how does the new NMI watchdog handle systems that use this '8259A
Virtual Wire' mode, pretty common on pre-P6 computers?

Maciej

2014-06-09 23:19:48

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [Patch V4 08/42] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()

On Mon, 9 Jun 2014, Jiang Liu wrote:

> Function mp_register_gsi() may return invalid GSI if error happens,
> so enhance acpi_register_gsi() to handle possible error cases.

Can you please explain how that happens? I think I know it, but it'd
be nice if it would be documented.

> Signed-off-by: Jiang Liu <[email protected]>
> ---
> arch/x86/kernel/acpi/boot.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
> index 392360c607dc..f201579cd0df 100644
> --- a/arch/x86/kernel/acpi/boot.c
> +++ b/arch/x86/kernel/acpi/boot.c
> @@ -97,6 +97,8 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
> };
>
> +#define ACPI_INVALID_GSI INT_MIN
> +
> static unsigned int gsi_to_irq(unsigned int gsi)
> {
> unsigned int irq = gsi + NR_IRQS_LEGACY;
> @@ -441,7 +443,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
> polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
> ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
> if (ret < 0)
> - gsi = INT_MIN;
> + gsi = ACPI_INVALID_GSI;
>
> return gsi;
> }
> @@ -666,13 +668,13 @@ int (*acpi_suspend_lowlevel)(void);
> */
> int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
> {
> - unsigned int irq;
> unsigned int plat_gsi = gsi;

The assignemend of gsi to plat_gsi is pointless

> plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);

__acpi_register_gsi is a function pointer, so

plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);

is completely correct and way simpler to read.

> - irq = gsi_to_irq(plat_gsi);
> + if (plat_gsi != ACPI_INVALID_GSI)
> + return gsi_to_irq(plat_gsi);
>
> - return irq;
> + return -1;
> }
> EXPORT_SYMBOL_GPL(acpi_register_gsi);

No need to repost the whole series. Just reply with a new version to
this.

Thanks,

tglx

2014-06-09 23:22:47

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [Patch V4 12/42] x86, ioapic: kill static variable nr_irqs_gsi

On Mon, 9 Jun 2014, Jiang Liu wrote:
> unsigned int arch_dynirq_lower_bound(unsigned int from)
> {
> - return from < nr_irqs_gsi ? nr_irqs_gsi : from;
> + unsigned int min = gsi_top + NR_IRQS_LEGACY;

Why is this gsi_top + NR_IRQ_LEGACY? The legacy interrupts are part of
the gsi space, aren't they?

Thanks,

tglx

2014-06-09 23:46:14

by Yinghai Lu

[permalink] [raw]
Subject: Re: [Patch V4 01/42] x86, irq: update high address field when updating affinity for MSI IRQ

On Mon, Jun 9, 2014 at 1:19 AM, Jiang Liu <[email protected]> wrote:
> If x2apic is enabled, the MSI high address field should also be aslo
> updated when setting affinity for MSI IRQ, otherwise the MSI IRQ may
> target wrong APIC IDs.

Do you have any test case to reveal the problem?

>
> Signed-off-by: Jiang Liu <[email protected]>
> Cc: [email protected]
> ---
> arch/x86/kernel/apic/io_apic.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> index 9d0a9795a0f8..2de992501a1b 100644
> --- a/arch/x86/kernel/apic/io_apic.c
> +++ b/arch/x86/kernel/apic/io_apic.c
> @@ -3007,6 +3007,10 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
>
> __get_cached_msi_msg(data->msi_desc, &msg);
>
> + msg.address_hi = MSI_ADDR_BASE_HI;
> + if (x2apic_enabled())
> + msg.address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
> +
> msg.data &= ~MSI_DATA_VECTOR_MASK;
> msg.data |= MSI_DATA_VECTOR(cfg->vector);
> msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;

No. This change is not needed.

When x2apic is used, and apicid > 255, irq remapping is used.

msi_chip.irq_set_affinity will be changed from msi_set_affinity to
x86_io_apic_ops.set_affinity (aka intel_setup_ioapic_entry), via
irq_remap_modify_chip_defaults().

Thanks

Yinghai

2014-06-10 00:34:27

by David Rientjes

[permalink] [raw]
Subject: Re: [Patch V4 01/42] x86, irq: update high address field when updating affinity for MSI IRQ

On Mon, 9 Jun 2014, Jiang Liu wrote:

> If x2apic is enabled, the MSI high address field should also be aslo
> updated when setting affinity for MSI IRQ, otherwise the MSI IRQ may
> target wrong APIC IDs.
>
> Signed-off-by: Jiang Liu <[email protected]>
> Cc: [email protected]

Acked-by: David Rientjes <[email protected]>

2014-06-10 02:55:09

by Jiang Liu

[permalink] [raw]
Subject: Re: [Patch V4 01/42] x86, irq: update high address field when updating affinity for MSI IRQ



On 2014/6/10 7:46, Yinghai Lu wrote:
> On Mon, Jun 9, 2014 at 1:19 AM, Jiang Liu <[email protected]> wrote:
>> If x2apic is enabled, the MSI high address field should also be aslo
>> updated when setting affinity for MSI IRQ, otherwise the MSI IRQ may
>> target wrong APIC IDs.
>
> Do you have any test case to reveal the problem?
Just by code inspection.

>
>>
>> Signed-off-by: Jiang Liu <[email protected]>
>> Cc: [email protected]
>> ---
>> arch/x86/kernel/apic/io_apic.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
>> index 9d0a9795a0f8..2de992501a1b 100644
>> --- a/arch/x86/kernel/apic/io_apic.c
>> +++ b/arch/x86/kernel/apic/io_apic.c
>> @@ -3007,6 +3007,10 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
>>
>> __get_cached_msi_msg(data->msi_desc, &msg);
>>
>> + msg.address_hi = MSI_ADDR_BASE_HI;
>> + if (x2apic_enabled())
>> + msg.address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
>> +
>> msg.data &= ~MSI_DATA_VECTOR_MASK;
>> msg.data |= MSI_DATA_VECTOR(cfg->vector);
>> msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
>
> No. This change is not needed.
>
> When x2apic is used, and apicid > 255, irq remapping is used.
>
> msi_chip.irq_set_affinity will be changed from msi_set_affinity to
> x86_io_apic_ops.set_affinity (aka intel_setup_ioapic_entry), via
> irq_remap_modify_chip_defaults().
Thanks for explanation, will drop this patch.
Gerry
>
> Thanks
>
> Yinghai
>

2014-06-10 03:21:07

by Jiang Liu

[permalink] [raw]
Subject: Re: [Patch V4 11/42] x86, ioapic: kill unused global variable timer_through_8259



On 2014/6/9 22:41, Maciej W. Rozycki wrote:
> On Mon, 9 Jun 2014, Jiang Liu wrote:
>
>> index d4aba16e6bbf..94a56c233e87 100644
>> --- a/arch/x86/kernel/apic/io_apic.c
>> +++ b/arch/x86/kernel/apic/io_apic.c
>> @@ -2638,8 +2638,6 @@ static int __init disable_timer_pin_setup(char *arg)
>> }
>> early_param("disable_timer_pin_1", disable_timer_pin_setup);
>>
>> -int timer_through_8259 __initdata;
>> -
>> /*
>> * This code may look a bit paranoid, but it's supposed to cooperate with
>> * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
>> @@ -2744,7 +2742,6 @@ static inline void __init check_timer(void)
>> legacy_pic->unmask(0);
>> if (timer_irq_works()) {
>> apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
>> - timer_through_8259 = 1;
>> goto out;
>> }
>> /*
>
> So how does the new NMI watchdog handle systems that use this '8259A
> Virtual Wire' mode, pretty common on pre-P6 computers?
Hi Maciej,
We just kill the useless variable "timer_through_8259", 8259 virtual
wire mode is still supported.
Thanks!
Gerry

>
> Maciej
>

2014-06-10 05:31:41

by Jiang Liu

[permalink] [raw]
Subject: Re: [Patch V4 12/42] x86, ioapic: kill static variable nr_irqs_gsi

Hi Thomas,
This piece of code is inherited from current IOAPIC driver
and I think it's a workaround for some weird platforms.
For normal platforms with both 8259A and IOAPIC controllers,
legacy ISA IRQs should be connected to both 8259A and IOAPIC pins
(ignore timer and cascade IRQs for simplicity). According to comments
in current kernel, there are some platforms on which:
1) some ISA IRQs are only connected to 8259A controllers.
2) the corresponding IOAPIC pins are connected to some non-ISA IRQs.
For such platforms, IRQ0-15 are used for ISA IRQs and another
16 IRQs just above gsi_top are reserved for IOAPIC pins 0-15 which
are connected to non-ISA IRQs.
I have no real experience with such a platform, but just
guessing possible cases according to kernel comments and "Multiple
Processor Specification". Please look at these two pictures for quick
reference.
http://www.manualslib.com/manual/77733/Intel-Multiprocessor.html?page=31#manual
http://www.manualslib.com/manual/77733/Intel-Multiprocessor.html?page=63#manual

Thanks!
Gerry

On 2014/6/10 7:22, Thomas Gleixner wrote:
> On Mon, 9 Jun 2014, Jiang Liu wrote:
>> unsigned int arch_dynirq_lower_bound(unsigned int from)
>> {
>> - return from < nr_irqs_gsi ? nr_irqs_gsi : from;
>> + unsigned int min = gsi_top + NR_IRQS_LEGACY;
>
> Why is this gsi_top + NR_IRQ_LEGACY? The legacy interrupts are part of
> the gsi space, aren't they?
>
> Thanks,
>
> tglx
>

2014-06-10 05:49:52

by Jiang Liu

[permalink] [raw]
Subject: Re: [Patch V4 08/42] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()



On 2014/6/10 7:19, Thomas Gleixner wrote:
> On Mon, 9 Jun 2014, Jiang Liu wrote:
>
>> Function mp_register_gsi() may return invalid GSI if error happens,
>> so enhance acpi_register_gsi() to handle possible error cases.
>
> Can you please explain how that happens? I think I know it, but it'd
> be nice if it would be documented.
Sure.

>
>> Signed-off-by: Jiang Liu <[email protected]>
>> ---
>> arch/x86/kernel/acpi/boot.c | 10 ++++++----
>> 1 file changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
>> index 392360c607dc..f201579cd0df 100644
>> --- a/arch/x86/kernel/acpi/boot.c
>> +++ b/arch/x86/kernel/acpi/boot.c
>> @@ -97,6 +97,8 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
>> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
>> };
>>
>> +#define ACPI_INVALID_GSI INT_MIN
>> +
>> static unsigned int gsi_to_irq(unsigned int gsi)
>> {
>> unsigned int irq = gsi + NR_IRQS_LEGACY;
>> @@ -441,7 +443,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
>> polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
>> ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
>> if (ret < 0)
>> - gsi = INT_MIN;
>> + gsi = ACPI_INVALID_GSI;
>>
>> return gsi;
>> }
>> @@ -666,13 +668,13 @@ int (*acpi_suspend_lowlevel)(void);
>> */
>> int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
>> {
>> - unsigned int irq;
>> unsigned int plat_gsi = gsi;
>
> The assignemend of gsi to plat_gsi is pointless
This was done in patch 21. And eventually function acpi_register_gsi()
will be simplified as below by patch 21 and 22.
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int
polarity)
{
return (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
}

I will rework and resend patch 8, 21 and 22.
>
>> plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
>
> __acpi_register_gsi is a function pointer, so
>
> plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);
>
> is completely correct and way simpler to read.
Thanks, will change to the simpler way.

>
>> - irq = gsi_to_irq(plat_gsi);
>> + if (plat_gsi != ACPI_INVALID_GSI)
>> + return gsi_to_irq(plat_gsi);
>>
>> - return irq;
>> + return -1;
>> }
>> EXPORT_SYMBOL_GPL(acpi_register_gsi);
>
> No need to repost the whole series. Just reply with a new version to
> this.
>
> Thanks,
>
> tglx
>

2014-06-10 06:08:16

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 08/42] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()

Function mp_register_gsi() may return error code when failed to look up
or program corresponding IOAPIC pin for GSI, so enhance acpi_register_gsi()
to handle possible error cases.

Signed-off-by: Jiang Liu <[email protected]>
---
Minor changes according to review comments:
1) kill useless assignment to plat_gsi.
2) simplify usage of function pointer
---
arch/x86/kernel/acpi/boot.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 392360c607dc..298f79616f1c 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -97,6 +97,8 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};

+#define ACPI_INVALID_GSI INT_MIN
+
static unsigned int gsi_to_irq(unsigned int gsi)
{
unsigned int irq = gsi + NR_IRQS_LEGACY;
@@ -441,7 +443,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
if (ret < 0)
- gsi = INT_MIN;
+ gsi = ACPI_INVALID_GSI;

return gsi;
}
@@ -666,13 +668,13 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int irq;
- unsigned int plat_gsi = gsi;
+ unsigned int plat_gsi;

- plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
- irq = gsi_to_irq(plat_gsi);
+ plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);
+ if (plat_gsi != ACPI_INVALID_GSI)
+ return gsi_to_irq(plat_gsi);

- return irq;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

--
1.7.10.4

2014-06-10 06:10:31

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 21/42] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number

Currently ACPI and ioapic both implement algorithms to map (ioapic, pin)
to IRQ number. So consolidate the common part into one place, which is
also preparing for irqdomain support.

It introduces mp_map_gsi_to_irq(), which will be used to allocate IRQ
number IOAPIC pins when irqdomain is enabled.

Also rename gsi_to_irq() to map_gsi_to_irq(), later we will introduce
unmap_gsi_to_irq() when enabling IOAPIC hotplug.

Signed-off-by: Jiang Liu <[email protected]>
---
Rebase due to change in patch 8.
---
arch/x86/include/asm/io_apic.h | 2 ++
arch/x86/kernel/acpi/boot.c | 45 +++++++++++++++++++---------------------
arch/x86/kernel/apic/io_apic.c | 27 +++++++++++++-----------
3 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index b775cf3622c3..978e51fdcb59 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -172,6 +172,7 @@ extern u32 gsi_top;
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
+extern int mp_map_gsi_to_irq(u32 gsi);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

@@ -214,6 +215,7 @@ static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
+static inline int mp_map_gsi_to_irq(u32 gsi) { return gsi; }

struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b12976590a72..9965afbd71ca 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -100,27 +100,15 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

#define ACPI_INVALID_GSI INT_MIN

-static unsigned int gsi_to_irq(unsigned int gsi)
+static int map_gsi_to_irq(unsigned int gsi)
{
- unsigned int irq = gsi + nr_legacy_irqs();
- unsigned int i;
+ int i;

- for (i = 0; i < nr_legacy_irqs(); i++) {
- if (isa_irq_to_gsi[i] == gsi) {
+ for (i = 0; i < nr_legacy_irqs(); i++)
+ if (isa_irq_to_gsi[i] == gsi)
return i;
- }
- }
-
- /* Provide an identity mapping of gsi == irq
- * except on truly weird platforms that have
- * non isa irqs in the first 16 gsis.
- */
- if (gsi >= nr_legacy_irqs())
- irq = gsi;
- else
- irq = gsi_top + gsi;

- return irq;
+ return mp_map_gsi_to_irq(gsi);
}

/*
@@ -416,6 +404,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
+ int irq;
int ioapic;
int ioapic_pin;
struct io_apic_irq_attr irq_attr;
@@ -428,6 +417,10 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;

+ irq = map_gsi_to_irq(gsi);
+ if (irq < 0)
+ return ACPI_INVALID_GSI;
+
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
@@ -449,7 +442,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
if (ret < 0)
gsi = ACPI_INVALID_GSI;

@@ -614,16 +607,20 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
outb(new >> 8, 0x4d1);
}

-int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- *irq = gsi_to_irq(gsi);
+ int irq = map_gsi_to_irq(gsi);

+ if (irq >= 0) {
#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
+ if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+ setup_IO_APIC_irq_extra(gsi);
#endif
+ *irqp = irq;
+ return 0;
+ }

- return 0;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

@@ -681,7 +678,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)

plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);
if (plat_gsi != ACPI_INVALID_GSI)
- return gsi_to_irq(plat_gsi);
+ return map_gsi_to_irq(plat_gsi);

return -1;
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 12d12f897107..ed159cd36971 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -959,11 +959,19 @@ static int irq_trigger(int idx)
return trigger;
}

+int mp_map_gsi_to_irq(u32 gsi)
+{
+ /*
+ * 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;
+}
+
static int pin_2_irq(int idx, int apic, int pin)
{
int irq;
int bus = mp_irqs[idx].srcbus;
- struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);

/*
* Debugging check, we are in big trouble if this message pops up!
@@ -971,17 +979,6 @@ static int pin_2_irq(int idx, int apic, int pin)
if (mp_irqs[idx].dstirq != pin)
pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");

- if (test_bit(bus, mp_bus_not_pci)) {
- irq = mp_irqs[idx].srcbusirq;
- } else {
- u32 gsi = gsi_cfg->gsi_base + pin;
-
- if (gsi >= nr_legacy_irqs())
- irq = gsi;
- else
- irq = gsi_top + gsi;
- }
-
#ifdef CONFIG_X86_32
/*
* PCI IRQ command line redirection. Yes, limits are hardcoded.
@@ -996,11 +993,17 @@ static int pin_2_irq(int idx, int apic, int pin)
apic_printk(APIC_VERBOSE, KERN_DEBUG
"using PIRQ%d -> IRQ %d\n",
pin-16, irq);
+ return irq;
}
}
}
#endif

+ if (test_bit(bus, mp_bus_not_pci))
+ irq = mp_irqs[idx].srcbusirq;
+ else
+ irq = mp_map_gsi_to_irq(mp_pin_to_gsi(apic, pin));
+
return irq;
}

--
1.7.10.4

2014-06-10 06:12:04

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 22/42] x86, irq, ACPI: change __acpi_register_gsi to return IRQ number instead of GSI

Currently __acpi_register_gsi is defined to return GSI number and
may be set to acpi_register_gsi_pic(), acpi_register_gsi_ioapic(),
acpi_register_gsi_xen_hvm() and acpi_register_gsi_xen().

Among which, acpi_register_gsi_ioapic() returns GSI number, but
acpi_register_gsi_xen_hvm() and acpi_register_gsi_xen() actually
returns IRQ number instead of GSI. And for acpi_register_gsi_pic(),
GSI number equals to IRQ number.

So change acpi_register_gsi_ioapic() to return IRQ number, it also
simplifies the code.

Signed-off-by: Jiang Liu <[email protected]>
---
Rebase due to change in patch 8.
---
arch/x86/kernel/acpi/boot.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 9965afbd71ca..0cf311c72bce 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -419,7 +419,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,

irq = map_gsi_to_irq(gsi);
if (irq < 0)
- return ACPI_INVALID_GSI;
+ return irq;

ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
@@ -444,12 +444,11 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
if (ret < 0)
- gsi = ACPI_INVALID_GSI;
+ irq = -1;

- return gsi;
+ return irq;
}

-
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
{
@@ -652,11 +651,13 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
int trigger, int polarity)
{
+ int irq = gsi;
+
#ifdef CONFIG_X86_IO_APIC
- gsi = mp_register_gsi(dev, gsi, trigger, polarity);
+ irq = mp_register_gsi(dev, gsi, trigger, polarity);
#endif

- return gsi;
+ return irq;
}

int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
@@ -674,13 +675,7 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int plat_gsi;
-
- plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);
- if (plat_gsi != ACPI_INVALID_GSI)
- return map_gsi_to_irq(plat_gsi);
-
- return -1;
+ return __acpi_register_gsi(dev, gsi, trigger, polarity);
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

--
1.7.10.4

2014-06-10 06:13:21

by Jiang Liu

[permalink] [raw]
Subject: [Patch V4 38/42] x86, irq, ACPI: release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
---
Minor change, simplify usage of function pointer.
---
arch/x86/kernel/acpi/boot.c | 27 +++++++++++++++++++++++++++
drivers/acpi/pci_irq.c | 3 ++-
2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index fd4b6d2e436c..8c28023924bf 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -421,8 +421,24 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
return irq;
}

+static void mp_unregister_gsi(u32 gsi)
+{
+ int irq;
+
+ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ return;
+
+ if (acpi_gbl_FADT.sci_interrupt == gsi)
+ return;
+
+ irq = mp_map_gsi_to_irq(gsi, 0);
+ if (irq > 0)
+ mp_unmap_irq(irq);
+}
+
static struct irq_domain_ops acpi_irqdomain_ops = {
.map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
};

static int __init
@@ -640,8 +656,16 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
return irq;
}

+static void acpi_unregister_gsi_ioapic(u32 gsi)
+{
+#ifdef CONFIG_X86_IO_APIC
+ mp_unregister_gsi(gsi);
+#endif
+}
+
int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
int trigger, int polarity) = acpi_register_gsi_pic;
+void (*__acpi_unregister_gsi)(u32 gsi) = NULL;

#ifdef CONFIG_ACPI_SLEEP
int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel;
@@ -661,6 +685,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);

void acpi_unregister_gsi(u32 gsi)
{
+ if (__acpi_unregister_gsi)
+ __acpi_unregister_gsi(gsi);
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);

@@ -668,6 +694,7 @@ static void __init acpi_set_irq_model_ioapic(void)
{
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
__acpi_register_gsi = acpi_register_gsi_ioapic;
+ __acpi_unregister_gsi = acpi_unregister_gsi_ioapic;
acpi_ioapic = 1;
}

diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 9c62340c2360..6ba463ceccc6 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -498,5 +498,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
*/

dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
- acpi_unregister_gsi(gsi);
+ if (gsi >= 0 && dev->irq > 0)
+ acpi_unregister_gsi(gsi);
}
--
1.7.10.4

2014-06-10 14:18:35

by David Vrabel

[permalink] [raw]
Subject: Re: [Xen-devel] [Patch V4 19/42] x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY

On 09/06/14 09:19, Jiang Liu wrote:
> Some platforms, such as Intel MID and mshypv, do not support legacy
> interrupt controllers. So count legacy IRQs by legacy_pic->nr_legacy_irqs
> instead of hard-coded NR_IRQS_LEGACY.
>
[...]
> --- a/arch/x86/pci/xen.c
> +++ b/arch/x86/pci/xen.c

Xen bits:

Acked-by: David Vrabel <[email protected]>

David

2014-06-10 21:57:42

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [Patch V4 11/42] x86, ioapic: kill unused global variable timer_through_8259

On Tue, 10 Jun 2014, Jiang Liu wrote:

> >> index d4aba16e6bbf..94a56c233e87 100644
> >> --- a/arch/x86/kernel/apic/io_apic.c
> >> +++ b/arch/x86/kernel/apic/io_apic.c
> >> @@ -2638,8 +2638,6 @@ static int __init disable_timer_pin_setup(char *arg)
> >> }
> >> early_param("disable_timer_pin_1", disable_timer_pin_setup);
> >>
> >> -int timer_through_8259 __initdata;
> >> -
> >> /*
> >> * This code may look a bit paranoid, but it's supposed to cooperate with
> >> * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
> >> @@ -2744,7 +2742,6 @@ static inline void __init check_timer(void)
> >> legacy_pic->unmask(0);
> >> if (timer_irq_works()) {
> >> apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
> >> - timer_through_8259 = 1;
> >> goto out;
> >> }
> >> /*
> >
> > So how does the new NMI watchdog handle systems that use this '8259A
> > Virtual Wire' mode, pretty common on pre-P6 computers?
> Hi Maciej,
> We just kill the useless variable "timer_through_8259", 8259 virtual
> wire mode is still supported.

No doubt it is useless, the question is why it is unused. If you tracked
it down, you'd come up with this change of mine:

commit 35542c5ebced864776d90d83d1e255016fd4c084
Author: Maciej W. Rozycki <[email protected]>
Date: Wed May 21 22:10:22 2008 +0100

x86: I/O APIC: clean up the 8259A on a NMI watchdog failure

There is no point in keeping the 8259A enabled if the I/O APIC NMI
watchdog has failed and the 8259A is not used to pass through regular
timer interrupts. This fixes problems with some systems where some logic
gets confused.

Signed-off-by: Maciej W. Rozycki <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>

that introduced that variable. And to answer myself:

commit 072b198a4ad48bd722ec6d203d65422a4698eae7
Author: Don Zickus <[email protected]>
Date: Fri Nov 12 11:22:24 2010 -0500

x86, nmi_watchdog: Remove all stub function calls from old nmi_watchdog

Now that the bulk of the old nmi_watchdog is gone, remove all
the stub variables and hooks associated with it.

This touches lots of files mainly because of how the io_apic
nmi_watchdog was implemented. Now that the io_apic nmi_watchdog
is forever gone, remove all its fingers.

Most of this code was not being exercised by virtue of
nmi_watchdog != NMI_IO_APIC, so there shouldn't be anything to
risky here.

Signed-off-by: Don Zickus <[email protected]>
Cc: [email protected]
Cc: [email protected]
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>

So the I/O APIC watchdog is gone and '8259A Virtual Wire' mode systems are
not handled anymore. Well, I guess it was a useful hack for its days, but
I understand that maintaining that rather hairy code to support a
minuscule set of old SMP systems (P5 or even i486 UP systems virtually
never had an I/O APIC, unless you just didn't populate additional
processor sockets; P5 SMPs were usually only DP though) still in existence
(mine is still all right, thanks, after 17 years; even the original boxed
CPU fans work great :) ) was considered not worth it. Oh well...

In that case though I think we should clean up some stale comment
references to that watchdog in arch/x86/kernel/apic/io_apic.c too. It may
be worthwhile if code was scrutinised at that time too WRT implicit
hardware setup dependencies as indicated by these comments, as these
comments having been left behind clearly indicate that such a step has
never been made.

And for the record, your clean-up logically belongs to this change:

commit 5f2b0ba4d94b3ac23cbc4b7f675d98eb677a760a
Author: Don Zickus <[email protected]>
Date: Fri Nov 12 11:22:23 2010 -0500

x86, nmi_watchdog: Remove the old nmi_watchdog

Now that we have a new nmi_watchdog that is more generic and
sits on top of the perf subsystem, we really do not need the old
nmi_watchdog any more.

In addition, the old nmi_watchdog doesn't really work if you are
using the default clocksource, hpet. The old nmi_watchdog code
relied on local apic interrupts to determine if the cpu is still
alive. With hpet as the clocksource, these interrupts don't
increment any more and the old nmi_watchdog triggers false
postives.

This piece removes the old nmi_watchdog code and stubs out any
variables and functions calls. The stubs are the same ones used
by the new nmi_watchdog code, so it should be well tested.

Signed-off-by: Don Zickus <[email protected]>
Cc: [email protected]
Cc: [email protected]
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>

that removed the lone use of `timer_through_8259'. So it's been lingering
out there for some 3.5 years. Thanks for sorting this out.

Maciej

2014-06-12 10:59:16

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [Patch V4 12/42] x86, ioapic: kill static variable nr_irqs_gsi

On Tue, 10 Jun 2014, Jiang Liu wrote:

> Hi Thomas,
> This piece of code is inherited from current IOAPIC driver
> and I think it's a workaround for some weird platforms.
> For normal platforms with both 8259A and IOAPIC controllers,
> legacy ISA IRQs should be connected to both 8259A and IOAPIC pins
> (ignore timer and cascade IRQs for simplicity). According to comments
> in current kernel, there are some platforms on which:
> 1) some ISA IRQs are only connected to 8259A controllers.
> 2) the corresponding IOAPIC pins are connected to some non-ISA IRQs.
> For such platforms, IRQ0-15 are used for ISA IRQs and another
> 16 IRQs just above gsi_top are reserved for IOAPIC pins 0-15 which
> are connected to non-ISA IRQs.
> I have no real experience with such a platform, but just
> guessing possible cases according to kernel comments and "Multiple
> Processor Specification". Please look at these two pictures for quick
> reference.
> http://www.manualslib.com/manual/77733/Intel-Multiprocessor.html?page=31#manual
> http://www.manualslib.com/manual/77733/Intel-Multiprocessor.html?page=63#manual

Duh. I completely forgot about the 82489 mess.

We probably want a comment somewhere why we have this gsi + legacy
thing.

Thanks,

tglx

2014-06-12 12:40:11

by Jiang Liu

[permalink] [raw]
Subject: Re: [Patch V4 12/42] x86, ioapic: kill static variable nr_irqs_gsi

Hi Thomas,
With all patches applied, we have following code and comments
for this case:
switch (type) {
case IOAPIC_DOMAIN_LEGACY:
/*
* Dynamically allocate IRQ number for non-ISA IRQs in
the first 16
* GSIs on some weird platforms.
*/
if (gsi < nr_legacy_irqs())
irq = irq_create_mapping(domain, pin);
else if (irq_create_strict_mappings(domain, gsi, pin, 1)
== 0)
irq = gsi;
break;


On 2014/6/12 18:58, Thomas Gleixner wrote:
> On Tue, 10 Jun 2014, Jiang Liu wrote:
>
>> Hi Thomas,
>> This piece of code is inherited from current IOAPIC driver
>> and I think it's a workaround for some weird platforms.
>> For normal platforms with both 8259A and IOAPIC controllers,
>> legacy ISA IRQs should be connected to both 8259A and IOAPIC pins
>> (ignore timer and cascade IRQs for simplicity). According to comments
>> in current kernel, there are some platforms on which:
>> 1) some ISA IRQs are only connected to 8259A controllers.
>> 2) the corresponding IOAPIC pins are connected to some non-ISA IRQs.
>> For such platforms, IRQ0-15 are used for ISA IRQs and another
>> 16 IRQs just above gsi_top are reserved for IOAPIC pins 0-15 which
>> are connected to non-ISA IRQs.
>> I have no real experience with such a platform, but just
>> guessing possible cases according to kernel comments and "Multiple
>> Processor Specification". Please look at these two pictures for quick
>> reference.
>> http://www.manualslib.com/manual/77733/Intel-Multiprocessor.html?page=31#manual
>> http://www.manualslib.com/manual/77733/Intel-Multiprocessor.html?page=63#manual
>
> Duh. I completely forgot about the 82489 mess.
>
> We probably want a comment somewhere why we have this gsi + legacy
> thing.
>
> Thanks,
>
> tglx
>

Subject: [tip:irq/core] genirq: Export irq_domain_disassociate() to architecture interrupt drivers

Commit-ID: 43a775916d63d1c822107b39987192ca5ced445c
Gitweb: http://git.kernel.org/tip/43a775916d63d1c822107b39987192ca5ced445c
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:05 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:03:36 +0200

genirq: Export irq_domain_disassociate() to architecture interrupt drivers

Export irq_domain_disassociate() to architecture interrupt drivers,
so it could be used to handle legacy IRQ descriptors on x86.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
include/linux/irqdomain.h | 2 ++
kernel/irq/irqdomain.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index c983ed1..b0f9d16 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -172,6 +172,8 @@ extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
extern void irq_domain_associate_many(struct irq_domain *domain,
unsigned int irq_base,
irq_hw_number_t hwirq_base, int count);
+extern void irq_domain_disassociate(struct irq_domain *domain,
+ unsigned int irq);

extern unsigned int irq_create_mapping(struct irq_domain *host,
irq_hw_number_t hwirq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index eb5e10e..6534ff6 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -231,7 +231,7 @@ void irq_set_default_host(struct irq_domain *domain)
}
EXPORT_SYMBOL_GPL(irq_set_default_host);

-static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
+void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
{
struct irq_data *irq_data = irq_get_irq_data(irq);
irq_hw_number_t hwirq;

2014-06-21 21:08:46

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [Patch V4 00/42] use irqdomain to dynamically allocate IRQ for IOAPIC

Jiang,

On Mon, 9 Jun 2014, Jiang Liu wrote:

> On x86 platforms, IRQ number are statically allocated to IOAPIC pins at boot.
> There are two issues with this design. First it causes trouble to IOAPIC
> hotplug because we need to allocate a block of IRQ numbers for each IOAPIC.
> Second it may waste IRQ nubmers even if some IOAPIC pins are not used because
> IRQ numbers are statically assigned.
>
> This patchset tries to enable dynamic IRQ number allocation for IOAPIC
> by adopting the irqdomain framework, it solves the two issues mentioned
> above. It also simplifies the IOAPIC driver by consolidating ways to
> program IOAPIC pins with the irqdomain map interface.
>
> We will enhance the IOAPIC driver core to support ACPI based IOAPIC hotplug
> once the IOAPIC driver has been converted to irqdomain.

I merged the whole lot. Thanks for doing this and reacting on all the
review comments. Very nice cleanup work!

Thanks,

tglx

Subject: [tip:x86/apic] x86, mpparse: Use pr_lvl() helper utilities to replace printk(KERN_LVL)

Commit-ID: b1bfd5ea451b60a4725907c282dec232c63f68bb
Gitweb: http://git.kernel.org/tip/b1bfd5ea451b60a4725907c282dec232c63f68bb
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:31 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:40 +0200

x86, mpparse: Use pr_lvl() helper utilities to replace printk(KERN_LVL)

Use pr_lvl() helper utilities to replace printk(KERN_LVL) for readability,
no function changes. Also use pr_cont() to avoid multiple newlines in
one printk().

Signed-off-by: Jiang Liu <[email protected]>
Acked-by: David Rientjes <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/mpparse.c | 95 ++++++++++++++++++++++-------------------------
1 file changed, 44 insertions(+), 51 deletions(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index d2b5648..b10e113 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -67,7 +67,7 @@ static void __init MP_processor_info(struct mpc_cpu *m)
boot_cpu_physical_apicid = m->apicid;
}

- printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
+ pr_info("Processor #%d%s\n", m->apicid, bootup_cpu);
generic_processor_info(apicid, m->apicver);
}

@@ -87,9 +87,8 @@ static void __init MP_bus_info(struct mpc_bus *m)

#if MAX_MP_BUSSES < 256
if (m->busid >= MAX_MP_BUSSES) {
- printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
- " is too large, max. supported is %d\n",
- m->busid, str, MAX_MP_BUSSES - 1);
+ pr_warn("MP table busid value (%d) for bustype %s is too large, max. supported is %d\n",
+ m->busid, str, MAX_MP_BUSSES - 1);
return;
}
#endif
@@ -110,7 +109,7 @@ static void __init MP_bus_info(struct mpc_bus *m)
mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
#endif
} else
- printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+ pr_warn("Unknown bustype %s - ignoring\n", str);
}

static void __init MP_ioapic_info(struct mpc_ioapic *m)
@@ -121,8 +120,8 @@ static void __init MP_ioapic_info(struct mpc_ioapic *m)

static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
{
- apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
- " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ apic_printk(APIC_VERBOSE,
+ "Int: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC INT %02x\n",
mp_irq->irqtype, mp_irq->irqflag & 3,
(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
@@ -135,8 +134,8 @@ static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}

static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
{
- apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
- " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+ apic_printk(APIC_VERBOSE,
+ "Lint: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC LINT %02x\n",
m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
m->srcbusirq, m->destapic, m->destapiclint);
}
@@ -148,34 +147,33 @@ static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
{

if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
- printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
+ pr_err("MPTABLE: bad signature [%c%c%c%c]!\n",
mpc->signature[0], mpc->signature[1],
mpc->signature[2], mpc->signature[3]);
return 0;
}
if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
- printk(KERN_ERR "MPTABLE: checksum error!\n");
+ pr_err("MPTABLE: checksum error!\n");
return 0;
}
if (mpc->spec != 0x01 && mpc->spec != 0x04) {
- printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
- mpc->spec);
+ pr_err("MPTABLE: bad table version (%d)!!\n", mpc->spec);
return 0;
}
if (!mpc->lapic) {
- printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+ pr_err("MPTABLE: null local APIC address!\n");
return 0;
}
memcpy(oem, mpc->oem, 8);
oem[8] = 0;
- printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
+ pr_info("MPTABLE: OEM ID: %s\n", oem);

memcpy(str, mpc->productid, 12);
str[12] = 0;

- printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+ pr_info("MPTABLE: Product ID: %s\n", str);

- printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
+ pr_info("MPTABLE: APIC at: 0x%X\n", mpc->lapic);

return 1;
}
@@ -188,8 +186,8 @@ static void skip_entry(unsigned char **ptr, int *count, int size)

static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
{
- printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
- "type %x\n", *mpt);
+ pr_err("Your mptable is wrong, contact your HW vendor!\n");
+ pr_cont("type %x\n", *mpt);
print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
1, mpc, mpc->length, 1);
}
@@ -259,7 +257,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
}

if (!num_processors)
- printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ pr_err("MPTABLE: no processors registered!\n");
return num_processors;
}

@@ -295,16 +293,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
* If it does, we assume it's valid.
*/
if (mpc_default_type == 5) {
- printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
- "falling back to ELCR\n");
+ pr_info("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");

if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
ELCR_trigger(13))
- printk(KERN_ERR "ELCR contains invalid data... "
- "not using ELCR\n");
+ pr_err("ELCR contains invalid data... not using ELCR\n");
else {
- printk(KERN_INFO
- "Using ELCR to identify PCI interrupts\n");
+ pr_info("Using ELCR to identify PCI interrupts\n");
ELCR_fallback = 1;
}
}
@@ -353,7 +348,7 @@ static void __init construct_ioapic_table(int mpc_default_type)
bus.busid = 0;
switch (mpc_default_type) {
default:
- printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+ pr_err("???\nUnknown standard configuration %d\n",
mpc_default_type);
/* fall through */
case 1:
@@ -462,8 +457,8 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
#ifdef CONFIG_X86_LOCAL_APIC
smp_found_config = 0;
#endif
- printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
- "... disabling SMP support. (tell your hw vendor)\n");
+ pr_err("BIOS bug, MP table errors detected!...\n");
+ pr_cont("... disabling SMP support. (tell your hw vendor)\n");
early_iounmap(mpc, size);
return -1;
}
@@ -481,8 +476,7 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
if (!mp_irq_entries) {
struct mpc_bus bus;

- printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
- "using default mptable. (tell your hw vendor)\n");
+ pr_err("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");

bus.type = MP_BUS;
bus.busid = 0;
@@ -516,14 +510,14 @@ void __init default_get_smp_config(unsigned int early)
if (acpi_lapic && acpi_ioapic)
return;

- printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
- mpf->specification);
+ pr_info("Intel MultiProcessor Specification v1.%d\n",
+ mpf->specification);
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
if (mpf->feature2 & (1 << 7)) {
- printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
+ pr_info(" IMCR and PIC compatibility mode.\n");
pic_mode = 1;
} else {
- printk(KERN_INFO " Virtual Wire compatibility mode.\n");
+ pr_info(" Virtual Wire compatibility mode.\n");
pic_mode = 0;
}
#endif
@@ -539,8 +533,7 @@ void __init default_get_smp_config(unsigned int early)
return;
}

- printk(KERN_INFO "Default MP configuration #%d\n",
- mpf->feature1);
+ pr_info("Default MP configuration #%d\n", mpf->feature1);
construct_default_ISA_mptable(mpf->feature1);

} else if (mpf->physptr) {
@@ -550,7 +543,7 @@ void __init default_get_smp_config(unsigned int early)
BUG();

if (!early)
- printk(KERN_INFO "Processors: %d\n", num_processors);
+ pr_info("Processors: %d\n", num_processors);
/*
* Only use the first configuration found.
*/
@@ -583,10 +576,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
#endif
mpf_found = mpf;

- printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
- (unsigned long long) virt_to_phys(mpf),
- (unsigned long long) virt_to_phys(mpf) +
- sizeof(*mpf) - 1, mpf);
+ pr_info("found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
+ (unsigned long long) virt_to_phys(mpf),
+ (unsigned long long) virt_to_phys(mpf) +
+ sizeof(*mpf) - 1, mpf);

mem = virt_to_phys(mpf);
memblock_reserve(mem, sizeof(*mpf));
@@ -735,7 +728,7 @@ static int __init replace_intsrc_all(struct mpc_table *mpc,
int nr_m_spare = 0;
unsigned char *mpt = ((unsigned char *)mpc) + count;

- printk(KERN_INFO "mpc_length %x\n", mpc->length);
+ pr_info("mpc_length %x\n", mpc->length);
while (count < mpc->length) {
switch (*mpt) {
case MP_PROCESSOR:
@@ -862,13 +855,13 @@ static int __init update_mp_table(void)
if (!smp_check_mpc(mpc, oem, str))
return 0;

- printk(KERN_INFO "mpf: %llx\n", (u64)virt_to_phys(mpf));
- printk(KERN_INFO "physptr: %x\n", mpf->physptr);
+ pr_info("mpf: %llx\n", (u64)virt_to_phys(mpf));
+ pr_info("physptr: %x\n", mpf->physptr);

if (mpc_new_phys && mpc->length > mpc_new_length) {
mpc_new_phys = 0;
- printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
- mpc_new_length);
+ pr_info("mpc_new_length is %ld, please use alloc_mptable=8k\n",
+ mpc_new_length);
}

if (!mpc_new_phys) {
@@ -879,10 +872,10 @@ static int __init update_mp_table(void)
mpc->checksum = 0xff;
new = mpf_checksum((unsigned char *)mpc, mpc->length);
if (old == new) {
- printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+ pr_info("mpc is readonly, please try alloc_mptable instead\n");
return 0;
}
- printk(KERN_INFO "use in-position replacing\n");
+ pr_info("use in-position replacing\n");
} else {
mpf->physptr = mpc_new_phys;
mpc_new = phys_to_virt(mpc_new_phys);
@@ -892,7 +885,7 @@ static int __init update_mp_table(void)
if (mpc_new_phys - mpf->physptr) {
struct mpf_intel *mpf_new;
/* steal 16 bytes from [0, 1k) */
- printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+ pr_info("mpf new: %x\n", 0x400 - 16);
mpf_new = phys_to_virt(0x400 - 16);
memcpy(mpf_new, mpf, 16);
mpf = mpf_new;
@@ -900,7 +893,7 @@ static int __init update_mp_table(void)
}
mpf->checksum = 0;
mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
- printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
+ pr_info("physptr new: %x\n", mpf->physptr);
}

/*

Subject: [tip:x86/apic] x86, acpi: Reorganize code to avoid forward declaration in boot.c

Commit-ID: 8d7cdcb9d8f366c0567b66cce0d5ce37d3311aaf
Gitweb: http://git.kernel.org/tip/8d7cdcb9d8f366c0567b66cce0d5ce37d3311aaf
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:33 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:40 +0200

x86, acpi: Reorganize code to avoid forward declaration in boot.c

Reorganize code to avoid forward declaration in boot.c, no function
changes.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 236 ++++++++++++++++++++++----------------------
1 file changed, 116 insertions(+), 120 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b41b470..ceb3b36 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -345,10 +345,123 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
#endif /*CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
-static void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi);
+#define MP_ISA_BUS 0
+
+static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi)
+{
+ int ioapic;
+ int pin;
+ struct mpc_intsrc mp_irq;
+
+ /*
+ * Convert 'gsi' to 'ioapic.pin'.
+ */
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return;
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+
+ /*
+ * TBD: This check is for faulty timer entries, where the override
+ * erroneously sets the trigger to level, resulting in a HUGE
+ * increase of timer interrupts!
+ */
+ if ((bus_irq == 0) && (trigger == 3))
+ trigger = 1;
+
+ mp_irq.type = MP_INTSRC;
+ mp_irq.irqtype = mp_INT;
+ mp_irq.irqflag = (trigger << 2) | polarity;
+ mp_irq.srcbus = MP_ISA_BUS;
+ mp_irq.srcbusirq = bus_irq; /* IRQ */
+ mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
+ mp_irq.dstirq = pin; /* INTIN# */
+
+ mp_save_irq(&mp_irq);
+
+ isa_irq_to_gsi[bus_irq] = gsi;
+}
+
+static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
+{
+#ifdef CONFIG_X86_MPPARSE
+ struct mpc_intsrc mp_irq;
+ struct pci_dev *pdev;
+ unsigned char number;
+ unsigned int devfn;
+ int ioapic;
+ u8 pin;
+
+ if (!acpi_ioapic)
+ return 0;
+ if (!dev || !dev_is_pci(dev))
+ return 0;
+
+ pdev = to_pci_dev(dev);
+ number = pdev->bus->number;
+ devfn = pdev->devfn;
+ pin = pdev->pin;
+ /* print the entry should happen on mptable identically */
+ mp_irq.type = MP_INTSRC;
+ mp_irq.irqtype = mp_INT;
+ mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ mp_irq.srcbus = number;
+ mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ mp_irq.dstapic = mpc_ioapic_id(ioapic);
+ mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+
+ mp_save_irq(&mp_irq);
+#endif
+ return 0;
+}
+
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity);
+ int polarity)
+{
+ int ioapic;
+ int ioapic_pin;
+ struct io_apic_irq_attr irq_attr;
+ int ret;
+
+ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ return gsi;
+
+ /* Don't set up the ACPI SCI because it's already set up */
+ if (acpi_gbl_FADT.sci_interrupt == gsi)
+ return gsi;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0) {
+ printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+ return gsi;
+ }
+
+ ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
+
+ if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
+ printk(KERN_ERR "Invalid reference to IOAPIC pin "
+ "%d-%d\n", mpc_ioapic_id(ioapic),
+ ioapic_pin);
+ return gsi;
+ }
+
+ if (enable_update_mptable)
+ mp_config_acpi_gsi(dev, gsi, trigger, polarity);
+
+ set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
+ trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
+ polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+ ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ if (ret < 0)
+ gsi = INT_MIN;
+
+ return gsi;
+}
+

static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
@@ -905,44 +1018,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
#endif /* CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
-#define MP_ISA_BUS 0
-
-static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi)
-{
- int ioapic;
- int pin;
- struct mpc_intsrc mp_irq;
-
- /*
- * Convert 'gsi' to 'ioapic.pin'.
- */
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0)
- return;
- pin = mp_find_ioapic_pin(ioapic, gsi);
-
- /*
- * TBD: This check is for faulty timer entries, where the override
- * erroneously sets the trigger to level, resulting in a HUGE
- * increase of timer interrupts!
- */
- if ((bus_irq == 0) && (trigger == 3))
- trigger = 1;
-
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger << 2) | polarity;
- mp_irq.srcbus = MP_ISA_BUS;
- mp_irq.srcbusirq = bus_irq; /* IRQ */
- mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
- mp_irq.dstirq = pin; /* INTIN# */
-
- mp_save_irq(&mp_irq);
-
- isa_irq_to_gsi[bus_irq] = gsi;
-}
-
static void __init mp_config_acpi_legacy_irqs(void)
{
int i;
@@ -1009,85 +1084,6 @@ static void __init mp_config_acpi_legacy_irqs(void)
}
}

-static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity)
-{
-#ifdef CONFIG_X86_MPPARSE
- struct mpc_intsrc mp_irq;
- struct pci_dev *pdev;
- unsigned char number;
- unsigned int devfn;
- int ioapic;
- u8 pin;
-
- if (!acpi_ioapic)
- return 0;
- if (!dev || !dev_is_pci(dev))
- return 0;
-
- pdev = to_pci_dev(dev);
- number = pdev->bus->number;
- devfn = pdev->devfn;
- pin = pdev->pin;
- /* print the entry should happen on mptable identically */
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
- (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
- mp_irq.srcbus = number;
- mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
- ioapic = mp_find_ioapic(gsi);
- mp_irq.dstapic = mpc_ioapic_id(ioapic);
- mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
-
- mp_save_irq(&mp_irq);
-#endif
- return 0;
-}
-
-static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity)
-{
- int ioapic;
- int ioapic_pin;
- struct io_apic_irq_attr irq_attr;
- int ret;
-
- if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
- return gsi;
-
- /* Don't set up the ACPI SCI because it's already set up */
- if (acpi_gbl_FADT.sci_interrupt == gsi)
- return gsi;
-
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0) {
- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
- return gsi;
- }
-
- ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-
- if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mpc_ioapic_id(ioapic),
- ioapic_pin);
- return gsi;
- }
-
- if (enable_update_mptable)
- mp_config_acpi_gsi(dev, gsi, trigger, polarity);
-
- set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
- trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
- if (ret < 0)
- gsi = INT_MIN;
-
- return gsi;
-}
-
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error

Subject: [tip:x86/apic] x86, PCI, ACPI: Use kmalloc_node() to optimize for performance

Commit-ID: 965cd0e4a5e5d704934fa6d476b1a4faa0417e1b
Gitweb: http://git.kernel.org/tip/965cd0e4a5e5d704934fa6d476b1a4faa0417e1b
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:34 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:40 +0200

x86, PCI, ACPI: Use kmalloc_node() to optimize for performance

Use kmalloc_node() instead of kmalloc() when possible to optimize
for performance on NUMA platforms.

Signed-off-by: Jiang Liu <[email protected]>
Acked-by: Bjorn Helgaas <[email protected]>
Acked-by: David Rientjes <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/pci/acpi.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 5075371..cfd1b13 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -448,7 +448,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
return;

size = sizeof(*info->res) * info->res_num;
- info->res = kzalloc(size, GFP_KERNEL);
+ info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
if (!info->res) {
info->res_num = 0;
return;
@@ -456,7 +456,7 @@ static void probe_pci_root_info(struct pci_root_info *info,

size = sizeof(*info->res_offset) * info->res_num;
info->res_num = 0;
- info->res_offset = kzalloc(size, GFP_KERNEL);
+ info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
if (!info->res_offset) {
kfree(info->res);
info->res = NULL;
@@ -499,7 +499,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
if (node != NUMA_NO_NODE && !node_online(node))
node = NUMA_NO_NODE;

- info = kzalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
if (!info) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);

Subject: [tip:x86/apic] x86, mpparse: Simplify arch/x86/include/asm/ mpspec.h

Commit-ID: a491cc902ca495365e9cd45154b60d8c702d86da
Gitweb: http://git.kernel.org/tip/a491cc902ca495365e9cd45154b60d8c702d86da
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:32 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:40 +0200

x86, mpparse: Simplify arch/x86/include/asm/mpspec.h

Simplify arch/x86/include/asm/mpspec.h by
1) Change max_physical_apicid to static as it's only used in apic.c.
2) Kill declaration of mpc_default_type, it's never defined.
3) Delete default_acpi_madt_oem_check(), it has already been declared
in apic.h.
4) Make default_acpi_madt_oem_check() depends on CONFIG_X86_LOCAL_APIC
instead of CONFIG_X86_64 to support i386.
5) Change mp_override_legacy_irq(), mp_config_acpi_legacy_irqs() and
mp_register_gsi() as static because they are only used in acpi/boot.c.

Signed-off-by: Jiang Liu <[email protected]>
Acked-by: David Rientjes <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Cc: Seiji Aguchi <[email protected]>
Cc: HATAYAMA Daisuke <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Richard Weinberger <[email protected]>
Cc: Andi Kleen <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/apic.h | 4 ++--
arch/x86/include/asm/io_apic.h | 3 ---
arch/x86/include/asm/mpspec.h | 13 -------------
arch/x86/kernel/acpi/boot.c | 12 +++++++++---
arch/x86/kernel/apic/apic.c | 2 +-
5 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 19b0eba..69ed79a 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -502,8 +502,6 @@ static inline unsigned default_get_apic_id(unsigned long x)
#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469

#ifdef CONFIG_X86_64
-extern int default_acpi_madt_oem_check(char *, char *);
-
extern void apic_send_IPI_self(int vector);

DECLARE_PER_CPU(int, x2apic_extra_bits);
@@ -552,6 +550,8 @@ static inline int default_apic_id_valid(int apicid)
return (apicid < 255);
}

+extern int default_acpi_madt_oem_check(char *, char *);
+
extern void default_setup_apic_routing(void);

extern struct apic apic_noop;
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 90f97b4..9121abb 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -118,9 +118,6 @@ extern int mp_irq_entries;
/* MP IRQ source entries */
extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];

-/* non-0 if default (table-less) MP configuration */
-extern int mpc_default_type;
-
/* Older SiS APIC requires we rewrite the index register */
extern int sis_apic_bug;

diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index f5a6179..7bef40a 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -40,8 +40,6 @@ extern int mp_bus_id_to_type[MAX_MP_BUSSES];
extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);

extern unsigned int boot_cpu_physical_apicid;
-extern unsigned int max_physical_apicid;
-extern int mpc_default_type;
extern unsigned long mp_lapic_addr;

#ifdef CONFIG_X86_LOCAL_APIC
@@ -88,15 +86,6 @@ static inline void early_reserve_e820_mpc_new(void) { }
#endif

int generic_processor_info(int apicid, int version);
-#ifdef CONFIG_ACPI
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
-extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi);
-extern void mp_config_acpi_legacy_irqs(void);
-struct device;
-extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
- int active_high_low);
-#endif /* CONFIG_ACPI */

#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_LOCAL_APIC)

@@ -163,6 +152,4 @@ extern physid_mask_t phys_cpu_present_map;

extern int generic_mps_oem_check(struct mpc_table *, char *, char *);

-extern int default_acpi_madt_oem_check(char *, char *);
-
#endif /* _ASM_X86_MPSPEC_H */
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 86281ff..b41b470 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -345,6 +345,10 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
#endif /*CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
+static void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi);
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity);

static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
@@ -903,7 +907,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
#ifdef CONFIG_X86_IO_APIC
#define MP_ISA_BUS 0

-void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi)
{
int ioapic;
int pin;
@@ -938,7 +943,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
isa_irq_to_gsi[bus_irq] = gsi;
}

-void __init mp_config_acpi_legacy_irqs(void)
+static void __init mp_config_acpi_legacy_irqs(void)
{
int i;
struct mpc_intsrc mp_irq;
@@ -1040,7 +1045,8 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
return 0;
}

-int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
{
int ioapic;
int ioapic_pin;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ad28db7..ca1bd75 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
/*
* The highest APIC ID seen during enumeration.
*/
-unsigned int max_physical_apicid;
+static unsigned int max_physical_apicid;

/*
* Bitmask of physically existing CPUs:

Subject: [tip:x86/apic] x86, acpi, irq: Kill static function irq_to_gsi()

Commit-ID: 032329eebba86350849c027fe3a0b672558893d4
Gitweb: http://git.kernel.org/tip/032329eebba86350849c027fe3a0b672558893d4
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:35 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:40 +0200

x86, acpi, irq: Kill static function irq_to_gsi()

Static function irq_to_gsi() is only called by acpi_isa_irq_to_gsi(),
so kill function irq_to_gsi() and simplify acpi_isa_irq_to_gsi().

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 26 ++++++--------------------
1 file changed, 6 insertions(+), 20 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index ceb3b36..0968276 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -120,22 +120,6 @@ static unsigned int gsi_to_irq(unsigned int gsi)
return irq;
}

-static u32 irq_to_gsi(int irq)
-{
- unsigned int gsi;
-
- if (irq < NR_IRQS_LEGACY)
- gsi = isa_irq_to_gsi[irq];
- else if (irq < gsi_top)
- gsi = irq;
- else if (irq < (gsi_top + NR_IRQS_LEGACY))
- gsi = irq - gsi_top;
- else
- gsi = 0xffffffff;
-
- return gsi;
-}
-
/*
* This is just a simple wrapper around early_ioremap(),
* with sanity checks for phys == 0 and size == 0.
@@ -640,10 +624,12 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq >= 16)
- return -1;
- *gsi = irq_to_gsi(isa_irq);
- return 0;
+ if (isa_irq < NR_IRQS_LEGACY) {
+ *gsi = isa_irq_to_gsi[isa_irq];
+ return 0;
+ }
+
+ return -1;
}

static int acpi_register_gsi_pic(struct device *dev, u32 gsi,

Subject: [tip:x86/apic] x86, ACPI, trivial: Minor improvements to arch/x86 /kernel/acpi/boot.c

Commit-ID: e819813f5cb98030bab38569abffd9354a1c1a82
Gitweb: http://git.kernel.org/tip/e819813f5cb98030bab38569abffd9354a1c1a82
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:36 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:40 +0200

x86, ACPI, trivial: Minor improvements to arch/x86/kernel/acpi/boot.c

1) Remove out-of-date comment
2) Kill unused function acpi_set_irq_model_pic()
3) Use NR_IRQS_LEGACY instead of hard-coded 16
4) Trivial syntax improvements

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Cc: Jiri Kosina <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 50 +++++++++++++++------------------------------
1 file changed, 16 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 0968276..392360c 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -483,11 +483,6 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;

- /*
- * mp_config_acpi_legacy_irqs() already setup IRQs < 16
- * If GSI is < 16, this will update its flags,
- * else it will create a new mp_irqs[] entry.
- */
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);

/*
@@ -686,14 +681,7 @@ void acpi_unregister_gsi(u32 gsi)
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);

-void __init acpi_set_irq_model_pic(void)
-{
- acpi_irq_model = ACPI_IRQ_MODEL_PIC;
- __acpi_register_gsi = acpi_register_gsi_pic;
- acpi_ioapic = 0;
-}
-
-void __init acpi_set_irq_model_ioapic(void)
+static void __init acpi_set_irq_model_ioapic(void)
{
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
__acpi_register_gsi = acpi_register_gsi_ioapic;
@@ -932,9 +920,8 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -959,9 +946,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -989,11 +975,10 @@ static int __init acpi_parse_madt_lapic_entries(void)
return count;
}

- x2count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
- acpi_parse_x2apic_nmi, 0);
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
+ x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
+ acpi_parse_x2apic_nmi, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI,
+ acpi_parse_lapic_nmi, 0);
if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -1022,7 +1007,7 @@ static void __init mp_config_acpi_legacy_irqs(void)
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < NR_IRQS_LEGACY; i++) {
int ioapic, pin;
unsigned int dstapic;
int idx;
@@ -1099,9 +1084,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return -ENODEV;
}

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
- MAX_IO_APICS);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
+ MAX_IO_APICS);
if (!count) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV;
@@ -1110,9 +1094,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return count;
}

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+ acpi_parse_int_src_ovr, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing interrupt source overrides entry\n");
@@ -1131,9 +1114,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
/* Fill in identity legacy mappings where no override */
mp_config_acpi_legacy_irqs();

- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
+ acpi_parse_nmi_src, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */

Subject: [tip:x86/apic] x86, ACPI, irq: Enhance error handling in function acpi_register_gsi()

Commit-ID: 2c0a6894df19515baf9d2bf0076a2b57c8b51efb
Gitweb: http://git.kernel.org/tip/2c0a6894df19515baf9d2bf0076a2b57c8b51efb
Author: Jiang Liu <[email protected]>
AuthorDate: Tue, 10 Jun 2014 14:11:23 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:40 +0200

x86, ACPI, irq: Enhance error handling in function acpi_register_gsi()

Function mp_register_gsi() may return error code when failed to look up
or program corresponding IOAPIC pin for GSI, so enhance acpi_register_gsi()
to handle possible error cases.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 392360c..298f796 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -97,6 +97,8 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};

+#define ACPI_INVALID_GSI INT_MIN
+
static unsigned int gsi_to_irq(unsigned int gsi)
{
unsigned int irq = gsi + NR_IRQS_LEGACY;
@@ -441,7 +443,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
if (ret < 0)
- gsi = INT_MIN;
+ gsi = ACPI_INVALID_GSI;

return gsi;
}
@@ -666,13 +668,13 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int irq;
- unsigned int plat_gsi = gsi;
+ unsigned int plat_gsi;

- plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
- irq = gsi_to_irq(plat_gsi);
+ plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);
+ if (plat_gsi != ACPI_INVALID_GSI)
+ return gsi_to_irq(plat_gsi);

- return irq;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

Subject: [tip:x86/apic] x86, ACPI, irq: Fix possible eror in GSI to IRQ mapping for legacy IRQ

Commit-ID: 2e0ad0e2c13534f1a0e7f63661e666c281e09b66
Gitweb: http://git.kernel.org/tip/2e0ad0e2c13534f1a0e7f63661e666c281e09b66
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:38 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, ACPI, irq: Fix possible eror in GSI to IRQ mapping for legacy IRQ

A default identity mapping between GSI and IRQ is built for legacy IRQs.
So when overriding the default identity mapping for legacy IRQs,
we should also invalidate isa_irq_to_gsi[gsi] when setting
isa_irq_to_gsi[irq] = gsi. Otherwise there may be two entries with the
same GSI in the isa_irq_to_gsi array, and acpi_isa_irq_to_gsi() may give
wrong result.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 298f796..f3bafcd 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -366,6 +366,13 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,

mp_save_irq(&mp_irq);

+ /*
+ * Reset default identity mapping if gsi is also an legacy IRQ,
+ * otherwise there will be more than one entry with the same GSI
+ * and acpi_isa_irq_to_gsi() may give wrong result.
+ */
+ if (gsi < NR_IRQS_LEGACY && isa_irq_to_gsi[gsi] == gsi)
+ isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
isa_irq_to_gsi[bus_irq] = gsi;
}

@@ -621,7 +628,8 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq < NR_IRQS_LEGACY) {
+ if (isa_irq < NR_IRQS_LEGACY &&
+ isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
*gsi = isa_irq_to_gsi[isa_irq];
return 0;
}

Subject: [tip:x86/apic] x86, irq, trivial: Minor improvements of IRQ related code

Commit-ID: 3eb2be5f49fdeac5ea2880aec90008f0a8250029
Gitweb: http://git.kernel.org/tip/3eb2be5f49fdeac5ea2880aec90008f0a8250029
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:39 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, irq, trivial: Minor improvements of IRQ related code

1) Kill unused MAX_HARDIRQS_PER_CPU.
2) Improve function prototype declararions.
3) Simple typo fix, change "gsit" to "gsi".
4) Use macro VECTOR_UNDEFINED instead of hard-coded -1.
5) Kill redundant comments.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Jiri Kosina <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/hardirq.h | 3 ---
arch/x86/include/asm/io_apic.h | 16 +++++++---------
arch/x86/kernel/apic/io_apic.c | 21 +++++----------------
3 files changed, 12 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 230853d..0f5fb6b 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -40,9 +40,6 @@ typedef struct {

DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);

-/* We can have at most NR_VECTORS irqs routed to a cpu at a time */
-#define MAX_HARDIRQS_PER_CPU NR_VECTORS
-
#define __ARCH_IRQ_STAT

#define inc_irq_stat(member) this_cpu_inc(irq_stat.member)
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 9121abb..8dd1e13 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -144,22 +144,20 @@ struct io_apic_irq_attr;
struct irq_cfg;
extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+extern void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_insert_resources(void);

extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
unsigned int, int,
struct io_apic_irq_attr *);
-extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
- unsigned int, int,
- struct io_apic_irq_attr *);
extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg);

extern void native_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id);
extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
-int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
+extern int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+ struct io_apic_irq_attr *attr);

extern int save_ioapic_entries(void);
extern void mask_ioapic_entries(void);
@@ -172,11 +170,11 @@ struct mp_ioapic_gsi{
u32 gsi_base;
u32 gsi_end;
};
-extern struct mp_ioapic_gsi mp_gsi_routing[];
extern u32 gsi_top;
-int mp_find_ioapic(u32 gsi);
-int mp_find_ioapic_pin(int ioapic, u32 gsi);
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+
+extern int mp_find_ioapic(u32 gsi);
+extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
+extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

extern void mp_save_irq(struct mpc_intsrc *m);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 81e08ef..f339042 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1010,7 +1010,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
break;

if (!test_bit(lbus, mp_bus_not_pci) &&
- !mp_irqs[i].irqtype &&
+ mp_irqs[i].irqtype == mp_INT &&
(bus == lbus) &&
(slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
@@ -1359,7 +1359,7 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)

irq = pin_2_irq(idx, ioapic_idx, pin);

- if ((ioapic_idx > 0) && (irq > 16))
+ if ((ioapic_idx > 0) && (irq > NR_IRQS_LEGACY))
continue;

/*
@@ -1388,7 +1388,7 @@ static void __init setup_IO_APIC_irqs(void)
}

/*
- * for the gsit that is not in first ioapic
+ * for the gsi that is not in first ioapic
* but could not use acpi_register_gsi()
* like some special sci in IBM x3330
*/
@@ -2225,7 +2225,7 @@ asmlinkage __visible void smp_irq_move_cleanup_interrupt(void)
apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
goto unlock;
}
- __this_cpu_write(vector_irq[vector], -1);
+ __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
unlock:
raw_spin_unlock(&desc->lock);
}
@@ -2514,17 +2514,6 @@ static inline void init_IO_APIC_traps(void)
struct irq_cfg *cfg;
unsigned int irq;

- /*
- * NOTE! The local APIC isn't very good at handling
- * multiple interrupts at the same interrupt level.
- * As the interrupt level is determined by taking the
- * vector number and shifting that right by 4, we
- * want to spread these out a bit so that they don't
- * all fall in the same interrupt level.
- *
- * Also, we've got to be careful not to trash gate
- * 0x80, because int 0x80 is hm, kind of importantish. ;)
- */
for_each_active_irq(irq) {
cfg = irq_get_chip_data(irq);
if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
@@ -3550,7 +3539,7 @@ void __init setup_ioapic_dest(void)
continue;
irq = pin_2_irq(irq_entry, ioapic, pin);

- if ((ioapic > 0) && (irq > 16))
+ if ((ioapic > 0) && (irq > NR_IRQS_LEGACY))
continue;

idata = irq_get_irq_data(irq);

Subject: [tip:x86/apic] x86, ioapic: Kill unused global variable timer_through_8259

Commit-ID: 4035ed0134b2dc545a0b22e3c052f684786649d4
Gitweb: http://git.kernel.org/tip/4035ed0134b2dc545a0b22e3c052f684786649d4
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:40 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, ioapic: Kill unused global variable timer_through_8259

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/io_apic.h | 4 ----
arch/x86/kernel/apic/io_apic.c | 3 ---
2 files changed, 7 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 8dd1e13..de3d8b0 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -130,9 +130,6 @@ extern int noioapicquirk;
/* -1 if "noapic" boot option passed */
extern int noioapicreroute;

-/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
-extern int timer_through_8259;
-
/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
@@ -212,7 +209,6 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);

#define io_apic_assign_pci_irqs 0
#define setup_ioapic_ids_from_mpc x86_init_noop
-static const int timer_through_8259 = 0;
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index f339042..18ab95b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2638,8 +2638,6 @@ static int __init disable_timer_pin_setup(char *arg)
}
early_param("disable_timer_pin_1", disable_timer_pin_setup);

-int timer_through_8259 __initdata;
-
/*
* This code may look a bit paranoid, but it's supposed to cooperate with
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
@@ -2744,7 +2742,6 @@ static inline void __init check_timer(void)
legacy_pic->unmask(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
- timer_through_8259 = 1;
goto out;
}
/*

Subject: [tip:x86/apic] x86, ioapic: Kill static variable nr_irqs_gsi

Commit-ID: 518b2c63fcdde0723d2719bbe5b14086bdc8ec80
Gitweb: http://git.kernel.org/tip/518b2c63fcdde0723d2719bbe5b14086bdc8ec80
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:41 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, ioapic: Kill static variable nr_irqs_gsi

Static variable nr_irqs_gsi is used to maintain the lowest dynamic
allocatable IRQ number. It may cause trouble when enabling dynamic
IRQ allocation for IOAPIC, so use arch_dynirq_lower_bound() to
avoid directly accessing nr_irqs_gsi and kill nr_irqs_gsi.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 24 +++++-------------------
1 file changed, 5 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 18ab95b..46d09ea 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -118,9 +118,6 @@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* # of MP IRQ source entries */
int mp_irq_entries;

-/* GSI interrupts */
-static int nr_irqs_gsi = NR_IRQS_LEGACY;
-
#ifdef CONFIG_EISA
int mp_bus_id_to_type[MAX_MP_BUSSES];
#endif
@@ -3326,20 +3323,11 @@ static int __init io_apic_get_redir_entries(int ioapic)
return reg_01.bits.entries + 1;
}

-static void __init probe_nr_irqs_gsi(void)
-{
- int nr;
-
- nr = gsi_top + NR_IRQS_LEGACY;
- if (nr > nr_irqs_gsi)
- nr_irqs_gsi = nr;
-
- printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
-}
-
unsigned int arch_dynirq_lower_bound(unsigned int from)
{
- return from < nr_irqs_gsi ? nr_irqs_gsi : from;
+ unsigned int min = gsi_top + NR_IRQS_LEGACY;
+
+ return from < min ? min : from;
}

int __init arch_probe_nr_irqs(void)
@@ -3349,12 +3337,12 @@ int __init arch_probe_nr_irqs(void)
if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
nr_irqs = NR_VECTORS * nr_cpu_ids;

- nr = nr_irqs_gsi + 8 * nr_cpu_ids;
+ nr = (gsi_top + NR_IRQS_LEGACY) + 8 * nr_cpu_ids;
#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
/*
* for MSI and HT dyn irq
*/
- nr += nr_irqs_gsi * 16;
+ nr += (gsi_top + NR_IRQS_LEGACY) * 16;
#endif
if (nr < nr_irqs)
nr_irqs = nr;
@@ -3627,8 +3615,6 @@ fake_ioapic_page:
ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
ioapic_res++;
}
-
- probe_nr_irqs_gsi();
}

void __init ioapic_insert_resources(void)

Subject: [tip:x86/apic] x86, ioapic: Introduce helper utilities to walk ioapics and pins

Commit-ID: f44d16929638a6dc34bdd51e7422e7e3c1d0b904
Gitweb: http://git.kernel.org/tip/f44d16929638a6dc34bdd51e7422e7e3c1d0b904
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:42 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, ioapic: Introduce helper utilities to walk ioapics and pins

Introduce helper utilities for_each_ioapic(), for_each_ioapic_reverse(),
for_each_pin() and for_each_ioapic_pin() to walk ioapics and pins.
They will be rewritten e will rewrite later to support IOAPIC hotplug.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 120 +++++++++++++++++++++--------------------
1 file changed, 62 insertions(+), 58 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 46d09ea..16b0247 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -62,6 +62,16 @@

#define __apicdebuginit(type) static type __init

+#define for_each_ioapic(idx) \
+ for ((idx) = 0; (idx) < nr_ioapics; (idx)++)
+#define for_each_ioapic_reverse(idx) \
+ for ((idx) = nr_ioapics - 1; (idx) >= 0; (idx)--)
+#define for_each_pin(idx, pin) \
+ for ((pin) = 0; (pin) < ioapics[(idx)].nr_registers; (pin)++)
+#define for_each_ioapic_pin(idx, pin) \
+ for_each_ioapic((idx)) \
+ for_each_pin((idx), (pin))
+
#define for_each_irq_pin(entry, head) \
for (entry = head; entry; entry = entry->next)

@@ -191,7 +201,7 @@ int __init arch_early_irq_init(void)
if (!legacy_pic->nr_legacy_irqs)
io_apic_irqs = ~0UL;

- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
ioapics[i].saved_registers =
kzalloc(sizeof(struct IO_APIC_route_entry) *
ioapics[i].nr_registers, GFP_KERNEL);
@@ -624,9 +634,8 @@ static void clear_IO_APIC (void)
{
int apic, pin;

- for (apic = 0; apic < nr_ioapics; apic++)
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
- clear_IO_APIC_pin(apic, pin);
+ for_each_ioapic_pin(apic, pin)
+ clear_IO_APIC_pin(apic, pin);
}

#ifdef CONFIG_X86_32
@@ -675,13 +684,13 @@ int save_ioapic_entries(void)
int apic, pin;
int err = 0;

- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers) {
err = -ENOMEM;
continue;
}

- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+ for_each_pin(apic, pin)
ioapics[apic].saved_registers[pin] =
ioapic_read_entry(apic, pin);
}
@@ -696,11 +705,11 @@ void mask_ioapic_entries(void)
{
int apic, pin;

- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers)
continue;

- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
+ for_each_pin(apic, pin) {
struct IO_APIC_route_entry entry;

entry = ioapics[apic].saved_registers[pin];
@@ -719,11 +728,11 @@ int restore_ioapic_entries(void)
{
int apic, pin;

- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers)
continue;

- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+ for_each_pin(apic, pin)
ioapic_write_entry(apic, pin,
ioapics[apic].saved_registers[pin]);
}
@@ -782,7 +791,7 @@ static int __init find_isa_irq_apic(int irq, int type)
if (i < mp_irq_entries) {
int ioapic_idx;

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic)
return ioapic_idx;
}
@@ -1001,7 +1010,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].srcbus;

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
mp_irqs[i].dstapic == MP_APIC_ALL)
break;
@@ -1224,12 +1233,10 @@ static inline int IO_APIC_irq_trigger(int irq)
{
int apic, idx, pin;

- for (apic = 0; apic < nr_ioapics; apic++) {
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
- idx = find_irq_entry(apic, pin, mp_INT);
- if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
- return irq_trigger(idx);
- }
+ for_each_ioapic_pin(apic, pin) {
+ idx = find_irq_entry(apic, pin, mp_INT);
+ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+ return irq_trigger(idx);
}
/*
* nonexistent IRQs are edge default
@@ -1349,7 +1356,7 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
struct io_apic_irq_attr attr;
unsigned int pin, irq;

- for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) {
+ 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;
@@ -1380,7 +1387,7 @@ static void __init setup_IO_APIC_irqs(void)

apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
__io_apic_setup_irqs(ioapic_idx);
}

@@ -1583,7 +1590,7 @@ __apicdebuginit(void) print_IO_APICs(void)
struct irq_chip *chip;

printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
mpc_ioapic_id(ioapic_idx),
ioapics[ioapic_idx].nr_registers);
@@ -1594,7 +1601,7 @@ __apicdebuginit(void) print_IO_APICs(void)
*/
printk(KERN_INFO "testing the IO APIC.......................\n");

- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
print_IO_APIC(ioapic_idx);

printk(KERN_DEBUG "IRQ to pin mappings:\n");
@@ -1825,26 +1832,22 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
void __init enable_IO_APIC(void)
{
int i8259_apic, i8259_pin;
- int apic;
+ int apic, pin;

if (!legacy_pic->nr_legacy_irqs)
return;

- for(apic = 0; apic < nr_ioapics; apic++) {
- int pin;
+ for_each_ioapic_pin(apic, pin) {
/* See if any of the pins is in ExtINT mode */
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
- struct IO_APIC_route_entry entry;
- entry = ioapic_read_entry(apic, pin);
+ struct IO_APIC_route_entry entry = ioapic_read_entry(apic, pin);

- /* If the interrupt line is enabled and in ExtInt mode
- * I have found the pin where the i8259 is connected.
- */
- if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
- ioapic_i8259.apic = apic;
- ioapic_i8259.pin = pin;
- goto found_i8259;
- }
+ /* If the interrupt line is enabled and in ExtInt mode
+ * I have found the pin where the i8259 is connected.
+ */
+ if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+ ioapic_i8259.apic = apic;
+ ioapic_i8259.pin = pin;
+ goto found_i8259;
}
}
found_i8259:
@@ -1947,7 +1950,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
/*
* Set the IOAPIC ID to the value stored in the MPC table.
*/
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
+ for_each_ioapic(ioapic_idx) {
/* Read the register 0 value */
raw_spin_lock_irqsave(&ioapic_lock, flags);
reg_00.raw = io_apic_read(ioapic_idx, 0);
@@ -2863,7 +2866,7 @@ static void ioapic_resume(void)
{
int ioapic_idx;

- for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--)
+ for_each_ioapic_reverse(ioapic_idx)
resume_ioapic_id(ioapic_idx);

restore_ioapic_entries();
@@ -3457,9 +3460,8 @@ static u8 __init io_apic_unique_id(u8 id)
DECLARE_BITMAP(used, 256);

bitmap_zero(used, 256);
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i)
__set_bit(mpc_ioapic_id(i), used);
- }
if (!test_bit(id, used))
return id;
return find_first_zero_bit(used, 256);
@@ -3517,8 +3519,7 @@ void __init setup_ioapic_dest(void)
if (skip_ioapic_setup == 1)
return;

- for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
- for (pin = 0; pin < ioapics[ioapic].nr_registers; pin++) {
+ for_each_ioapic_pin(ioapic, pin) {
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
@@ -3547,29 +3548,33 @@ void __init setup_ioapic_dest(void)

static struct resource *ioapic_resources;

-static struct resource * __init ioapic_setup_resources(int nr_ioapics)
+static struct resource * __init ioapic_setup_resources(void)
{
unsigned long n;
struct resource *res;
char *mem;
- int i;
+ int i, num = 0;

- if (nr_ioapics <= 0)
+ for_each_ioapic(i)
+ num++;
+ if (num == 0)
return NULL;

n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
- n *= nr_ioapics;
+ n *= num;

mem = alloc_bootmem(n);
res = (void *)mem;

- mem += sizeof(struct resource) * nr_ioapics;
+ mem += sizeof(struct resource) * num;

- for (i = 0; i < nr_ioapics; i++) {
- res[i].name = mem;
- res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ num = 0;
+ for_each_ioapic(i) {
+ res[num].name = mem;
+ res[num].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
mem += IOAPIC_RESOURCE_NAME_SIZE;
+ num++;
}

ioapic_resources = res;
@@ -3583,8 +3588,8 @@ void __init native_io_apic_init_mappings(void)
struct resource *ioapic_res;
int i;

- ioapic_res = ioapic_setup_resources(nr_ioapics);
- for (i = 0; i < nr_ioapics; i++) {
+ ioapic_res = ioapic_setup_resources();
+ for_each_ioapic(i) {
if (smp_found_config) {
ioapic_phys = mpc_ioapic_addr(i);
#ifdef CONFIG_X86_32
@@ -3629,7 +3634,7 @@ void __init ioapic_insert_resources(void)
return;
}

- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
insert_resource(&iomem_resource, r);
r++;
}
@@ -3637,16 +3642,15 @@ void __init ioapic_insert_resources(void)

int mp_find_ioapic(u32 gsi)
{
- int i = 0;
+ int i;

if (nr_ioapics == 0)
return -1;

/* Find the IOAPIC that manages this GSI. */
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(i);
- if ((gsi >= gsi_cfg->gsi_base)
- && (gsi <= gsi_cfg->gsi_end))
+ if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end)
return i;
}

@@ -3658,7 +3662,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
{
struct mp_ioapic_gsi *gsi_cfg;

- if (WARN_ON(ioapic == -1))
+ if (WARN_ON(ioapic < 0))
return -1;

gsi_cfg = mp_ioapic_gsi_routing(ioapic);

Subject: [tip:x86/apic] x86, ioapic: Use irq_cfg() instead of irq_get_chip_data() for better readability

Commit-ID: 32f5ef5d8dd5ac3cc7ac12cdaf33023e2fbd33c1
Gitweb: http://git.kernel.org/tip/32f5ef5d8dd5ac3cc7ac12cdaf33023e2fbd33c1
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:43 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, ioapic: Use irq_cfg() instead of irq_get_chip_data() for better readability

Use defined helper function irq_cfg() instead of irq_get_chip_data() for
better readability.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 16b0247..446a931 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -230,7 +230,7 @@ int __init arch_early_irq_init(void)
return 0;
}

-static struct irq_cfg *irq_cfg(unsigned int irq)
+static inline struct irq_cfg *irq_cfg(unsigned int irq)
{
return irq_get_chip_data(irq);
}
@@ -272,7 +272,7 @@ static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
if (res < 0) {
if (res != -EEXIST)
return NULL;
- cfg = irq_get_chip_data(at);
+ cfg = irq_cfg(at);
if (cfg)
return cfg;
}
@@ -1204,7 +1204,7 @@ void __setup_vector_irq(int cpu)
raw_spin_lock(&vector_lock);
/* Mark the inuse vectors */
for_each_active_irq(irq) {
- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (!cfg)
continue;

@@ -1612,7 +1612,7 @@ __apicdebuginit(void) print_IO_APICs(void)
if (chip != &ioapic_chip)
continue;

- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (!cfg)
continue;
entry = cfg->irq_2_pin;
@@ -2253,7 +2253,7 @@ static void irq_complete_move(struct irq_cfg *cfg)

void irq_force_complete_move(int irq)
{
- struct irq_cfg *cfg = irq_get_chip_data(irq);
+ struct irq_cfg *cfg = irq_cfg(irq);

if (!cfg)
return;
@@ -2515,7 +2515,7 @@ static inline void init_IO_APIC_traps(void)
unsigned int irq;

for_each_active_irq(irq) {
- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
/*
* Hmm.. We don't have an entry for this,
@@ -2648,7 +2648,7 @@ early_param("disable_timer_pin_1", disable_timer_pin_setup);
*/
static inline void __init check_timer(void)
{
- struct irq_cfg *cfg = irq_get_chip_data(0);
+ struct irq_cfg *cfg = irq_cfg(0);
int node = cpu_to_node(0);
int apic1, pin1, apic2, pin2;
unsigned long flags;
@@ -2912,7 +2912,7 @@ int arch_setup_hwirq(unsigned int irq, int node)

void arch_teardown_hwirq(unsigned int irq)
{
- struct irq_cfg *cfg = irq_get_chip_data(irq);
+ struct irq_cfg *cfg = irq_cfg(irq);
unsigned long flags;

free_remapped_irq(irq);
@@ -3039,7 +3039,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
if (!irq_offset)
write_msi_msg(irq, &msg);

- setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+ setup_remapped_irq(irq, irq_cfg(irq), chip);

irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");

@@ -3178,7 +3178,7 @@ int default_setup_hpet_msi(unsigned int irq, unsigned int id)

hpet_msi_write(irq_get_handler_data(irq), &msg);
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
- setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+ setup_remapped_irq(irq, irq_cfg(irq), chip);

irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
return 0;

Subject: [tip:x86/apic] x86: ce4100, irq: Do not set legacy_pic to null_legacy_pic

Commit-ID: 6532ce994c304835f3bfc8479acce9d102cd8b5b
Gitweb: http://git.kernel.org/tip/6532ce994c304835f3bfc8479acce9d102cd8b5b
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:47 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86: ce4100, irq: Do not set legacy_pic to null_legacy_pic

Intel CE4100 platforms has i8259 legacy interrupt controllers, so don't
set legacy_pic to null_legacy_pic in late booting stage because we need
legacy_pic to mask i8259 pins when enabling IOAPIC pins for safety.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/platform/ce4100/ce4100.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 0a54a58..701fd58 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -138,8 +138,6 @@ static void __init sdv_arch_setup(void)
static void sdv_pci_init(void)
{
x86_of_pci_init();
- /* We can't set this earlier, because we need to calibrate the timer */
- legacy_pic = &null_legacy_pic;
}

/*

Subject: [tip:x86/apic] x86, irq: Simplify arch_early_irq_init()

Commit-ID: 4b92b4f754939e4ac6bb53355abbe48a5054b573
Gitweb: http://git.kernel.org/tip/4b92b4f754939e4ac6bb53355abbe48a5054b573
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:49 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86, irq: Simplify arch_early_irq_init()

Simplify function arch_early_irq_init() and kill static array irq_cfgx[].

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 33 +++++++++++----------------------
1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 4208ea9..e25e7e3 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -183,6 +183,7 @@ 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 */
void mp_save_irq(struct mpc_intsrc *m)
@@ -214,14 +215,10 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
}

-
-/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
-
int __init arch_early_irq_init(void)
{
struct irq_cfg *cfg;
- int count, node, i;
+ int i, node = cpu_to_node(0);

if (!nr_legacy_irqs())
io_apic_irqs = ~0UL;
@@ -234,22 +231,14 @@ int __init arch_early_irq_init(void)
pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
}

- cfg = irq_cfgx;
- count = ARRAY_SIZE(irq_cfgx);
- node = cpu_to_node(0);
-
- for (i = 0; i < count; i++) {
- irq_set_chip_data(i, &cfg[i]);
- zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
- zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
- /*
- * For legacy IRQ's, start with assigning irq0 to irq15 to
- * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
- */
- if (i < nr_legacy_irqs()) {
- cfg[i].vector = IRQ0_VECTOR + i;
- cpumask_setall(cfg[i].domain);
- }
+ /*
+ * For legacy IRQ's, start with assigning irq0 to irq15 to
+ * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
+ */
+ for (i = 0; i < nr_legacy_irqs(); i++) {
+ cfg = alloc_irq_and_cfg_at(i, node);
+ cfg->vector = IRQ0_VECTOR + i;
+ cpumask_setall(cfg->domain);
}

return 0;
@@ -3377,7 +3366,7 @@ int __init arch_probe_nr_irqs(void)
if (nr < nr_irqs)
nr_irqs = nr;

- return nr_legacy_irqs();
+ return 0;
}

int io_apic_set_pci_routing(struct device *dev, int irq,

Subject: [tip:x86/apic] x86, ACPI, irq: Consolidate algorithm of mapping ( ioapic, pin) to IRQ number

Commit-ID: 6b9fb7082409cd4a2c7caf43e3c023ad82dad0d4
Gitweb: http://git.kernel.org/tip/6b9fb7082409cd4a2c7caf43e3c023ad82dad0d4
Author: Jiang Liu <[email protected]>
AuthorDate: Tue, 10 Jun 2014 14:13:25 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86, ACPI, irq: Consolidate algorithm of mapping (ioapic, pin) to IRQ number

Currently ACPI and ioapic both implement algorithms to map (ioapic, pin)
to IRQ number. So consolidate the common part into one place, which is
also preparing for irqdomain support.

It introduces mp_map_gsi_to_irq(), which will be used to allocate IRQ
number IOAPIC pins when irqdomain is enabled.

Also rename gsi_to_irq() to map_gsi_to_irq(), later we will introduce
unmap_gsi_to_irq() when enabling IOAPIC hotplug.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/io_apic.h | 2 ++
arch/x86/kernel/acpi/boot.c | 45 ++++++++++++++++++++----------------------
arch/x86/kernel/apic/io_apic.c | 27 ++++++++++++++-----------
3 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index b775cf3..978e51f 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -172,6 +172,7 @@ extern u32 gsi_top;
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
+extern int mp_map_gsi_to_irq(u32 gsi);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

@@ -214,6 +215,7 @@ static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
+static inline int mp_map_gsi_to_irq(u32 gsi) { return gsi; }

struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b129765..9965afb 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -100,27 +100,15 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

#define ACPI_INVALID_GSI INT_MIN

-static unsigned int gsi_to_irq(unsigned int gsi)
+static int map_gsi_to_irq(unsigned int gsi)
{
- unsigned int irq = gsi + nr_legacy_irqs();
- unsigned int i;
+ int i;

- for (i = 0; i < nr_legacy_irqs(); i++) {
- if (isa_irq_to_gsi[i] == gsi) {
+ for (i = 0; i < nr_legacy_irqs(); i++)
+ if (isa_irq_to_gsi[i] == gsi)
return i;
- }
- }
-
- /* Provide an identity mapping of gsi == irq
- * except on truly weird platforms that have
- * non isa irqs in the first 16 gsis.
- */
- if (gsi >= nr_legacy_irqs())
- irq = gsi;
- else
- irq = gsi_top + gsi;

- return irq;
+ return mp_map_gsi_to_irq(gsi);
}

/*
@@ -416,6 +404,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
+ int irq;
int ioapic;
int ioapic_pin;
struct io_apic_irq_attr irq_attr;
@@ -428,6 +417,10 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;

+ irq = map_gsi_to_irq(gsi);
+ if (irq < 0)
+ return ACPI_INVALID_GSI;
+
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
@@ -449,7 +442,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
if (ret < 0)
gsi = ACPI_INVALID_GSI;

@@ -614,16 +607,20 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
outb(new >> 8, 0x4d1);
}

-int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- *irq = gsi_to_irq(gsi);
+ int irq = map_gsi_to_irq(gsi);

+ if (irq >= 0) {
#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
+ if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+ setup_IO_APIC_irq_extra(gsi);
#endif
+ *irqp = irq;
+ return 0;
+ }

- return 0;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

@@ -681,7 +678,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)

plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);
if (plat_gsi != ACPI_INVALID_GSI)
- return gsi_to_irq(plat_gsi);
+ return map_gsi_to_irq(plat_gsi);

return -1;
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e25e7e3..7fd9f1b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -959,11 +959,19 @@ static int irq_trigger(int idx)
return trigger;
}

+int mp_map_gsi_to_irq(u32 gsi)
+{
+ /*
+ * 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;
+}
+
static int pin_2_irq(int idx, int apic, int pin)
{
int irq;
int bus = mp_irqs[idx].srcbus;
- struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);

/*
* Debugging check, we are in big trouble if this message pops up!
@@ -971,17 +979,6 @@ static int pin_2_irq(int idx, int apic, int pin)
if (mp_irqs[idx].dstirq != pin)
pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");

- if (test_bit(bus, mp_bus_not_pci)) {
- irq = mp_irqs[idx].srcbusirq;
- } else {
- u32 gsi = gsi_cfg->gsi_base + pin;
-
- if (gsi >= nr_legacy_irqs())
- irq = gsi;
- else
- irq = gsi_top + gsi;
- }
-
#ifdef CONFIG_X86_32
/*
* PCI IRQ command line redirection. Yes, limits are hardcoded.
@@ -996,11 +993,17 @@ static int pin_2_irq(int idx, int apic, int pin)
apic_printk(APIC_VERBOSE, KERN_DEBUG
"using PIRQ%d -> IRQ %d\n",
pin-16, irq);
+ return irq;
}
}
}
#endif

+ if (test_bit(bus, mp_bus_not_pci))
+ irq = mp_irqs[idx].srcbusirq;
+ else
+ irq = mp_map_gsi_to_irq(mp_pin_to_gsi(apic, pin));
+
return irq;
}

Subject: [tip:x86/apic] x86, irq, ACPI: Change __acpi_register_gsi to return IRQ number instead of GSI

Commit-ID: 84245af7297ced9e8fe837dc0fc4782438771bd2
Gitweb: http://git.kernel.org/tip/84245af7297ced9e8fe837dc0fc4782438771bd2
Author: Jiang Liu <[email protected]>
AuthorDate: Tue, 10 Jun 2014 14:14:47 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86, irq, ACPI: Change __acpi_register_gsi to return IRQ number instead of GSI

Currently __acpi_register_gsi is defined to return GSI number and
may be set to acpi_register_gsi_pic(), acpi_register_gsi_ioapic(),
acpi_register_gsi_xen_hvm() and acpi_register_gsi_xen().

Among which, acpi_register_gsi_ioapic() returns GSI number, but
acpi_register_gsi_xen_hvm() and acpi_register_gsi_xen() actually
returns IRQ number instead of GSI. And for acpi_register_gsi_pic(),
GSI number equals to IRQ number.

So change acpi_register_gsi_ioapic() to return IRQ number, it also
simplifies the code.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 9965afb..0cf311c 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -419,7 +419,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,

irq = map_gsi_to_irq(gsi);
if (irq < 0)
- return ACPI_INVALID_GSI;
+ return irq;

ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
@@ -444,12 +444,11 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
if (ret < 0)
- gsi = ACPI_INVALID_GSI;
+ irq = -1;

- return gsi;
+ return irq;
}

-
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
{
@@ -652,11 +651,13 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
int trigger, int polarity)
{
+ int irq = gsi;
+
#ifdef CONFIG_X86_IO_APIC
- gsi = mp_register_gsi(dev, gsi, trigger, polarity);
+ irq = mp_register_gsi(dev, gsi, trigger, polarity);
#endif

- return gsi;
+ return irq;
}

int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
@@ -674,13 +675,7 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int plat_gsi;
-
- plat_gsi = __acpi_register_gsi(dev, gsi, trigger, polarity);
- if (plat_gsi != ACPI_INVALID_GSI)
- return map_gsi_to_irq(plat_gsi);
-
- return -1;
+ return __acpi_register_gsi(dev, gsi, trigger, polarity);
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

Subject: [tip:x86/apic] x86, irq: Introduce mechanisms to support dynamically allocate IRQ for IOAPIC

Commit-ID: d7f3d4781852f5160b939f526afbc21a813a0206
Gitweb: http://git.kernel.org/tip/d7f3d4781852f5160b939f526afbc21a813a0206
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:52 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86, irq: Introduce mechanisms to support dynamically allocate IRQ for IOAPIC

Currently x86 support identity mapping between GSI(IOAPIC pin) and IRQ
number, so continous IRQs at low end are statically allocated to IOAPICs
at boot time. This design causes trouble to support IOAPIC hotplug.

This patch implements basic mechanism to dynamically allocate IRQ on
demand for IOAPIC pins by using irqdomain framework.

It first adds several fields into struct ioapic to support irqdomain.
Then it implements an algorithm to dynamically allocate IRQ number
for IOAPIC pins on demand.

Currently it supports three types of irqdomain:
1) LEGACY: used to support IOAPIC hosting legacy IRQs and building
identity mapping for legacy IRQs. A speical case, we dynamically
allocate IRQ number for IOAPIC pin which has GSI number below
nr_legacy_irqs() but isn't legacy IRQ. This is for backward
compatibility and avoid regression.
2) STRICT: build identity mapping between GSI and IRQ nubmer.
3) DYNAMIC: dynamically allocate IRQ number for IOAPIC pin on demand.

Legacy(ISA) IRQs is not managed by irqdomain because there may be
multiple pins sharing the same IRQ number and current irqdomain only
supports 1:1 mapping between pins and IRQ.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/io_apic.h | 21 +++++-
arch/x86/kernel/acpi/boot.c | 8 +--
arch/x86/kernel/apic/io_apic.c | 158 ++++++++++++++++++++++++++++++++---------
4 files changed, 147 insertions(+), 41 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9df5c45..147a7b7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -836,6 +836,7 @@ config X86_IO_APIC
def_bool y
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+ select IRQ_DOMAIN

config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
bool "Reroute for broken boot IRQs"
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 978e51f..64c6e34 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -98,6 +98,8 @@ struct IR_IO_APIC_route_entry {
#define IOAPIC_AUTO -1
#define IOAPIC_EDGE 0
#define IOAPIC_LEVEL 1
+#define IOAPIC_MAP_ALLOC 0x1
+#define IOAPIC_MAP_CHECK 0x2

#ifdef CONFIG_X86_IO_APIC

@@ -163,6 +165,21 @@ extern int restore_ioapic_entries(void);
extern void setup_ioapic_ids_from_mpc(void);
extern void setup_ioapic_ids_from_mpc_nocheck(void);

+enum ioapic_domain_type {
+ IOAPIC_DOMAIN_INVALID,
+ IOAPIC_DOMAIN_LEGACY,
+ IOAPIC_DOMAIN_STRICT,
+ IOAPIC_DOMAIN_DYNAMIC,
+};
+
+struct device_node;
+struct irq_domain_ops;
+struct ioapic_domain_cfg {
+ enum ioapic_domain_type type;
+ const struct irq_domain_ops *ops;
+ struct device_node *dev;
+};
+
struct mp_ioapic_gsi{
u32 gsi_base;
u32 gsi_end;
@@ -172,7 +189,7 @@ extern u32 gsi_top;
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
-extern int mp_map_gsi_to_irq(u32 gsi);
+extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

@@ -215,7 +232,7 @@ static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
-static inline int mp_map_gsi_to_irq(u32 gsi) { return gsi; }
+static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }

struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 0cf311c..d6635ba 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -100,7 +100,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

#define ACPI_INVALID_GSI INT_MIN

-static int map_gsi_to_irq(unsigned int gsi)
+static int map_gsi_to_irq(unsigned int gsi, unsigned int flags)
{
int i;

@@ -108,7 +108,7 @@ static int map_gsi_to_irq(unsigned int gsi)
if (isa_irq_to_gsi[i] == gsi)
return i;

- return mp_map_gsi_to_irq(gsi);
+ return mp_map_gsi_to_irq(gsi, flags);
}

/*
@@ -417,7 +417,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;

- irq = map_gsi_to_irq(gsi);
+ irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
if (irq < 0)
return irq;

@@ -608,7 +608,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)

int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- int irq = map_gsi_to_irq(gsi);
+ int irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);

if (irq >= 0) {
#ifdef CONFIG_X86_IO_APIC
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 7fd9f1b..51ce80004 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -31,6 +31,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
#include <linux/msi.h>
#include <linux/htirq.h>
#include <linux/freezer.h>
@@ -83,6 +84,7 @@ int sis_apic_bug = -1;

static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
+static DEFINE_MUTEX(ioapic_mutex);

static struct ioapic {
/*
@@ -97,6 +99,8 @@ static struct ioapic {
struct mpc_ioapic mp_config;
/* IO APIC gsi routing info */
struct mp_ioapic_gsi gsi_config;
+ struct ioapic_domain_cfg irqdomain_cfg;
+ struct irq_domain *irqdomain;
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];

@@ -142,6 +146,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
}

+static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
+{
+ return ioapics[ioapic].irqdomain;
+}
+
int nr_ioapics;

/* The one past the highest gsi number used */
@@ -959,19 +968,79 @@ static int irq_trigger(int idx)
return trigger;
}

-int mp_map_gsi_to_irq(u32 gsi)
+static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
{
+ int irq = -1;
+ int ioapic = (int)(long)domain->host_data;
+ int type = ioapics[ioapic].irqdomain_cfg.type;
+
+ switch (type) {
+ case IOAPIC_DOMAIN_LEGACY:
+ /*
+ * Dynamically allocate IRQ number for non-ISA IRQs in the first 16
+ * GSIs on some weird platforms.
+ */
+ if (gsi < nr_legacy_irqs())
+ irq = irq_create_mapping(domain, pin);
+ else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+ irq = gsi;
+ break;
+ case IOAPIC_DOMAIN_STRICT:
+ if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+ irq = gsi;
+ break;
+ case IOAPIC_DOMAIN_DYNAMIC:
+ irq = irq_create_mapping(domain, pin);
+ break;
+ default:
+ WARN(1, "ioapic: unknown irqdomain type %d\n", type);
+ break;
+ }
+
+ return irq > 0 ? irq : -1;
+}
+
+static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
+ unsigned int flags)
+{
+ int irq;
+ struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+
/*
- * Provide an identity mapping of gsi == irq except on truly weird
- * platforms that have non isa irqs in the first 16 gsis.
+ * Don't use irqdomain to manage ISA IRQs because there may be
+ * multiple IOAPIC pins sharing the same ISA IRQ number and
+ * irqdomain only supports 1:1 mapping between IOAPIC pin and
+ * IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are used
+ * for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H).
+ * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are
+ * available, and some BIOSes may use MP Interrupt Source records
+ * to override IRQ numbers for PIRQs instead of reprogramming
+ * the interrupt routing logic. Thus there may be multiple pins
+ * sharing the same legacy IRQ number when ACPI is disabled.
*/
- return gsi >= nr_legacy_irqs() ? gsi : gsi_top + gsi;
+ 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;
+ }
+
+ 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);
+ mutex_unlock(&ioapic_mutex);
+
+ return irq > 0 ? irq : -1;
}

-static int pin_2_irq(int idx, int apic, int pin)
+static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
{
- int irq;
- int bus = mp_irqs[idx].srcbus;
+ u32 gsi = mp_pin_to_gsi(ioapic, pin);

/*
* Debugging check, we are in big trouble if this message pops up!
@@ -989,7 +1058,7 @@ static int pin_2_irq(int idx, int apic, int pin)
apic_printk(APIC_VERBOSE, KERN_DEBUG
"disabling PIRQ%d\n", pin-16);
} else {
- irq = pirq_entries[pin-16];
+ int irq = pirq_entries[pin-16];
apic_printk(APIC_VERBOSE, KERN_DEBUG
"using PIRQ%d -> IRQ %d\n",
pin-16, irq);
@@ -999,12 +1068,23 @@ static int pin_2_irq(int idx, int apic, int pin)
}
#endif

- if (test_bit(bus, mp_bus_not_pci))
- irq = mp_irqs[idx].srcbusirq;
- else
- irq = mp_map_gsi_to_irq(mp_pin_to_gsi(apic, pin));
+ return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+}

- return irq;
+int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
+{
+ int ioapic, pin, idx;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return -1;
+
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ idx = find_irq_entry(ioapic, pin, mp_INT);
+ if ((flags & IOAPIC_MAP_CHECK) && idx < 0)
+ return -1;
+
+ return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
}

/*
@@ -1014,7 +1094,7 @@ static int pin_2_irq(int idx, int apic, int pin)
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
struct io_apic_irq_attr *irq_attr)
{
- int irq, i, best_guess = -1;
+ int irq, i, best_ioapic = -1, best_idx = -1;

apic_printk(APIC_DEBUG,
"querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1043,30 +1123,37 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
continue;

/* Skip ISA IRQs */
- irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
- if (ioapic_idx == 0 && !IO_APIC_IRQ(irq))
+ irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq, 0);
+ if (irq > 0 && !IO_APIC_IRQ(irq))
continue;

if (pin == (mp_irqs[i].srcbusirq & 3)) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- return irq;
+ best_idx = i;
+ best_ioapic = ioapic_idx;
+ goto out;
}
+
/*
* Use the first all-but-pin matching entry as a
* best-guess fuzzy result for broken mptables.
*/
- if (best_guess < 0) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- best_guess = irq;
+ if (best_idx < 0) {
+ best_idx = i;
+ best_ioapic = ioapic_idx;
}
}
- return best_guess;
+ if (best_idx < 0)
+ return -1;
+
+out:
+ irq = pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq,
+ IOAPIC_MAP_ALLOC);
+ if (irq > 0)
+ set_io_apic_irq_attr(irq_attr, best_ioapic,
+ mp_irqs[best_idx].dstirq,
+ irq_trigger(best_idx),
+ irq_polarity(best_idx));
+ return irq;
}
EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);

@@ -1257,7 +1344,7 @@ static inline int IO_APIC_irq_trigger(int irq)

for_each_ioapic_pin(apic, pin) {
idx = find_irq_entry(apic, pin, mp_INT);
- if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin, 0)))
return irq_trigger(idx);
}
/*
@@ -1383,8 +1470,9 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
continue;

- irq = pin_2_irq(idx, ioapic_idx, pin);
- if (!mp_init_irq_at_boot(ioapic_idx, irq))
+ 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;

/*
@@ -1434,8 +1522,8 @@ void setup_IO_APIC_irq_extra(u32 gsi)
if (idx == -1)
return;

- irq = pin_2_irq(idx, ioapic_idx, pin);
- if (mp_init_irq_at_boot(ioapic_idx, irq))
+ irq = pin_2_irq(idx, ioapic_idx, pin, IOAPIC_MAP_ALLOC);
+ if (irq < 0 || mp_init_irq_at_boot(ioapic_idx, irq))
return;

set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
@@ -3543,8 +3631,8 @@ void __init setup_ioapic_dest(void)
if (irq_entry == -1)
continue;

- irq = pin_2_irq(irq_entry, ioapic, pin);
- if (!mp_init_irq_at_boot(ioapic, irq))
+ irq = pin_2_irq(irq_entry, ioapic, pin, 0);
+ if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
continue;

idata = irq_get_irq_data(irq);

Subject: [tip:x86/apic] x86: ce4100, irq: Make CE4100 depend on CONFIG_X86_IO_APIC

Commit-ID: 6084a6e23c971ef703229ee1aec68d01688578d6
Gitweb: http://git.kernel.org/tip/6084a6e23c971ef703229ee1aec68d01688578d6
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:46 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86: ce4100, irq: Make CE4100 depend on CONFIG_X86_IO_APIC

Intel CE4100 platforms need IOAPIC support becasue some devices are
always connected to the second IOAPIC, so make CONFIG_CE depends on
CONFIG_X86_IO_APIC.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/Kconfig | 1 +
arch/x86/platform/ce4100/ce4100.c | 9 ++-------
2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index a8f749e..9df5c45 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -429,6 +429,7 @@ config X86_INTEL_CE
bool "CE4100 TV platform"
depends on PCI
depends on PCI_GODIRECT
+ depends on X86_IO_APIC
depends on X86_32
depends on X86_EXTENDED_PLATFORM
select X86_REBOOTFIXUPS
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 8244f5e..0a54a58 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -135,14 +135,12 @@ static void __init sdv_arch_setup(void)
sdv_serial_fixup();
}

-#ifdef CONFIG_X86_IO_APIC
static void sdv_pci_init(void)
{
x86_of_pci_init();
/* We can't set this earlier, because we need to calibrate the timer */
legacy_pic = &null_legacy_pic;
}
-#endif

/*
* CE4100 specific x86_init function overrides and early setup
@@ -155,7 +153,9 @@ void __init x86_ce4100_early_setup(void)
x86_init.resources.probe_roms = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
x86_init.mpparse.find_smp_config = x86_init_noop;
+ x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
x86_init.pci.init = ce4100_pci_init;
+ x86_init.pci.init_irq = sdv_pci_init;

/*
* By default, the reboot method is ACPI which is supported by the
@@ -166,10 +166,5 @@ void __init x86_ce4100_early_setup(void)
*/
reboot_type = BOOT_KBD;

-#ifdef CONFIG_X86_IO_APIC
- x86_init.pci.init_irq = sdv_pci_init;
- x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
-#endif
-
pm_power_off = ce4100_power_off;
}

Subject: [tip:x86/apic] x86, mpparse, irq: Provide basic irqdomain support

Commit-ID: 74501edcd846830bec86bfa06c47c25083e70ffc
Gitweb: http://git.kernel.org/tip/74501edcd846830bec86bfa06c47c25083e70ffc
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:55 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, mpparse, irq: Provide basic irqdomain support

Enhance mpparse to provide basic support of irqdomain.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/mpparse.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index ea8595e..13c8e1f 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/pci.h>
+#include <linux/irqdomain.h>

#include <asm/mtrr.h>
#include <asm/mpspec.h>
@@ -112,10 +113,17 @@ static void __init MP_bus_info(struct mpc_bus *m)
pr_warn("Unknown bustype %s - ignoring\n", str);
}

+static struct irq_domain_ops mp_ioapic_irqdomain_ops;
+
static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_LEGACY,
+ .ops = &mp_ioapic_irqdomain_ops,
+ };
+
if (m->flags & MPC_APIC_USABLE)
- mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, NULL);
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, &cfg);
}

static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)

Subject: [tip:x86/apic] x86, SFI, irq: Provide basic irqdomain support

Commit-ID: 1b5d3e00d45e093fa0551c588034c3355b362f66
Gitweb: http://git.kernel.org/tip/1b5d3e00d45e093fa0551c588034c3355b362f66
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:56 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, SFI, irq: Provide basic irqdomain support

Enhance SFI to provide basic support of irqdomain with identity mapping
between GSIs and IRQs.

Some Intel MID platforms assumes identity mapping between GSI and IRQ,
so we can't dynamically allocate IRQ number on demand.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: [email protected]
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: David Cohen <[email protected]>
Cc: Kuppuswamy Sathyanarayanan <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/pci/intel_mid_pci.c | 3 +++
arch/x86/platform/intel-mid/sfi.c | 2 ++
arch/x86/platform/sfi/sfi.c | 8 +++++++-
3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 84b9d67..fcbdc5fa 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -217,6 +217,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
* IOAPIC RTE entries, so we just enable RTE for the device.
*/
+ if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
+ return -EBUSY;
+
irq_attr.ioapic = mp_find_ioapic(dev->irq);
irq_attr.ioapic_pin = dev->irq;
irq_attr.trigger = 1; /* level */
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
index 994c40b..7161395 100644
--- a/arch/x86/platform/intel-mid/sfi.c
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -473,6 +473,8 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
/* PNW and CLV go with active low */
irq_attr.polarity = 1;
}
+ WARN_ON(mp_map_gsi_to_irq(irq,
+ IOAPIC_MAP_ALLOC) < 0);
io_apic_set_pci_routing(NULL, irq, &irq_attr);
}
} else {
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index 8f2f789..1fdaa57 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/io.h>
+#include <linux/irqdomain.h>

#include <asm/io_apic.h>
#include <asm/mpspec.h>
@@ -70,19 +71,24 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
#endif /* CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
+static struct irq_domain_ops sfi_ioapic_irqdomain_ops;

static int __init sfi_parse_ioapic(struct sfi_table_header *table)
{
struct sfi_table_simple *sb;
struct sfi_apic_table_entry *pentry;
int i, num;
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_STRICT,
+ .ops = &sfi_ioapic_irqdomain_ops,
+ };

sb = (struct sfi_table_simple *)table;
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry);
pentry = (struct sfi_apic_table_entry *)sb->pentry;

for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_top, NULL);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg);
pentry++;
}

Subject: [tip:x86/apic] x86, devicetree, irq: Use common mechanism to support irqdomain

Commit-ID: facd8fdb25fc4d041a283446cfb040cbfe2c3723
Gitweb: http://git.kernel.org/tip/facd8fdb25fc4d041a283446cfb040cbfe2c3723
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:57 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, devicetree, irq: Use common mechanism to support irqdomain

Now the ioapic driver provides a common interface to create irqdomain,
so replace the private implementation.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: Tony Lindgren <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/prom.h | 2 -
arch/x86/kernel/devicetree.c | 191 +++++++++++++------------------------------
arch/x86/kernel/irqinit.c | 6 --
3 files changed, 59 insertions(+), 140 deletions(-)

diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index fbeb06e..1d081ac 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -26,12 +26,10 @@
extern int of_ioapic;
extern u64 initial_dtb;
extern void add_dtb(u64 data);
-extern void x86_add_irq_domains(void);
void x86_of_pci_init(void);
void x86_dtb_init(void);
#else
static inline void add_dtb(u64 data) { }
-static inline void x86_add_irq_domains(void) { }
static inline void x86_of_pci_init(void) { }
static inline void x86_dtb_init(void) { }
#define of_ioapic 0
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index d2c53fe..ee26fec 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -166,82 +166,6 @@ static void __init dtb_lapic_setup(void)
#ifdef CONFIG_X86_IO_APIC
static unsigned int ioapic_id;

-static void __init dtb_add_ioapic(struct device_node *dn)
-{
- struct resource r;
- int ret;
-
- ret = of_address_to_resource(dn, 0, &r);
- if (ret) {
- printk(KERN_ERR "Can't obtain address from node %s.\n",
- dn->full_name);
- return;
- }
- mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL);
-}
-
-static void __init dtb_ioapic_setup(void)
-{
- struct device_node *dn;
-
- for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
- dtb_add_ioapic(dn);
-
- if (nr_ioapics) {
- of_ioapic = 1;
- return;
- }
- printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
-}
-#else
-static void __init dtb_ioapic_setup(void) {}
-#endif
-
-static void __init dtb_apic_setup(void)
-{
- dtb_lapic_setup();
- dtb_ioapic_setup();
-}
-
-#ifdef CONFIG_OF_FLATTREE
-static void __init x86_flattree_get_config(void)
-{
- u32 size, map_len;
- void *dt;
-
- if (!initial_dtb)
- return;
-
- map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
-
- initial_boot_params = dt = early_memremap(initial_dtb, map_len);
- size = of_get_flat_dt_size();
- if (map_len < size) {
- early_iounmap(dt, map_len);
- initial_boot_params = dt = early_memremap(initial_dtb, size);
- map_len = size;
- }
-
- unflatten_and_copy_device_tree();
- early_iounmap(dt, map_len);
-}
-#else
-static inline void x86_flattree_get_config(void) { }
-#endif
-
-void __init x86_dtb_init(void)
-{
- x86_flattree_get_config();
-
- if (!of_have_populated_dt())
- return;
-
- dtb_setup_hpet();
- dtb_apic_setup();
-}
-
-#ifdef CONFIG_X86_IO_APIC
-
struct of_ioapic_type {
u32 out_type;
u32 trigger;
@@ -292,7 +216,7 @@ static int ioapic_xlate(struct irq_domain *domain,

it = &of_ioapic_type[intspec[1]];

- idx = (u32) domain->host_data;
+ idx = (u32)(long)domain->host_data;
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);

rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
@@ -309,78 +233,81 @@ const struct irq_domain_ops ioapic_irq_domain_ops = {
.xlate = ioapic_xlate,
};

-static void dt_add_ioapic_domain(unsigned int ioapic_num,
- struct device_node *np)
+static void __init dtb_add_ioapic(struct device_node *dn)
{
- struct irq_domain *id;
- struct mp_ioapic_gsi *gsi_cfg;
+ struct resource r;
int ret;
- int num, legacy_irqs = nr_legacy_irqs();
-
- gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
- num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
-
- id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
- (void *)ioapic_num);
- BUG_ON(!id);
- if (gsi_cfg->gsi_base == 0) {
- /*
- * The first nr_legacy_irqs() irq descs are allocated in
- * early_irq_init() and need just a mapping. The
- * remaining irqs need both. All of them are preallocated
- * and assigned so we can keep the 1:1 mapping which the ioapic
- * is having.
- */
- irq_domain_associate_many(id, 0, 0, legacy_irqs);
-
- if (num > legacy_irqs) {
- ret = irq_create_strict_mappings(id, legacy_irqs,
- legacy_irqs, num - legacy_irqs);
- if (ret)
- pr_err("Error creating mapping for the "
- "remaining IRQs: %d\n", ret);
- }
- irq_set_default_host(id);
- } else {
- ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
- if (ret)
- pr_err("Error creating IRQ mapping: %d\n", ret);
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_DYNAMIC,
+ .ops = &ioapic_irq_domain_ops,
+ .dev = dn,
+ };
+
+ ret = of_address_to_resource(dn, 0, &r);
+ if (ret) {
+ printk(KERN_ERR "Can't obtain address from node %s.\n",
+ dn->full_name);
+ return;
}
+ mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
}

-static void __init ioapic_add_ofnode(struct device_node *np)
+static void __init dtb_ioapic_setup(void)
{
- struct resource r;
- int i, ret;
+ struct device_node *dn;

- ret = of_address_to_resource(np, 0, &r);
- if (ret) {
- printk(KERN_ERR "Failed to obtain address for %s\n",
- np->full_name);
+ for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
+ dtb_add_ioapic(dn);
+
+ if (nr_ioapics) {
+ of_ioapic = 1;
return;
}
+ printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif

- for (i = 0; i < nr_ioapics; i++) {
- if (r.start == mpc_ioapic_addr(i)) {
- dt_add_ioapic_domain(i, np);
- return;
- }
- }
- printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
+static void __init dtb_apic_setup(void)
+{
+ dtb_lapic_setup();
+ dtb_ioapic_setup();
}

-void __init x86_add_irq_domains(void)
+#ifdef CONFIG_OF_FLATTREE
+static void __init x86_flattree_get_config(void)
{
- struct device_node *dp;
+ u32 size, map_len;
+ void *dt;

- if (!of_have_populated_dt())
+ if (!initial_dtb)
return;

- for_each_node_with_property(dp, "interrupt-controller") {
- if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
- ioapic_add_ofnode(dp);
+ map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
+
+ initial_boot_params = dt = early_memremap(initial_dtb, map_len);
+ size = of_get_flat_dt_size();
+ if (map_len < size) {
+ early_iounmap(dt, map_len);
+ initial_boot_params = dt = early_memremap(initial_dtb, size);
+ map_len = size;
}
+
+ unflatten_and_copy_device_tree();
+ early_iounmap(dt, map_len);
}
#else
-void __init x86_add_irq_domains(void) { }
+static inline void x86_flattree_get_config(void) { }
#endif
+
+void __init x86_dtb_init(void)
+{
+ x86_flattree_get_config();
+
+ if (!of_have_populated_dt())
+ return;
+
+ dtb_setup_hpet();
+ dtb_apic_setup();
+}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index a0111e9..1e6cff5 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -87,12 +87,6 @@ void __init init_IRQ(void)
int i;

/*
- * We probably need a better place for this, but it works for
- * now ...
- */
- x86_add_irq_domains();
-
- /*
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
* If these IRQ's are handled by legacy interrupt-controllers like PIC,
* then this configuration will likely be static after the boot. If

Subject: [tip:x86/apic] x86, irq, mpparse: Use common irqdomain map interface to program IOAPIC pins

Commit-ID: 9506063992cc0785246fd314a4a40b6314685aa8
Gitweb: http://git.kernel.org/tip/9506063992cc0785246fd314a4a40b6314685aa8
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:00 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, irq, mpparse: Use common irqdomain map interface to program IOAPIC pins

Refine mpparse to use common irqdomain map interface to program IOAPIC pins,
so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/mpparse.c | 4 +++-
arch/x86/pci/irq.c | 2 --
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 13c8e1f..faf503a 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -113,7 +113,9 @@ static void __init MP_bus_info(struct mpc_bus *m)
pr_warn("Unknown bustype %s - ignoring\n", str);
}

-static struct irq_domain_ops mp_ioapic_irqdomain_ops;
+static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};

static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 84112f5..e4200e5 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -1227,8 +1227,6 @@ static int pirq_enable_irq(struct pci_dev *dev)
}
dev = temp_dev;
if (irq >= 0) {
- io_apic_set_pci_routing(&dev->dev, irq,
- &irq_attr);
dev->irq = irq;
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);

Subject: [tip:x86/apic] x86, irq, SFI: Use common irqdomain map interface to program IOAPIC pins

Commit-ID: ecc527d560cd87c74cc0bc7aff36eb72f7e18615
Gitweb: http://git.kernel.org/tip/ecc527d560cd87c74cc0bc7aff36eb72f7e18615
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:01 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, irq, SFI: Use common irqdomain map interface to program IOAPIC pins

Refine SFI to use common irqdomain map interface to program IOAPIC pins,
so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: [email protected]
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: David Cohen <[email protected]>
Cc: Kuppuswamy Sathyanarayanan <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/pci/intel_mid_pci.c | 19 +++++--------
arch/x86/platform/intel-mid/sfi.c | 58 +++++++++++++++++----------------------
arch/x86/platform/sfi/sfi.c | 4 ++-
3 files changed, 35 insertions(+), 46 deletions(-)

diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index fcbdc5fa..337d165 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -208,27 +208,22 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,

static int intel_mid_pci_irq_enable(struct pci_dev *dev)
{
- u8 pin;
- struct io_apic_irq_attr irq_attr;
+ int polarity;

- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
+ polarity = 0; /* active high */
+ else
+ polarity = 1; /* active low */

/*
* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
* IOAPIC RTE entries, so we just enable RTE for the device.
*/
+ if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
+ return -EBUSY;
if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
return -EBUSY;

- irq_attr.ioapic = mp_find_ioapic(dev->irq);
- irq_attr.ioapic_pin = dev->irq;
- irq_attr.trigger = 1; /* level */
- if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
- irq_attr.polarity = 0; /* active high */
- else
- irq_attr.polarity = 1; /* active low */
- io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
-
return 0;
}

diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
index 7161395..3c53a90 100644
--- a/arch/x86/platform/intel-mid/sfi.c
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -432,9 +432,8 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
struct sfi_table_simple *sb;
struct sfi_device_table_entry *pentry;
struct devs_id *dev = NULL;
- int num, i;
- int ioapic;
- struct io_apic_irq_attr irq_attr;
+ int num, i, ret;
+ int polarity;

sb = (struct sfi_table_simple *)table;
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
@@ -448,37 +447,30 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
* devices, but they have separate RTE entry in IOAPIC
* so we have to enable them one by one here
*/
- ioapic = mp_find_ioapic(irq);
- if (ioapic >= 0) {
- irq_attr.ioapic = ioapic;
- irq_attr.ioapic_pin = irq;
- irq_attr.trigger = 1;
- if (intel_mid_identify_cpu() ==
- INTEL_MID_CPU_CHIP_TANGIER) {
- if (!strncmp(pentry->name,
- "r69001-ts-i2c", 13))
- /* active low */
- irq_attr.polarity = 1;
- else if (!strncmp(pentry->name,
- "synaptics_3202", 14))
- /* active low */
- irq_attr.polarity = 1;
- else if (irq == 41)
- /* fast_int_1 */
- irq_attr.polarity = 1;
- else
- /* active high */
- irq_attr.polarity = 0;
- } else {
- /* PNW and CLV go with active low */
- irq_attr.polarity = 1;
- }
- WARN_ON(mp_map_gsi_to_irq(irq,
- IOAPIC_MAP_ALLOC) < 0);
- io_apic_set_pci_routing(NULL, irq, &irq_attr);
+ if (intel_mid_identify_cpu() ==
+ INTEL_MID_CPU_CHIP_TANGIER) {
+ if (!strncmp(pentry->name, "r69001-ts-i2c", 13))
+ /* active low */
+ polarity = 1;
+ else if (!strncmp(pentry->name,
+ "synaptics_3202", 14))
+ /* active low */
+ polarity = 1;
+ else if (irq == 41)
+ /* fast_int_1 */
+ polarity = 1;
+ else
+ /* active high */
+ polarity = 0;
+ } else {
+ /* PNW and CLV go with active low */
+ polarity = 1;
}
- } else {
- irq = 0; /* No irq */
+
+ ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
+ if (ret == 0)
+ ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC);
+ WARN_ON(ret < 0);
}

dev = get_device_id(pentry->type, pentry->name);
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index 1fdaa57..2a8a74f 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -71,7 +71,9 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
#endif /* CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_X86_IO_APIC
-static struct irq_domain_ops sfi_ioapic_irqdomain_ops;
+static struct irq_domain_ops sfi_ioapic_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};

static int __init sfi_parse_ioapic(struct sfi_table_header *table)
{

Subject: [tip:x86/apic] x86, irq, devicetree: Use common irqdomain map interface to program IOAPIC pins

Commit-ID: 795aacf63fee1bfe8b68fd5db4882576c5c0c570
Gitweb: http://git.kernel.org/tip/795aacf63fee1bfe8b68fd5db4882576c5c0c570
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:02 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, irq, devicetree: Use common irqdomain map interface to program IOAPIC pins

Refine devicetree to use common irqdomain map interface to program
IOAPIC pins, so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: Tony Lindgren <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/devicetree.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index ee26fec..f33bb43 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -201,10 +201,8 @@ static int ioapic_xlate(struct irq_domain *domain,
const u32 *intspec, u32 intsize,
irq_hw_number_t *out_hwirq, u32 *out_type)
{
- struct io_apic_irq_attr attr;
struct of_ioapic_type *it;
- u32 line, idx;
- int rc;
+ u32 line, idx, gsi;

if (WARN_ON(intsize < 2))
return -EINVAL;
@@ -217,12 +215,9 @@ static int ioapic_xlate(struct irq_domain *domain,
it = &of_ioapic_type[intspec[1]];

idx = (u32)(long)domain->host_data;
- set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
-
- rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
- cpu_to_node(0), &attr);
- if (rc)
- return rc;
+ gsi = mp_pin_to_gsi(idx, line);
+ if (mp_set_gsi_attr(gsi, it->trigger, it->polarity, cpu_to_node(0)))
+ return -EBUSY;

*out_hwirq = line;
*out_type = it->out_type;
@@ -230,6 +225,7 @@ static int ioapic_xlate(struct irq_domain *domain,
}

const struct irq_domain_ops ioapic_irq_domain_ops = {
+ .map = mp_irqdomain_map,
.xlate = ioapic_xlate,
};

Subject: [tip:x86/apic] x86, irq: Clean up unused IOAPIC interface

Commit-ID: 9f354b0252b81c870ac7534d71906280cb573f86
Gitweb: http://git.kernel.org/tip/9f354b0252b81c870ac7534d71906280cb573f86
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:03 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

x86, irq: Clean up unused IOAPIC interface

Now we have converted all x86 platforms to use the common irqdomain map
interface. There's no caller of io_apic_set_pci_routing(),
setup_IO_APIC_irq_extra() and io_apic_setup_irq_pin_once() any more,
so kill them.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/io_apic.h | 9 ------
arch/x86/kernel/apic/io_apic.c | 70 ------------------------------------------
2 files changed, 79 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index c535878..af6f9d4 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -141,9 +141,6 @@ extern int noioapicreroute;

struct io_apic_irq_attr;
struct irq_cfg;
-extern int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr);
-extern void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_insert_resources(void);

extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
@@ -155,8 +152,6 @@ extern void native_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id);
extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
-extern int io_apic_setup_irq_pin_once(unsigned int irq, int node,
- struct io_apic_irq_attr *attr);

extern int save_ioapic_entries(void);
extern void mask_ioapic_entries(void);
@@ -240,10 +235,6 @@ static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }

-struct io_apic_irq_attr;
-static inline int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr) { return 0; }
-
static inline int save_ioapic_entries(void)
{
return -ENOMEM;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index a602b35..6e3d4c7 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -111,7 +111,6 @@ static struct ioapic {
struct ioapic_domain_cfg irqdomain_cfg;
struct irq_domain *irqdomain;
struct mp_pin_info *pin_info;
- DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];

#define mpc_ioapic_ver(ioapic_idx) ioapics[ioapic_idx].mp_config.apicver
@@ -1524,38 +1523,6 @@ static void __init setup_IO_APIC_irqs(void)
}

/*
- * for the gsi that is not in first ioapic
- * but could not use acpi_register_gsi()
- * like some special sci in IBM x3330
- */
-void setup_IO_APIC_irq_extra(u32 gsi)
-{
- int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0);
- struct io_apic_irq_attr attr;
-
- /*
- * Convert 'gsi' to 'ioapic.pin'.
- */
- ioapic_idx = mp_find_ioapic(gsi);
- if (ioapic_idx < 0)
- return;
-
- pin = mp_find_ioapic_pin(ioapic_idx, gsi);
- idx = find_irq_entry(ioapic_idx, pin, mp_INT);
- if (idx == -1)
- return;
-
- irq = pin_2_irq(idx, ioapic_idx, pin, IOAPIC_MAP_ALLOC);
- if (irq < 0 || mp_init_irq_at_boot(ioapic_idx, irq))
- return;
-
- set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
- irq_polarity(idx));
-
- io_apic_setup_irq_pin_once(irq, node, &attr);
-}
-
-/*
* Set up the timer pin, possibly with the 8259A-master behind.
*/
static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
@@ -3458,27 +3425,6 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
return ret;
}

-int io_apic_setup_irq_pin_once(unsigned int irq, int node,
- struct io_apic_irq_attr *attr)
-{
- unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin;
- int ret;
- struct IO_APIC_route_entry orig_entry;
-
- /* Avoid redundant programming */
- if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) {
- pr_debug("Pin %d-%d already programmed\n", mpc_ioapic_id(ioapic_idx), pin);
- orig_entry = ioapic_read_entry(attr->ioapic, pin);
- if (attr->trigger == orig_entry.trigger && attr->polarity == orig_entry.polarity)
- return 0;
- return -EBUSY;
- }
- ret = io_apic_setup_irq_pin(irq, node, attr);
- if (!ret)
- set_bit(pin, ioapics[ioapic_idx].pin_programmed);
- return ret;
-}
-
static int __init io_apic_get_redir_entries(int ioapic)
{
union IO_APIC_reg_01 reg_01;
@@ -3525,22 +3471,6 @@ int __init arch_probe_nr_irqs(void)
return 0;
}

-int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr)
-{
- int node;
-
- if (!IO_APIC_IRQ(irq)) {
- apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
- irq_attr->ioapic);
- return -EINVAL;
- }
-
- node = dev ? dev_to_node(dev) : cpu_to_node(0);
-
- return io_apic_setup_irq_pin_once(irq, node, irq_attr);
-}
-
#ifdef CONFIG_X86_32
static int __init io_apic_get_unique_id(int ioapic, int apic_id)
{

Subject: [tip:x86/apic] x86, irq: Simplify the way to handle ISA IRQ

Commit-ID: 16ee7b3dcc56be14b9a813612cff2cc2339cdced
Gitweb: http://git.kernel.org/tip/16ee7b3dcc56be14b9a813612cff2cc2339cdced
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:04 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

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 <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 15 +------
arch/x86/kernel/apic/io_apic.c | 98 ++++++++++++++++--------------------------
2 files changed, 40 insertions(+), 73 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 9add76f..fd4b6d2 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -101,17 +101,6 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

#define ACPI_INVALID_GSI INT_MIN

-static int map_gsi_to_irq(unsigned int gsi, unsigned int flags)
-{
- int i;
-
- for (i = 0; i < nr_legacy_irqs(); i++)
- if (isa_irq_to_gsi[i] == gsi)
- return i;
-
- return mp_map_gsi_to_irq(gsi, flags);
-}
-
/*
* This is just a simple wrapper around early_ioremap(),
* with sanity checks for phys == 0 and size == 0.
@@ -422,7 +411,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
return -1;
}

- irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
+ irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
if (irq < 0)
return irq;

@@ -603,7 +592,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)

int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- int irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+ int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);

if (irq >= 0) {
*irqp = irq;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 6e3d4c7..8485d90 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);
+ }
}

/*

Subject: [tip:x86/apic] x86, irq: Reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain

Commit-ID: 79598505aee61bc943955de3653be054c2f7393f
Gitweb: http://git.kernel.org/tip/79598505aee61bc943955de3653be054c2f7393f
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:44 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, irq: Reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain

Reorganize function IO_APIC_get_PCI_irq_vector() a bit to better support
coming irqdomain.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 61 +++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 28 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 446a931..09e5c7b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -997,7 +997,7 @@ static int pin_2_irq(int idx, int apic, int pin)
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
struct io_apic_irq_attr *irq_attr)
{
- int ioapic_idx, i, best_guess = -1;
+ int irq, i, best_guess = -1;

apic_printk(APIC_DEBUG,
"querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1007,41 +1007,46 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
"PCI BIOS passed nonexistent PCI bus %d!\n", bus);
return -1;
}
+
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].srcbus;
+ int ioapic_idx, found = 0;
+
+ if (bus != lbus || mp_irqs[i].irqtype != mp_INT ||
+ slot != ((mp_irqs[i].srcbusirq >> 2) & 0x1f))
+ continue;

for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
- mp_irqs[i].dstapic == MP_APIC_ALL)
+ mp_irqs[i].dstapic == MP_APIC_ALL) {
+ found = 1;
break;
+ }
+ if (!found)
+ continue;

- if (!test_bit(lbus, mp_bus_not_pci) &&
- mp_irqs[i].irqtype == mp_INT &&
- (bus == lbus) &&
- (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
- int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
-
- if (!(ioapic_idx || IO_APIC_IRQ(irq)))
- continue;
+ /* Skip ISA IRQs */
+ irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
+ if (ioapic_idx == 0 && !IO_APIC_IRQ(irq))
+ continue;

- if (pin == (mp_irqs[i].srcbusirq & 3)) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- return irq;
- }
- /*
- * Use the first all-but-pin matching entry as a
- * best-guess fuzzy result for broken mptables.
- */
- if (best_guess < 0) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- best_guess = irq;
- }
+ if (pin == (mp_irqs[i].srcbusirq & 3)) {
+ set_io_apic_irq_attr(irq_attr, ioapic_idx,
+ mp_irqs[i].dstirq,
+ irq_trigger(i),
+ irq_polarity(i));
+ return irq;
+ }
+ /*
+ * Use the first all-but-pin matching entry as a
+ * best-guess fuzzy result for broken mptables.
+ */
+ if (best_guess < 0) {
+ set_io_apic_irq_attr(irq_attr, ioapic_idx,
+ mp_irqs[i].dstirq,
+ irq_trigger(i),
+ irq_polarity(i));
+ best_guess = irq;
}
}
return best_guess;

Subject: [tip:x86/apic] x86, irq: Introduce two helper functions to support irqdomain map operation

Commit-ID: 15a3c7cc9154321fc3ed1f7738bb7bbe690af91d
Gitweb: http://git.kernel.org/tip/15a3c7cc9154321fc3ed1f7738bb7bbe690af91d
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:58 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, irq: Introduce two helper functions to support irqdomain map operation

Currently there are multiple entries to program IOAPIC pins, such as
io_apic_setup_irq_pin_once(), io_apic_set_pci_routing() and
setup_IO_APIC_irq_extra() etc.

This patch introduces two functions to help consolidate the code to
program IOAPIC pins. Function mp_set_pin_attr() is used to optionally
set trigger, polarity and NUMA node property for an IOAPIC pin.
If mp_set_pin_attr() is not invoked for a pin, the default configuration
from BIOS will be used.

Function mp_irqdomain_map() is an common implementation of irqdomain map()
operation. It figures out attribures for pin and then actually programs
the IOAPIC pin. We hope this will be the only entrance for programming
IOAPIC pin.

And the flow will:
1) caller such as xxx_pci_irq_enable figures out pin attributes.
2) Invoke mp_set_pin_attr() to set attributes for a pin. If the pin has
already bin programmed, mp_set_pin_attr() will aslo detects attribute
confictions.
3) Invoke mp_map_pin_to_irq()
3.1) If IRQ has already been assigned, return irq_find_mapping()
3.2) Else irq_create_mapping()
->irq_domain_associate()
->mp_irqdomain_map()
->io_apic_setup_irq_pin()

So every pin will only programmed once by mp_irqdomain_map(), so we
could kill io_apic_setup_irq_pin_once(), io_apic_set_pci_routing() and
setup_IO_APIC_irq_extra() etc.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/io_apic.h | 5 +++
arch/x86/kernel/apic/io_apic.c | 99 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 3e4bea3..c535878 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -173,7 +173,9 @@ enum ioapic_domain_type {
};

struct device_node;
+struct irq_domain;
struct irq_domain_ops;
+
struct ioapic_domain_cfg {
enum ioapic_domain_type type;
const struct irq_domain_ops *ops;
@@ -192,6 +194,9 @@ extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
struct ioapic_domain_cfg *cfg);
+extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq);
+extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
extern void __init pre_init_apic_IRQ0(void);

extern void mp_save_irq(struct mpc_intsrc *m);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 563f450..a602b35 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -87,6 +87,14 @@ static DEFINE_RAW_SPINLOCK(vector_lock);
static DEFINE_MUTEX(ioapic_mutex);
static unsigned int ioapic_dynirq_base;

+struct mp_pin_info {
+ int trigger;
+ int polarity;
+ int node;
+ int set;
+ u32 count;
+};
+
static struct ioapic {
/*
* # of IRQ routing registers
@@ -102,6 +110,7 @@ static struct ioapic {
struct mp_ioapic_gsi gsi_config;
struct ioapic_domain_cfg irqdomain_cfg;
struct irq_domain *irqdomain;
+ struct mp_pin_info *pin_info;
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];

@@ -147,6 +156,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
}

+static inline struct mp_pin_info *mp_pin_info(int ioapic_idx, int pin)
+{
+ return ioapics[ioapic_idx].pin_info + pin;
+}
+
static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
{
return ioapics[ioapic].irqdomain;
@@ -1006,6 +1020,7 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
{
int irq;
struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+ struct mp_pin_info *info = mp_pin_info(ioapic, pin);

/*
* Don't use irqdomain to manage ISA IRQs because there may be
@@ -1034,6 +1049,13 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
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;
@@ -2923,18 +2945,27 @@ out:

static int mp_irqdomain_create(int ioapic)
{
+ size_t size;
int hwirqs = mp_ioapic_pin_count(ioapic);
struct ioapic *ip = &ioapics[ioapic];
struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg;
struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);

+ size = sizeof(struct mp_pin_info) * mp_ioapic_pin_count(ioapic);
+ ip->pin_info = kzalloc(size, GFP_KERNEL);
+ if (!ip->pin_info)
+ return -ENOMEM;
+
if (cfg->type == IOAPIC_DOMAIN_INVALID)
return 0;

ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops,
(void *)(long)ioapic);
- if(!ip->irqdomain)
+ if(!ip->irqdomain) {
+ kfree(ip->pin_info);
+ ip->pin_info = NULL;
return -ENOMEM;
+ }

if (cfg->type == IOAPIC_DOMAIN_LEGACY ||
cfg->type == IOAPIC_DOMAIN_STRICT)
@@ -3902,6 +3933,72 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
nr_ioapics++;
}

+int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq)
+{
+ int ioapic = (int)(long)domain->host_data;
+ struct mp_pin_info *info = mp_pin_info(ioapic, hwirq);
+ struct io_apic_irq_attr attr;
+
+ /*
+ * 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, virq))
+ return 0;
+
+ /* Get default attribute if not set by caller yet */
+ if (!info->set) {
+ u32 gsi = mp_pin_to_gsi(ioapic, hwirq);
+
+ if (acpi_get_override_irq(gsi, &info->trigger,
+ &info->polarity) < 0) {
+ /*
+ * PCI interrupts are always polarity one level
+ * triggered.
+ */
+ info->trigger = 1;
+ info->polarity = 1;
+ }
+ info->node = NUMA_NO_NODE;
+ info->set = 1;
+ }
+ set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger,
+ info->polarity);
+
+ return io_apic_setup_irq_pin(virq, info->node, &attr);
+}
+
+int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
+{
+ int ret = 0;
+ int ioapic, pin;
+ struct mp_pin_info *info;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return -ENODEV;
+
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ info = mp_pin_info(ioapic, pin);
+ trigger = trigger ? 1 : 0;
+ polarity = polarity ? 1 : 0;
+
+ mutex_lock(&ioapic_mutex);
+ if (!info->set) {
+ info->trigger = trigger;
+ info->polarity = polarity;
+ info->node = node;
+ info->set = 1;
+ } else if (info->trigger != trigger || info->polarity != polarity) {
+ ret = -EBUSY;
+ }
+ mutex_unlock(&ioapic_mutex);
+
+ return ret;
+}
+
/* Enable IOAPIC early just for system timer */
void __init pre_init_apic_IRQ0(void)
{

Subject: [tip:x86/apic] x86, irq, mpparse: Release IOAPIC pin when PCI device is disabled

Commit-ID: c03b3b0738a56cf283b0d05256988d5e3c8bd719
Gitweb: http://git.kernel.org/tip/c03b3b0738a56cf283b0d05256988d5e3c8bd719
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:08 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

x86, irq, mpparse: Release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/mpparse.c | 1 +
arch/x86/pci/irq.c | 13 +++++++++++--
2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index faf503a..fde86d2 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -115,6 +115,7 @@ static void __init MP_bus_info(struct mpc_bus *m)

static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
.map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
};

static void __init MP_ioapic_info(struct mpc_ioapic *m)
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index e4200e5..748cfe8 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -26,6 +26,7 @@ static int acer_tm360_irqrouting;
static struct irq_routing_table *pirq_table;

static int pirq_enable_irq(struct pci_dev *dev);
+static void pirq_disable_irq(struct pci_dev *dev);

/*
* Never use: 0, 1, 2 (timer, keyboard, and cascade)
@@ -53,7 +54,7 @@ struct irq_router_handler {
};

int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
-void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq;

/*
* Check passed address for the PCI IRQ Routing Table signature
@@ -1186,7 +1187,7 @@ void pcibios_penalize_isa_irq(int irq, int active)

static int pirq_enable_irq(struct pci_dev *dev)
{
- u8 pin;
+ u8 pin = 0;

pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin && !pcibios_lookup_irq(dev, 1)) {
@@ -1252,3 +1253,11 @@ static int pirq_enable_irq(struct pci_dev *dev)
}
return 0;
}
+
+static void pirq_disable_irq(struct pci_dev *dev)
+{
+ if (io_apic_assign_pci_irqs && dev->irq) {
+ mp_unmap_irq(dev->irq);
+ dev->irq = 0;
+ }
+}

Subject: [tip:x86/apic] x86, irq: Introduce some helper utilities to improve readability

Commit-ID: 18e485518656205bbffce5e01f07830a6c3f557d
Gitweb: http://git.kernel.org/tip/18e485518656205bbffce5e01f07830a6c3f557d
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:45 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:41 +0200

x86, irq: Introduce some helper utilities to improve readability

It also fixes an off by one bug in
if ((ioapic_idx > 0) && (irq > NR_IRQS_LEGACY))
It should be
if ((ioapic_idx > 0) && (irq >= NR_IRQS_LEGACY))

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/io_apic.h | 2 ++
arch/x86/kernel/apic/io_apic.c | 29 ++++++++++++++++++++++-------
2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index de3d8b0..b775cf3 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -171,6 +171,7 @@ extern u32 gsi_top;

extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
+extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);

@@ -212,6 +213,7 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
+static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }

struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 09e5c7b..424f795 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -117,6 +117,24 @@ struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx)
return &ioapics[ioapic_idx].gsi_config;
}

+static inline int mp_ioapic_pin_count(int ioapic)
+{
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+ return gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
+}
+
+u32 mp_pin_to_gsi(int ioapic, int pin)
+{
+ return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin;
+}
+
+/* Initialize all legacy IRQs and all pins on the first IOAPIC at boot */
+static inline int mp_init_irq_at_boot(int ioapic, int irq)
+{
+ return ioapic == 0 || (irq >= 0 && irq < NR_IRQS_LEGACY);
+}
+
int nr_ioapics;

/* The one past the highest gsi number used */
@@ -1367,8 +1385,7 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
continue;

irq = pin_2_irq(idx, ioapic_idx, pin);
-
- if ((ioapic_idx > 0) && (irq > NR_IRQS_LEGACY))
+ if (!mp_init_irq_at_boot(ioapic_idx, irq))
continue;

/*
@@ -1419,9 +1436,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
return;

irq = pin_2_irq(idx, ioapic_idx, pin);
-
- /* Only handle the non legacy irqs on secondary ioapics */
- if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY)
+ if (mp_init_irq_at_boot(ioapic_idx, irq))
return;

set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
@@ -3528,9 +3543,9 @@ void __init setup_ioapic_dest(void)
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
- irq = pin_2_irq(irq_entry, ioapic, pin);

- if ((ioapic > 0) && (irq > NR_IRQS_LEGACY))
+ irq = pin_2_irq(irq_entry, ioapic, pin);
+ if (!mp_init_irq_at_boot(ioapic, irq))
continue;

idata = irq_get_irq_data(irq);

Subject: [tip:x86/apic] x86, irq, ACPI: Use common irqdomain map interface to program IOAPIC pins

Commit-ID: d7b830013f59cf586c1cec3caa1ce7156da59a13
Gitweb: http://git.kernel.org/tip/d7b830013f59cf586c1cec3caa1ce7156da59a13
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:59 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:43 +0200

x86, irq, ACPI: Use common irqdomain map interface to program IOAPIC pins

Refine ACPI to use common irqdomain map interface to program IOAPIC pins,
so we can unify the callsite to progam IOAPIC pins.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 44 ++++++++++++--------------------------------
1 file changed, 12 insertions(+), 32 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8d9aee1..9add76f 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -405,11 +405,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
- int irq;
- int ioapic;
- int ioapic_pin;
- struct io_apic_irq_attr irq_attr;
- int ret;
+ int irq, node;

if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
@@ -418,39 +414,27 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;

+ trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
+ polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
+ node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
+ if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
+ pr_warn("Failed to set pin attr for GSI%d\n", gsi);
+ return -1;
+ }
+
irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
if (irq < 0)
return irq;

- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0) {
- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
- return gsi;
- }
-
- ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-
- if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mpc_ioapic_id(ioapic),
- ioapic_pin);
- return gsi;
- }
-
if (enable_update_mptable)
mp_config_acpi_gsi(dev, gsi, trigger, polarity);

- set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
- trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
- if (ret < 0)
- irq = -1;
-
return irq;
}

-static struct irq_domain_ops acpi_irqdomain_ops;
+static struct irq_domain_ops acpi_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};

static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
@@ -622,10 +606,6 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
int irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);

if (irq >= 0) {
-#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
-#endif
*irqp = irq;
return 0;
}

Subject: [tip:x86/apic] x86, irq, devicetree: Release IOAPIC pin when PCI device is disabled

Commit-ID: 00f49c29b3298806c74589a4ed016a2afb359e98
Gitweb: http://git.kernel.org/tip/00f49c29b3298806c74589a4ed016a2afb359e98
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:10 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

x86, irq, devicetree: Release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: Tony Lindgren <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/devicetree.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index f33bb43..3d35033 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -226,6 +226,7 @@ static int ioapic_xlate(struct irq_domain *domain,

const struct irq_domain_ops ioapic_irq_domain_ops = {
.map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
.xlate = ioapic_xlate,
};

Subject: [tip:x86/apic] x86, irq: Clean up irqdomain transition code

Commit-ID: b81975eade8c6495f3c4d6746d22bdc95f617777
Gitweb: http://git.kernel.org/tip/b81975eade8c6495f3c4d6746d22bdc95f617777
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:11 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

x86, irq: Clean up irqdomain transition code

Now we have completely switched to irqdomain, so clean up transition code
in IOAPIC drivers.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 28 +++++++++++-----------------
1 file changed, 11 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 8d80a8f..a44dce8 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -86,6 +86,7 @@ static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
static DEFINE_MUTEX(ioapic_mutex);
static unsigned int ioapic_dynirq_base;
+static int ioapic_initialized;

struct mp_pin_info {
int trigger;
@@ -1034,13 +1035,8 @@ 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;
- }
+ if (!domain)
+ return -1;

mutex_lock(&ioapic_mutex);

@@ -2986,6 +2982,8 @@ void __init setup_IO_APIC(void)
init_IO_APIC_traps();
if (nr_legacy_irqs())
check_timer();
+
+ ioapic_initialized = 1;
}

/*
@@ -3461,12 +3459,11 @@ static int __init io_apic_get_redir_entries(int ioapic)

unsigned int arch_dynirq_lower_bound(unsigned int from)
{
- unsigned int min = gsi_top + nr_legacy_irqs();
-
- if (ioapic_dynirq_base)
- return ioapic_dynirq_base;
-
- return from < min ? min : from;
+ /*
+ * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
+ * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
+ */
+ return ioapic_initialized ? ioapic_dynirq_base : gsi_top;
}

int __init arch_probe_nr_irqs(void)
@@ -3841,10 +3838,7 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
ioapics[idx].mp_config.apicaddr = address;
ioapics[idx].irqdomain = NULL;
- if (cfg)
- ioapics[idx].irqdomain_cfg = *cfg;
- else
- ioapics[idx].irqdomain_cfg.type = IOAPIC_DOMAIN_INVALID;
+ ioapics[idx].irqdomain_cfg = *cfg;

set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);

Subject: [tip:x86/apic] x86, irq: Count legacy IRQs by legacy_pic-> nr_legacy_irqs instead of NR_IRQS_LEGACY

Commit-ID: 95d76acc7518d566df18d67c1343bb375b78d1f3
Gitweb: http://git.kernel.org/tip/95d76acc7518d566df18d67c1343bb375b78d1f3
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:48 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86, irq: Count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY

Some platforms, such as Intel MID and mshypv, do not support legacy
interrupt controllers. So count legacy IRQs by legacy_pic->nr_legacy_irqs
instead of hard-coded NR_IRQS_LEGACY.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: [email protected]
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: Tony Lindgren <[email protected]>
Acked-by: David Vrabel <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/i8259.h | 5 +++++
arch/x86/kernel/acpi/boot.c | 13 +++++++------
arch/x86/kernel/apic/io_apic.c | 43 ++++++++++++++++++++++++------------------
arch/x86/kernel/devicetree.c | 13 +++++++------
arch/x86/kernel/irqinit.c | 6 +++---
arch/x86/pci/xen.c | 7 ++++---
6 files changed, 51 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index a203659..ccffa53 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -67,4 +67,9 @@ struct legacy_pic {
extern struct legacy_pic *legacy_pic;
extern struct legacy_pic null_legacy_pic;

+static inline int nr_legacy_irqs(void)
+{
+ return legacy_pic->nr_legacy_irqs;
+}
+
#endif /* _ASM_X86_I8259_H */
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index f3bafcd..b129765 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -43,6 +43,7 @@
#include <asm/io.h>
#include <asm/mpspec.h>
#include <asm/smp.h>
+#include <asm/i8259.h>

#include "sleep.h" /* To include x86_acpi_suspend_lowlevel */
static int __initdata acpi_force = 0;
@@ -101,10 +102,10 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {

static unsigned int gsi_to_irq(unsigned int gsi)
{
- unsigned int irq = gsi + NR_IRQS_LEGACY;
+ unsigned int irq = gsi + nr_legacy_irqs();
unsigned int i;

- for (i = 0; i < NR_IRQS_LEGACY; i++) {
+ for (i = 0; i < nr_legacy_irqs(); i++) {
if (isa_irq_to_gsi[i] == gsi) {
return i;
}
@@ -114,7 +115,7 @@ static unsigned int gsi_to_irq(unsigned int gsi)
* except on truly weird platforms that have
* non isa irqs in the first 16 gsis.
*/
- if (gsi >= NR_IRQS_LEGACY)
+ if (gsi >= nr_legacy_irqs())
irq = gsi;
else
irq = gsi_top + gsi;
@@ -371,7 +372,7 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
* otherwise there will be more than one entry with the same GSI
* and acpi_isa_irq_to_gsi() may give wrong result.
*/
- if (gsi < NR_IRQS_LEGACY && isa_irq_to_gsi[gsi] == gsi)
+ if (gsi < nr_legacy_irqs() && isa_irq_to_gsi[gsi] == gsi)
isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
isa_irq_to_gsi[bus_irq] = gsi;
}
@@ -628,7 +629,7 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);

int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq < NR_IRQS_LEGACY &&
+ if (isa_irq < nr_legacy_irqs() &&
isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
*gsi = isa_irq_to_gsi[isa_irq];
return 0;
@@ -1017,7 +1018,7 @@ static void __init mp_config_acpi_legacy_irqs(void)
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
- for (i = 0; i < NR_IRQS_LEGACY; i++) {
+ for (i = 0; i < nr_legacy_irqs(); i++) {
int ioapic, pin;
unsigned int dstapic;
int idx;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 424f795..4208ea9 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -129,10 +129,17 @@ u32 mp_pin_to_gsi(int ioapic, int pin)
return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin;
}

-/* Initialize all legacy IRQs and all pins on the first IOAPIC at boot */
+/*
+ * Initialize all legacy IRQs and all pins on the first IOAPIC
+ * if we have legacy interrupt controller. Kernel boot option "pirq="
+ * may rely on non-legacy pins on the first IOAPIC.
+ */
static inline int mp_init_irq_at_boot(int ioapic, int irq)
{
- return ioapic == 0 || (irq >= 0 && irq < NR_IRQS_LEGACY);
+ if (!nr_legacy_irqs())
+ return 0;
+
+ return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
}

int nr_ioapics;
@@ -216,7 +223,7 @@ int __init arch_early_irq_init(void)
struct irq_cfg *cfg;
int count, node, i;

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
io_apic_irqs = ~0UL;

for_each_ioapic(i) {
@@ -239,7 +246,7 @@ int __init arch_early_irq_init(void)
* For legacy IRQ's, start with assigning irq0 to irq15 to
* IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
*/
- if (i < legacy_pic->nr_legacy_irqs) {
+ if (i < nr_legacy_irqs()) {
cfg[i].vector = IRQ0_VECTOR + i;
cpumask_setall(cfg[i].domain);
}
@@ -823,7 +830,7 @@ static int __init find_isa_irq_apic(int irq, int type)
*/
static int EISA_ELCR(unsigned int irq)
{
- if (irq < legacy_pic->nr_legacy_irqs) {
+ if (irq < nr_legacy_irqs()) {
unsigned int port = 0x4d0 + (irq >> 3);
return (inb(port) >> (irq & 7)) & 1;
}
@@ -980,7 +987,7 @@ static int pin_2_irq(int idx, int apic, int pin)
} else {
u32 gsi = gsi_cfg->gsi_base + pin;

- if (gsi >= NR_IRQS_LEGACY)
+ if (gsi >= nr_legacy_irqs())
irq = gsi;
else
irq = gsi_top + gsi;
@@ -1357,7 +1364,7 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
}

ioapic_register_intr(irq, cfg, attr->trigger);
- if (irq < legacy_pic->nr_legacy_irqs)
+ if (irq < nr_legacy_irqs())
legacy_pic->mask(irq);

ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry);
@@ -1782,7 +1789,7 @@ __apicdebuginit(void) print_PIC(void)
unsigned int v;
unsigned long flags;

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;

printk(KERN_DEBUG "\nprinting PIC contents\n");
@@ -1854,7 +1861,7 @@ void __init enable_IO_APIC(void)
int i8259_apic, i8259_pin;
int apic, pin;

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;

for_each_ioapic_pin(apic, pin) {
@@ -1939,7 +1946,7 @@ void disable_IO_APIC(void)
*/
clear_IO_APIC();

- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;

x86_io_apic_ops.disable();
@@ -2143,7 +2150,7 @@ static unsigned int startup_ioapic_irq(struct irq_data *data)
unsigned long flags;

raw_spin_lock_irqsave(&ioapic_lock, flags);
- if (irq < legacy_pic->nr_legacy_irqs) {
+ if (irq < nr_legacy_irqs()) {
legacy_pic->mask(irq);
if (legacy_pic->irq_pending(irq))
was_pending = 1;
@@ -2542,7 +2549,7 @@ static inline void init_IO_APIC_traps(void)
* so default to an old-fashioned 8259
* interrupt if we can..
*/
- if (irq < legacy_pic->nr_legacy_irqs)
+ if (irq < nr_legacy_irqs())
legacy_pic->make_irq(irq);
else
/* Strange. Oh, well.. */
@@ -2839,7 +2846,7 @@ void __init setup_IO_APIC(void)
/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
*/
- io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+ io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;

apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
/*
@@ -2850,7 +2857,7 @@ void __init setup_IO_APIC(void)
sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
- if (legacy_pic->nr_legacy_irqs)
+ if (nr_legacy_irqs())
check_timer();
}

@@ -3348,7 +3355,7 @@ static int __init io_apic_get_redir_entries(int ioapic)

unsigned int arch_dynirq_lower_bound(unsigned int from)
{
- unsigned int min = gsi_top + NR_IRQS_LEGACY;
+ unsigned int min = gsi_top + nr_legacy_irqs();

return from < min ? min : from;
}
@@ -3360,17 +3367,17 @@ int __init arch_probe_nr_irqs(void)
if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
nr_irqs = NR_VECTORS * nr_cpu_ids;

- nr = (gsi_top + NR_IRQS_LEGACY) + 8 * nr_cpu_ids;
+ nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids;
#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
/*
* for MSI and HT dyn irq
*/
- nr += (gsi_top + NR_IRQS_LEGACY) * 16;
+ nr += gsi_top * 16;
#endif
if (nr < nr_irqs)
nr_irqs = nr;

- return NR_IRQS_LEGACY;
+ return nr_legacy_irqs();
}

int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 7db54b5..b468005 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -21,6 +21,7 @@
#include <asm/apic.h>
#include <asm/pci_x86.h>
#include <asm/setup.h>
+#include <asm/i8259.h>

__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
@@ -314,7 +315,7 @@ static void dt_add_ioapic_domain(unsigned int ioapic_num,
struct irq_domain *id;
struct mp_ioapic_gsi *gsi_cfg;
int ret;
- int num;
+ int num, legacy_irqs = nr_legacy_irqs();

gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
@@ -324,17 +325,17 @@ static void dt_add_ioapic_domain(unsigned int ioapic_num,
BUG_ON(!id);
if (gsi_cfg->gsi_base == 0) {
/*
- * The first NR_IRQS_LEGACY irq descs are allocated in
+ * The first nr_legacy_irqs() irq descs are allocated in
* early_irq_init() and need just a mapping. The
* remaining irqs need both. All of them are preallocated
* and assigned so we can keep the 1:1 mapping which the ioapic
* is having.
*/
- irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
+ irq_domain_associate_many(id, 0, 0, legacy_irqs);

- if (num > NR_IRQS_LEGACY) {
- ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
- NR_IRQS_LEGACY, num - NR_IRQS_LEGACY);
+ if (num > legacy_irqs) {
+ ret = irq_create_strict_mappings(id, legacy_irqs,
+ legacy_irqs, num - legacy_irqs);
if (ret)
pr_err("Error creating mapping for the "
"remaining IRQs: %d\n", ret);
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 7f50156..a0111e9 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -78,7 +78,7 @@ void __init init_ISA_irqs(void)
#endif
legacy_pic->init(0);

- for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+ for (i = 0; i < nr_legacy_irqs(); i++)
irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
}

@@ -100,7 +100,7 @@ void __init init_IRQ(void)
* then this vector space can be freed and re-used dynamically as the
* irq's migrate etc.
*/
- for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+ for (i = 0; i < nr_legacy_irqs(); i++)
per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;

x86_init.irqs.intr_init();
@@ -121,7 +121,7 @@ void setup_vector_irq(int cpu)
* legacy PIC, for the new cpu that is coming online, setup the static
* legacy vector to irq mapping:
*/
- for (irq = 0; irq < legacy_pic->nr_legacy_irqs; irq++)
+ for (irq = 0; irq < nr_legacy_irqs(); irq++)
per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq;
#endif

diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 905956f..093f5f4 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -23,6 +23,7 @@
#include <xen/features.h>
#include <xen/events.h>
#include <asm/xen/pci.h>
+#include <asm/i8259.h>

static int xen_pcifront_enable_irq(struct pci_dev *dev)
{
@@ -40,7 +41,7 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev)
/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
pirq = gsi;

- if (gsi < NR_IRQS_LEGACY)
+ if (gsi < nr_legacy_irqs())
share = 0;

rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
@@ -511,7 +512,7 @@ int __init pci_xen_initial_domain(void)
xen_setup_acpi_sci();
__acpi_register_gsi = acpi_register_gsi_xen;
/* Pre-allocate legacy irqs */
- for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
+ for (irq = 0; irq < nr_legacy_irqs(); irq++) {
int trigger, polarity;

if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
@@ -522,7 +523,7 @@ int __init pci_xen_initial_domain(void)
true /* Map GSI to PIRQ */);
}
if (0 == nr_ioapics) {
- for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
+ for (irq = 0; irq < nr_legacy_irqs(); irq++)
xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
}
return 0;

Subject: [tip:x86/apic] x86, irq, ACPI: Release IOAPIC pin when PCI device is disabled

Commit-ID: 6a38fa0e3c94dfd1394a71a2d47c9c4d47367374
Gitweb: http://git.kernel.org/tip/6a38fa0e3c94dfd1394a71a2d47c9c4d47367374
Author: Jiang Liu <[email protected]>
AuthorDate: Tue, 10 Jun 2014 14:16:27 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

x86, irq, ACPI: Release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 27 +++++++++++++++++++++++++++
drivers/acpi/pci_irq.c | 3 ++-
2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index fd4b6d2..8c28023 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -421,8 +421,24 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
return irq;
}

+static void mp_unregister_gsi(u32 gsi)
+{
+ int irq;
+
+ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ return;
+
+ if (acpi_gbl_FADT.sci_interrupt == gsi)
+ return;
+
+ irq = mp_map_gsi_to_irq(gsi, 0);
+ if (irq > 0)
+ mp_unmap_irq(irq);
+}
+
static struct irq_domain_ops acpi_irqdomain_ops = {
.map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
};

static int __init
@@ -640,8 +656,16 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
return irq;
}

+static void acpi_unregister_gsi_ioapic(u32 gsi)
+{
+#ifdef CONFIG_X86_IO_APIC
+ mp_unregister_gsi(gsi);
+#endif
+}
+
int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
int trigger, int polarity) = acpi_register_gsi_pic;
+void (*__acpi_unregister_gsi)(u32 gsi) = NULL;

#ifdef CONFIG_ACPI_SLEEP
int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel;
@@ -661,6 +685,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);

void acpi_unregister_gsi(u32 gsi)
{
+ if (__acpi_unregister_gsi)
+ __acpi_unregister_gsi(gsi);
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);

@@ -668,6 +694,7 @@ static void __init acpi_set_irq_model_ioapic(void)
{
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
__acpi_register_gsi = acpi_register_gsi_ioapic;
+ __acpi_unregister_gsi = acpi_unregister_gsi_ioapic;
acpi_ioapic = 1;
}

diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 9c62340..6ba463c 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -498,5 +498,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
*/

dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
- acpi_unregister_gsi(gsi);
+ if (gsi >= 0 && dev->irq > 0)
+ acpi_unregister_gsi(gsi);
}

Subject: [tip:x86/apic] x86, irq: Enhance mp_register_ioapic() to support irqdomain

Commit-ID: 44767bfaaed782d6d635ecbb13f3980041e6f33e
Gitweb: http://git.kernel.org/tip/44767bfaaed782d6d635ecbb13f3980041e6f33e
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:53 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86, irq: Enhance mp_register_ioapic() to support irqdomain

Enhance function mp_register_ioapic() to support irqdomain.
When registering IOAPIC, caller may provide callbacks and parameters
for creating irqdomain. The IOAPIC core will create irqdomain later
if caller has passed in corresponding parameters.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: [email protected]
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: Tony Lindgren <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/io_apic.h | 3 ++-
arch/x86/kernel/acpi/boot.c | 2 +-
arch/x86/kernel/apic/io_apic.c | 42 +++++++++++++++++++++++++++++++++++++++++-
arch/x86/kernel/devicetree.c | 2 +-
arch/x86/kernel/mpparse.c | 2 +-
arch/x86/platform/sfi/sfi.c | 2 +-
6 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 64c6e34..3e4bea3 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -190,7 +190,8 @@ extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ struct ioapic_domain_cfg *cfg);
extern void __init pre_init_apic_IRQ0(void);

extern void mp_save_irq(struct mpc_intsrc *m);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index d6635ba..f86b4ba 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -462,7 +462,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
acpi_table_print_madt_entry(header);

mp_register_ioapic(ioapic->id,
- ioapic->address, ioapic->global_irq_base);
+ ioapic->address, ioapic->global_irq_base, NULL);

return 0;
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 51ce80004..563f450 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -85,6 +85,7 @@ int sis_apic_bug = -1;
static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
static DEFINE_MUTEX(ioapic_mutex);
+static unsigned int ioapic_dynirq_base;

static struct ioapic {
/*
@@ -2920,8 +2921,35 @@ out:
*/
#define PIC_IRQS (1UL << PIC_CASCADE_IR)

+static int mp_irqdomain_create(int ioapic)
+{
+ int hwirqs = mp_ioapic_pin_count(ioapic);
+ struct ioapic *ip = &ioapics[ioapic];
+ struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg;
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+ if (cfg->type == IOAPIC_DOMAIN_INVALID)
+ return 0;
+
+ ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops,
+ (void *)(long)ioapic);
+ if(!ip->irqdomain)
+ return -ENOMEM;
+
+ if (cfg->type == IOAPIC_DOMAIN_LEGACY ||
+ cfg->type == IOAPIC_DOMAIN_STRICT)
+ ioapic_dynirq_base = max(ioapic_dynirq_base,
+ gsi_cfg->gsi_end + 1);
+
+ if (gsi_cfg->gsi_base == 0)
+ irq_set_default_host(ip->irqdomain);
+
+ return 0;
+}
+
void __init setup_IO_APIC(void)
{
+ int ioapic;

/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
@@ -2929,6 +2957,9 @@ void __init setup_IO_APIC(void)
io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;

apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+ for_each_ioapic(ioapic)
+ BUG_ON(mp_irqdomain_create(ioapic));
+
/*
* Set up IO-APIC IRQ routing.
*/
@@ -3437,6 +3468,9 @@ unsigned int arch_dynirq_lower_bound(unsigned int from)
{
unsigned int min = gsi_top + nr_legacy_irqs();

+ if (ioapic_dynirq_base)
+ return ioapic_dynirq_base;
+
return from < min ? min : from;
}

@@ -3812,7 +3846,8 @@ static __init int bad_ioapic_register(int idx)
return 0;
}

-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
+void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ struct ioapic_domain_cfg *cfg)
{
int idx = 0;
int entries;
@@ -3826,6 +3861,11 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
ioapics[idx].mp_config.type = MP_IOAPIC;
ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
ioapics[idx].mp_config.apicaddr = address;
+ ioapics[idx].irqdomain = NULL;
+ if (cfg)
+ ioapics[idx].irqdomain_cfg = *cfg;
+ else
+ ioapics[idx].irqdomain_cfg.type = IOAPIC_DOMAIN_INVALID;

set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index b468005..d2c53fe 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -177,7 +177,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
dn->full_name);
return;
}
- mp_register_ioapic(++ioapic_id, r.start, gsi_top);
+ mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL);
}

static void __init dtb_ioapic_setup(void)
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index b10e113..ea8595e 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -115,7 +115,7 @@ static void __init MP_bus_info(struct mpc_bus *m)
static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
if (m->flags & MPC_APIC_USABLE)
- mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, NULL);
}

static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index bcd1a70..8f2f789 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -82,7 +82,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table)
pentry = (struct sfi_apic_table_entry *)sb->pentry;

for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_top);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_top, NULL);
pentry++;
}

Subject: [tip:x86/apic] x86, ACPI, irq: Provide basic irqdomain support

Commit-ID: ca7e28aa4ff34fdd6622d915682b2765453c5ddd
Gitweb: http://git.kernel.org/tip/ca7e28aa4ff34fdd6622d915682b2765453c5ddd
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:19:54 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:42 +0200

x86, ACPI, irq: Provide basic irqdomain support

Enhance ACPI driver to provide basic irqdomain support for IOAPIC.

We will build identity mapping for IOAPICs hosting legacy IRQs,
otherwise dynamically allocate IRQ numbers for IOAPIC pins on demand.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Pavel Machek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index f86b4ba..8d9aee1 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
#include <linux/ioport.h>
@@ -449,10 +450,16 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
return irq;
}

+static struct irq_domain_ops acpi_irqdomain_ops;
+
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
{
struct acpi_madt_io_apic *ioapic = NULL;
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_DYNAMIC,
+ .ops = &acpi_irqdomain_ops,
+ };

ioapic = (struct acpi_madt_io_apic *)header;

@@ -461,8 +468,12 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)

acpi_table_print_madt_entry(header);

- mp_register_ioapic(ioapic->id,
- ioapic->address, ioapic->global_irq_base, NULL);
+ /* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */
+ if (ioapic->global_irq_base < nr_legacy_irqs())
+ cfg.type = IOAPIC_DOMAIN_LEGACY;
+
+ mp_register_ioapic(ioapic->id, ioapic->address, ioapic->global_irq_base,
+ &cfg);

return 0;
}

Subject: [tip:x86/apic] x86, irq, SFI: Release IOAPIC pin when PCI device is disabled

Commit-ID: 8a3e533df17f821a4d25dd2969d2f90d7c168b46
Gitweb: http://git.kernel.org/tip/8a3e533df17f821a4d25dd2969d2f90d7c168b46
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:09 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

x86, irq, SFI: Release IOAPIC pin when PCI device is disabled

Release IOAPIC pin associated with PCI device when the PCI device
is disabled.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/pci/intel_mid_pci.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 337d165..09fece3 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -227,6 +227,12 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
return 0;
}

+static void intel_mid_pci_irq_disable(struct pci_dev *dev)
+{
+ if (dev->irq > 0)
+ mp_unmap_irq(dev->irq);
+}
+
struct pci_ops intel_mid_pci_ops = {
.read = pci_read,
.write = pci_write,
@@ -243,6 +249,7 @@ int __init intel_mid_pci_init(void)
pr_info("Intel MID platform detected, using MID PCI ops\n");
pci_mmcfg_late_init();
pcibios_enable_irq = intel_mid_pci_irq_enable;
+ pcibios_disable_irq = intel_mid_pci_irq_disable;
pci_root_ops = intel_mid_pci_ops;
pci_soc_mode = 1;
/* Continue with standard init */

Subject: [tip:x86/apic] x86, irq: Introduce helper functions to release IOAPIC pin

Commit-ID: df334bead7e94772c41745af9f329383067d44ae
Gitweb: http://git.kernel.org/tip/df334bead7e94772c41745af9f329383067d44ae
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 9 Jun 2014 16:20:06 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Sat, 21 Jun 2014 23:05:44 +0200

x86, irq: Introduce helper functions to release IOAPIC pin

Introduce function mp_unmap_irq() to release IOAPIC IRQ when IRQ is not
used any more, which will typically called by pcibios_disabled_irq.

And function mp_irqdomain_unmap() is a common implementation of
irq_domain_ops.unmap for IOAPIC.

Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Paul Gortmaker <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
arch/x86/include/asm/io_apic.h | 3 +++
arch/x86/kernel/apic/io_apic.c | 61 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index af6f9d4..0aeed5c 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -187,10 +187,12 @@ extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern u32 mp_pin_to_gsi(int ioapic, int pin);
extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
+extern void mp_unmap_irq(int irq);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
struct ioapic_domain_cfg *cfg);
extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
irq_hw_number_t hwirq);
+extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
extern void __init pre_init_apic_IRQ0(void);

@@ -234,6 +236,7 @@ static inline void ioapic_insert_resources(void) { }
static inline int mp_find_ioapic(u32 gsi) { return 0; }
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
+static inline void mp_unmap_irq(int irq) { }

static inline int save_ioapic_entries(void)
{
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 8485d90..8d80a8f 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -467,6 +467,21 @@ static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pi
return 0;
}

+static void __remove_pin_from_irq(struct irq_cfg *cfg, int apic, int pin)
+{
+ struct irq_pin_list **last, *entry;
+
+ last = &cfg->irq_2_pin;
+ for_each_irq_pin(entry, cfg->irq_2_pin)
+ if (entry->apic == apic && entry->pin == pin) {
+ *last = entry->next;
+ kfree(entry);
+ return;
+ } else {
+ last = &entry->next;
+ }
+}
+
static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
{
if (__add_pin_to_irq_node(cfg, node, apic, pin))
@@ -1119,6 +1134,31 @@ int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
}

+void mp_unmap_irq(int irq)
+{
+ struct irq_data *data = irq_get_irq_data(irq);
+ struct mp_pin_info *info;
+ int ioapic, pin;
+
+ if (!data || !data->domain)
+ return;
+
+ ioapic = (int)(long)data->domain->host_data;
+ pin = (int)data->hwirq;
+ info = mp_pin_info(ioapic, pin);
+
+ mutex_lock(&ioapic_mutex);
+ if (--info->count == 0) {
+ info->set = 0;
+ if (irq < nr_legacy_irqs() &&
+ ioapics[ioapic].irqdomain_cfg.type == IOAPIC_DOMAIN_LEGACY)
+ mp_irqdomain_unmap(data->domain, irq);
+ else
+ irq_dispose_mapping(irq);
+ }
+ mutex_unlock(&ioapic_mutex);
+}
+
/*
* Find a specific PCI IRQ entry.
* Not an __init, possibly needed by modules
@@ -3878,6 +3918,27 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
return io_apic_setup_irq_pin(virq, info->node, &attr);
}

+void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq)
+{
+ struct irq_data *data = irq_get_irq_data(virq);
+ struct irq_cfg *cfg = irq_cfg(virq);
+ int ioapic = (int)(long)domain->host_data;
+ int pin = (int)data->hwirq;
+
+ /*
+ * 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, virq))
+ return;
+
+ ioapic_mask_entry(ioapic, pin);
+ __remove_pin_from_irq(cfg, ioapic, pin);
+ WARN_ON(cfg->irq_2_pin != NULL);
+ arch_teardown_hwirq(virq);
+}
+
int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
{
int ret = 0;

2014-06-22 08:42:40

by Ingo Molnar

[permalink] [raw]
Subject: Re: [Patch V4 00/42] use irqdomain to dynamically allocate IRQ for IOAPIC


JFYI, with these patches applied x86 allyes32config fails with:

arch/x86/platform/intel-mid/device_libs/platform_wdt.c:45:3: error: implicit declaration of function ‘io_apic_set_pci_routing’

Thanks,

Ingo

2014-06-22 14:42:21

by Feng Tang

[permalink] [raw]
Subject: Re: [Patch V4 00/42] use irqdomain to dynamically allocate IRQ for IOAPIC

Hi,

On Sun, Jun 22, 2014 at 04:42:27PM +0800, Ingo Molnar wrote:
>
> JFYI, with these patches applied x86 allyes32config fails with:
>
> arch/x86/platform/intel-mid/device_libs/platform_wdt.c:45:3: error: implicit declaration of function ‘io_apic_set_pci_routing’

In some intel-mid platforms (Medfield/Merrifield etc), the IOAPIC
may have more than 80 pins, and some devices like a i2c based touch
screen has its interrupt line directly connected to IOAPIC (this
platform_wdt.c here should be the same case).

Since these devices are not PCI device or ACPI device, they can't
use the general PCI/ACPI xxx_enable_dev APIs which implicitly set
up the ioapic entry, but use this "io_apic_set_pci_routing"
directly.

Thanks,
Feng

>
> Thanks,
>
> Ingo
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-06-22 15:04:36

by Feng Tang

[permalink] [raw]
Subject: Re: [Patch V4 00/42] use irqdomain to dynamically allocate IRQ for IOAPIC

On Sun, Jun 22, 2014 at 10:39:46PM +0800, Feng Tang wrote:
> Hi,
>
> On Sun, Jun 22, 2014 at 04:42:27PM +0800, Ingo Molnar wrote:
> >
> > JFYI, with these patches applied x86 allyes32config fails with:
> >
> > arch/x86/platform/intel-mid/device_libs/platform_wdt.c:45:3: error: implicit declaration of function ‘io_apic_set_pci_routing’
>
> In some intel-mid platforms (Medfield/Merrifield etc), the IOAPIC
> may have more than 80 pins, and some devices like a i2c based touch
> screen has its interrupt line directly connected to IOAPIC (this
> platform_wdt.c here should be the same case).
>
> Since these devices are not PCI device or ACPI device, they can't
> use the general PCI/ACPI xxx_enable_dev APIs which implicitly set
> up the ioapic entry, but use this "io_apic_set_pci_routing"
> directly.

Just quickly read Jiang's patch set, guess these driver should be ok
by using Jiang's new cleaner API "mp_set_gsi_attr()" to replace these
io_apic_set_pci_routing().

Thanks,
Feng

2014-06-23 02:27:56

by Jiang Liu

[permalink] [raw]
Subject: [Patch] x86: intel-mid: fix conflicts between 78a3bb9e408b and 9f354b0252b8

Commit 9f354b0252b8 "x86, irq: Clean up unused IOAPIC interface" kills
interface io_apic_set_pci_routing(), so change arch/x86/platform/
intel-mid/device_libs/platform_wdt.c to use new interfaces.

Due to hardware resource restriction, this patch only passes compilation
without functional tests.

Signed-off-by: Jiang Liu <[email protected]>
---
.../platform/intel-mid/device_libs/platform_wdt.c | 22 ++++++--------------
1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
index 973cf3bfa9fd..0b283d4d0ad7 100644
--- a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
+++ b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
@@ -26,28 +26,18 @@ static struct platform_device wdt_dev = {

static int tangier_probe(struct platform_device *pdev)
{
- int ioapic;
- int irq;
+ int gsi;
struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
- struct io_apic_irq_attr irq_attr = { 0 };

if (!pdata)
return -EINVAL;

- irq = pdata->irq;
- ioapic = mp_find_ioapic(irq);
- if (ioapic >= 0) {
- int ret;
- irq_attr.ioapic = ioapic;
- irq_attr.ioapic_pin = irq;
- irq_attr.trigger = 1;
- /* irq_attr.polarity = 0; -> Active high */
- ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
- if (ret)
- return ret;
- } else {
+ /* IOAPIC builds identity mapping between GSI and IRQ on MID */
+ gsi = pdata->irq;
+ if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
+ mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
- irq);
+ gsi);
return -EINVAL;
}

--
1.7.10.4

2014-06-23 17:40:46

by David Cohen

[permalink] [raw]
Subject: Re: [Patch] x86: intel-mid: fix conflicts between 78a3bb9e408b and 9f354b0252b8

Hi Jiang,

On Mon, Jun 23, 2014 at 10:30:35AM +0800, Jiang Liu wrote:
> Commit 9f354b0252b8 "x86, irq: Clean up unused IOAPIC interface" kills
> interface io_apic_set_pci_routing(), so change arch/x86/platform/
> intel-mid/device_libs/platform_wdt.c to use new interfaces.
>
> Due to hardware resource restriction, this patch only passes compilation
> without functional tests.

I'll test this patch.

BR, David

>
> Signed-off-by: Jiang Liu <[email protected]>
> ---
> .../platform/intel-mid/device_libs/platform_wdt.c | 22 ++++++--------------
> 1 file changed, 6 insertions(+), 16 deletions(-)
>
> diff --git a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
> index 973cf3bfa9fd..0b283d4d0ad7 100644
> --- a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
> +++ b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
> @@ -26,28 +26,18 @@ static struct platform_device wdt_dev = {
>
> static int tangier_probe(struct platform_device *pdev)
> {
> - int ioapic;
> - int irq;
> + int gsi;
> struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
> - struct io_apic_irq_attr irq_attr = { 0 };
>
> if (!pdata)
> return -EINVAL;
>
> - irq = pdata->irq;
> - ioapic = mp_find_ioapic(irq);
> - if (ioapic >= 0) {
> - int ret;
> - irq_attr.ioapic = ioapic;
> - irq_attr.ioapic_pin = irq;
> - irq_attr.trigger = 1;
> - /* irq_attr.polarity = 0; -> Active high */
> - ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
> - if (ret)
> - return ret;
> - } else {
> + /* IOAPIC builds identity mapping between GSI and IRQ on MID */
> + gsi = pdata->irq;
> + if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
> + mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
> dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
> - irq);
> + gsi);
> return -EINVAL;
> }
>
> --
> 1.7.10.4
>

2014-06-26 19:34:56

by David Cohen

[permalink] [raw]
Subject: Re: [Patch] x86: intel-mid: fix conflicts between 78a3bb9e408b and 9f354b0252b8

On Mon, Jun 23, 2014 at 10:38:07AM -0700, David Cohen wrote:
> Hi Jiang,
>
> On Mon, Jun 23, 2014 at 10:30:35AM +0800, Jiang Liu wrote:
> > Commit 9f354b0252b8 "x86, irq: Clean up unused IOAPIC interface" kills
> > interface io_apic_set_pci_routing(), so change arch/x86/platform/
> > intel-mid/device_libs/platform_wdt.c to use new interfaces.
> >
> > Due to hardware resource restriction, this patch only passes compilation
> > without functional tests.
>
> I'll test this patch.

It sounds good.
Acked-by: David Cohen <[email protected]>

>
> BR, David
>
> >
> > Signed-off-by: Jiang Liu <[email protected]>
> > ---
> > .../platform/intel-mid/device_libs/platform_wdt.c | 22 ++++++--------------
> > 1 file changed, 6 insertions(+), 16 deletions(-)
> >
> > diff --git a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
> > index 973cf3bfa9fd..0b283d4d0ad7 100644
> > --- a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
> > +++ b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
> > @@ -26,28 +26,18 @@ static struct platform_device wdt_dev = {
> >
> > static int tangier_probe(struct platform_device *pdev)
> > {
> > - int ioapic;
> > - int irq;
> > + int gsi;
> > struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
> > - struct io_apic_irq_attr irq_attr = { 0 };
> >
> > if (!pdata)
> > return -EINVAL;
> >
> > - irq = pdata->irq;
> > - ioapic = mp_find_ioapic(irq);
> > - if (ioapic >= 0) {
> > - int ret;
> > - irq_attr.ioapic = ioapic;
> > - irq_attr.ioapic_pin = irq;
> > - irq_attr.trigger = 1;
> > - /* irq_attr.polarity = 0; -> Active high */
> > - ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
> > - if (ret)
> > - return ret;
> > - } else {
> > + /* IOAPIC builds identity mapping between GSI and IRQ on MID */
> > + gsi = pdata->irq;
> > + if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
> > + mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
> > dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
> > - irq);
> > + gsi);
> > return -EINVAL;
> > }
> >
> > --
> > 1.7.10.4
> >

2014-06-27 00:38:00

by Jiang Liu

[permalink] [raw]
Subject: Re: [Patch] x86: intel-mid: fix conflicts between 78a3bb9e408b and 9f354b0252b8

Thanks, David!

On 2014/6/27 3:33, David Cohen wrote:
> On Mon, Jun 23, 2014 at 10:38:07AM -0700, David Cohen wrote:
>> Hi Jiang,
>>
>> On Mon, Jun 23, 2014 at 10:30:35AM +0800, Jiang Liu wrote:
>>> Commit 9f354b0252b8 "x86, irq: Clean up unused IOAPIC interface" kills
>>> interface io_apic_set_pci_routing(), so change arch/x86/platform/
>>> intel-mid/device_libs/platform_wdt.c to use new interfaces.
>>>
>>> Due to hardware resource restriction, this patch only passes compilation
>>> without functional tests.
>>
>> I'll test this patch.
>
> It sounds good.
> Acked-by: David Cohen <[email protected]>
>
>>
>> BR, David
>>
>>>
>>> Signed-off-by: Jiang Liu <[email protected]>
>>> ---
>>> .../platform/intel-mid/device_libs/platform_wdt.c | 22 ++++++--------------
>>> 1 file changed, 6 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
>>> index 973cf3bfa9fd..0b283d4d0ad7 100644
>>> --- a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
>>> +++ b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
>>> @@ -26,28 +26,18 @@ static struct platform_device wdt_dev = {
>>>
>>> static int tangier_probe(struct platform_device *pdev)
>>> {
>>> - int ioapic;
>>> - int irq;
>>> + int gsi;
>>> struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
>>> - struct io_apic_irq_attr irq_attr = { 0 };
>>>
>>> if (!pdata)
>>> return -EINVAL;
>>>
>>> - irq = pdata->irq;
>>> - ioapic = mp_find_ioapic(irq);
>>> - if (ioapic >= 0) {
>>> - int ret;
>>> - irq_attr.ioapic = ioapic;
>>> - irq_attr.ioapic_pin = irq;
>>> - irq_attr.trigger = 1;
>>> - /* irq_attr.polarity = 0; -> Active high */
>>> - ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
>>> - if (ret)
>>> - return ret;
>>> - } else {
>>> + /* IOAPIC builds identity mapping between GSI and IRQ on MID */
>>> + gsi = pdata->irq;
>>> + if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
>>> + mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
>>> dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
>>> - irq);
>>> + gsi);
>>> return -EINVAL;
>>> }
>>>
>>> --
>>> 1.7.10.4
>>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>

2014-06-27 03:36:55

by Yinghai Lu

[permalink] [raw]
Subject: Re: [Patch V4 00/42] use irqdomain to dynamically allocate IRQ for IOAPIC

On Sat, Jun 21, 2014 at 2:08 PM, Thomas Gleixner <[email protected]> wrote:
> Jiang,
>
> On Mon, 9 Jun 2014, Jiang Liu wrote:
>
>> On x86 platforms, IRQ number are statically allocated to IOAPIC pins at boot.
>> There are two issues with this design. First it causes trouble to IOAPIC
>> hotplug because we need to allocate a block of IRQ numbers for each IOAPIC.
>> Second it may waste IRQ nubmers even if some IOAPIC pins are not used because
>> IRQ numbers are statically assigned.
>>
>> This patchset tries to enable dynamic IRQ number allocation for IOAPIC
>> by adopting the irqdomain framework, it solves the two issues mentioned
>> above. It also simplifies the IOAPIC driver by consolidating ways to
>> program IOAPIC pins with the irqdomain map interface.
>>
>> We will enhance the IOAPIC driver core to support ACPI based IOAPIC hotplug
>> once the IOAPIC driver has been converted to irqdomain.
>
> I merged the whole lot. Thanks for doing this and reacting on all the
> review comments. Very nice cleanup work!
>

I got following warning on RHEL 7.0 shutdown path.

[58018.128900] ------------[ cut here ]------------
[58018.134081] WARNING: CPU: 21 PID: 1 at fs/proc/generic.c:521
remove_proc_entry+0x150/0x1a0()
[58018.143596] remove_proc_entry: removing non-empty directory
'irq/23', leaking at least 'ehci_hcd:usb2'
[58018.154001] Modules linked in:
[58018.157435] CPU: 21 PID: 1 Comm: systemd-shutdow Tainted: G
W 3.16.0-rc2-yh-00420-g6d62036-dirty #36
[58018.168716] Hardware name: Oracle Corporation ORACLE SERVER
[58018.179703] 0000000000000009 ffff885e759bfb60 ffffffff81f76520
ffff885e759bfba8
[58018.188033] ffff885e759bfb98 ffffffff8109d03d ffff88edf9fb9f00
0000000000000002
[58018.196358] ffff885e759bfc6e ffff88f07b3f4330 ffff88edf9fb9fb9
ffff885e759bfbf8
[58018.204682] Call Trace:
[58018.207432] [<ffffffff81f76520>] dump_stack+0x45/0x56
[58018.213186] [<ffffffff8109d03d>] warn_slowpath_common+0x7d/0xa0
[58018.219903] [<ffffffff8109d0ac>] warn_slowpath_fmt+0x4c/0x50
[58018.226336] [<ffffffff8124b830>] remove_proc_entry+0x150/0x1a0
[58018.232963] [<ffffffff810fdb5f>] unregister_irq_proc+0xbf/0xd0
[58018.239589] [<ffffffff810f7b41>] free_desc+0x31/0xa0
[58018.245240] [<ffffffff810f7c1c>] irq_free_descs+0x6c/0x80
[58018.251375] [<ffffffff810fd2e3>] irq_dispose_mapping+0x53/0x60
[58018.258011] [<ffffffff81083d60>] mp_unmap_irq+0xa0/0xc0
[58018.263960] [<ffffffff8107ac8f>] acpi_unregister_gsi_ioapic+0x2f/0x40
[58018.271263] [<ffffffff8107ab17>] acpi_unregister_gsi+0x17/0x20
[58018.277896] [<ffffffff815a4562>] acpi_pci_irq_disable+0x5e/0x68
[58018.284619] [<ffffffff81e33680>] pcibios_disable_device+0x20/0x30
[58018.291536] [<ffffffff81557222>] do_pci_disable_device+0x52/0x60
[58018.298350] [<ffffffff815572c2>] pci_disable_device+0x92/0xb0
[58018.304876] [<ffffffff81c710bf>] usb_hcd_pci_shutdown+0x3f/0x50
[58018.311593] [<ffffffff81559666>] pci_device_shutdown+0x36/0x70
[58018.318220] [<ffffffff817a4875>] device_shutdown+0x135/0x190
[58018.324651] [<ffffffff810bd935>] kernel_power_off+0x35/0x80
[58018.330980] [<ffffffff810bdc33>] SyS_reboot+0x233/0x260
[58018.336919] [<ffffffff810de239>] ? cpuacct_account_field+0x99/0xb0
[58018.343929] [<ffffffff810de1a5>] ? cpuacct_account_field+0x5/0xb0
[58018.350843] [<ffffffff81f86327>] ? _raw_spin_unlock+0x27/0x30
[58018.357378] [<ffffffff810e3446>] ? trace_hardirqs_on_caller+0x16/0x260
[58018.364774] [<ffffffff810e369d>] ? trace_hardirqs_on+0xd/0x10
[58018.371302] [<ffffffff8105c83c>] ? syscall_trace_enter+0x17c/0x1c0
[58018.378312] [<ffffffff81f870aa>] tracesys+0xd4/0xd9
[58018.383867] ---[ end trace fade991312a6a2d9 ]---
[58018.389026] free irq_desc for 23

Like to suggest attached patch that skip mp_unregister_gsi on shutdown path.

Thanks

Yinghai


Attachments:
free_irq_hcd_pci.patch (636.00 B)
Subject: [tip:x86/apic] x86: intel-mid: Use the new io_apic interfaces

Commit-ID: a4355e6749113d424cd15852c73e22c1ef1bb004
Gitweb: http://git.kernel.org/tip/a4355e6749113d424cd15852c73e22c1ef1bb004
Author: Jiang Liu <[email protected]>
AuthorDate: Mon, 23 Jun 2014 10:30:35 +0800
Committer: Thomas Gleixner <[email protected]>
CommitDate: Mon, 14 Jul 2014 20:17:09 +0200

x86: intel-mid: Use the new io_apic interfaces

Commit 9f354b0252b8 "x86, irq: Clean up unused IOAPIC interface" kills
interface io_apic_set_pci_routing(), so change arch/x86/platform/
intel-mid/device_libs/platform_wdt.c to use new interfaces.

Due to hardware resource restriction, this patch only passes compilation
without functional tests.

Signed-off-by: Jiang Liu <[email protected]>
Acked-by: David Cohen <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Tang Feng <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Tony Luck <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
.../platform/intel-mid/device_libs/platform_wdt.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
index 973cf3b..0b283d4 100644
--- a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
+++ b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
@@ -26,28 +26,18 @@ static struct platform_device wdt_dev = {

static int tangier_probe(struct platform_device *pdev)
{
- int ioapic;
- int irq;
+ int gsi;
struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
- struct io_apic_irq_attr irq_attr = { 0 };

if (!pdata)
return -EINVAL;

- irq = pdata->irq;
- ioapic = mp_find_ioapic(irq);
- if (ioapic >= 0) {
- int ret;
- irq_attr.ioapic = ioapic;
- irq_attr.ioapic_pin = irq;
- irq_attr.trigger = 1;
- /* irq_attr.polarity = 0; -> Active high */
- ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
- if (ret)
- return ret;
- } else {
+ /* IOAPIC builds identity mapping between GSI and IRQ on MID */
+ gsi = pdata->irq;
+ if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
+ mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
- irq);
+ gsi);
return -EINVAL;
}