linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC
@ 2014-05-27  8:07 Jiang Liu
  2014-05-27  8:07 ` [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
                   ` (36 more replies)
  0 siblings, 37 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

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

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

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-16 are trivial code improvements, bugfixes and preparation.

Patch 17-24 enable basic irqdomain support and IRQ number dynamic
allocation.

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

Patch 30-31 cleans up unused interfaces and functions in IOAPIC driver.

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

Tests and comments are warmly welcomed!

Jiang Liu (37):
  x86, irq: update high address field when updating affinity for MSI
    IRQ
  genirq, trivial: improve documentation to match current
    implementation
  x86, mpparse: use pr_lvl() helper utilities to replace
    printk(KERN_LVL)
  x86, mpparse: simplify arch/x86/include/asm/mpspec.h
  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
  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

 Documentation/IRQ-domain.txt      |    3 +-
 arch/x86/Kconfig                  |    1 +
 arch/x86/include/asm/apic.h       |    4 +-
 arch/x86/include/asm/hardirq.h    |    3 -
 arch/x86/include/asm/io_apic.h    |   49 +--
 arch/x86/include/asm/mpspec.h     |   13 -
 arch/x86/include/asm/prom.h       |    2 -
 arch/x86/kernel/acpi/boot.c       |  231 ++++++-------
 arch/x86/kernel/apic/apic.c       |    2 +-
 arch/x86/kernel/apic/io_apic.c    |  681 +++++++++++++++++++++++--------------
 arch/x86/kernel/devicetree.c      |   96 +-----
 arch/x86/kernel/irqinit.c         |    6 -
 arch/x86/kernel/mpparse.c         |   98 +++---
 arch/x86/pci/acpi.c               |    6 +-
 arch/x86/pci/intel_mid_pci.c      |   27 +-
 arch/x86/pci/irq.c                |   15 +-
 arch/x86/platform/intel-mid/sfi.c |   56 ++-
 arch/x86/platform/sfi/sfi.c       |   13 +-
 drivers/acpi/pci_irq.c            |    3 +-
 include/linux/irqdomain.h         |    2 +
 kernel/irq/internals.h            |    2 +-
 kernel/irq/irqdomain.c            |    8 +-
 22 files changed, 715 insertions(+), 606 deletions(-)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:11   ` Thomas Gleixner
  2014-05-27  8:07 ` [Patch V3 02/37] genirq, trivial: improve documentation to match current implementation Jiang Liu
                   ` (35 subsequent siblings)
  36 siblings, 1 reply; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 02/37] genirq, trivial: improve documentation to match current implementation
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
  2014-05-27  8:07 ` [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 03/37] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL) Jiang Liu
                   ` (34 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Jiri Kosina
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi, linux-doc

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 Documentation/IRQ-domain.txt |    3 +--
 kernel/irq/internals.h       |    2 +-
 kernel/irq/irqdomain.c       |    6 +++---
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt
index 03df71aeb38c..8a8b82c9ca53 100644
--- a/Documentation/IRQ-domain.txt
+++ b/Documentation/IRQ-domain.txt
@@ -41,8 +41,7 @@ An interrupt controller driver creates and registers an irq_domain by
 calling one of the irq_domain_add_*() functions (each mapping method
 has a different allocator function, more on that later).  The function
 will return a pointer to the irq_domain on success.  The caller must
-provide the allocator function with an irq_domain_ops structure with
-the .map callback populated as a minimum.
+provide the allocator function with an irq_domain_ops structure.
 
 In most cases, the irq_domain will begin empty without any mappings
 between hwirq and IRQ numbers.  Mappings are added to the irq_domain
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index c4065e3edbc3..099ea2e0eb88 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -33,7 +33,7 @@ enum {
 };
 
 /*
- * Bit masks for desc->state
+ * Bit masks for desc->core_internal_state__do_not_mess_with_it
  *
  * IRQS_AUTODETECT		- autodetection in progress
  * IRQS_SPURIOUS_DISABLED	- was disabled due to spurious interrupt
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index f14033700c25..eb5e10e32e05 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -27,14 +27,14 @@ static struct irq_domain *irq_default_domain;
  * __irq_domain_add() - Allocate a new irq_domain data structure
  * @of_node: optional device-tree node of the interrupt controller
  * @size: Size of linear map; 0 for radix mapping only
+ * @hwirq_max: Maximum number of interrupts supported by controller
  * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no
  *              direct mapping
  * @ops: map/unmap domain callbacks
  * @host_data: Controller private data pointer
  *
- * Allocates and initialize and irq_domain structure.  Caller is expected to
- * register allocated irq_domain with irq_domain_register().  Returns pointer
- * to IRQ domain, or NULL on failure.
+ * Allocates and initialize and irq_domain structure.
+ * Returns pointer to IRQ domain, or NULL on failure.
  */
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 03/37] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL)
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
  2014-05-27  8:07 ` [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
  2014-05-27  8:07 ` [Patch V3 02/37] genirq, trivial: improve documentation to match current implementation Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-06-03  0:41   ` David Rientjes
  2014-05-27  8:07 ` [Patch V3 04/37] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
                   ` (33 subsequent siblings)
  36 siblings, 1 reply; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi

Use pr_lvl() helper utilities to replace printk(KERN_LVL) for readability,
no function changes.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/mpparse.c |   84 +++++++++++++++++++++------------------------
 1 file changed, 39 insertions(+), 45 deletions(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index d2b56489d70f..24da837389b7 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)
@@ -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!\ntype %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,7 +457,7 @@ 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"
+		pr_err("BIOS bug, MP table errors detected!...\n"
 			"... disabling SMP support. (tell your hw vendor)\n");
 		early_iounmap(mpc, size);
 		return -1;
@@ -481,7 +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, "
+		pr_err("BIOS bug, no explicit IRQ entries, "
 		       "using default mptable. (tell your hw vendor)\n");
 
 		bus.type = MP_BUS;
@@ -516,14 +511,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 +534,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 +544,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 +577,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 +729,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 +856,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 +873,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 +886,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 +894,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 04/37] x86, mpparse: simplify arch/x86/include/asm/mpspec.h
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (2 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 03/37] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL) Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
                   ` (32 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Len Brown, Pavel Machek,
	David Rientjes, Seiji Aguchi, Jiang Liu, HATAYAMA Daisuke,
	Paul Gortmaker, Richard Weinberger, Andi Kleen
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, H. Peter Anvin, linux-pm

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) 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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (3 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 04/37] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27 13:50   ` Bjorn Helgaas
  2014-05-27 21:22   ` David Rientjes
  2014-05-27  8:07 ` [Patch V3 06/37] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
                   ` (31 subsequent siblings)
  36 siblings, 2 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 06/37] x86, acpi, irq: kill static function irq_to_gsi()
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (4 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 07/37] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
                   ` (30 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

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 <jiang.liu@linux.intel.com>
---
 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 b41b47021f53..8390db1f7a93 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.
@@ -527,10 +511,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 07/37] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (5 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 06/37] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 08/37] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
                   ` (29 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86,
	Jiri Kosina
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

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 <jiang.liu@linux.intel.com>
---
 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 8390db1f7a93..6d65850f49e9 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -370,11 +370,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);
 
 	/*
@@ -573,14 +568,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;
@@ -819,9 +807,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");
@@ -846,9 +833,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");
@@ -876,11 +862,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 */
@@ -947,7 +932,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;
@@ -1103,9 +1088,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;
@@ -1114,9 +1098,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");
@@ -1135,9 +1118,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 08/37] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (6 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 07/37] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 09/37] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
                   ` (28 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

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 <jiang.liu@linux.intel.com>
---
 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 6d65850f49e9..8b8ff786af12 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;
@@ -553,13 +555,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);
 
@@ -1054,7 +1056,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;
 }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 09/37] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (7 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 08/37] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 10/37] x86, irq, trivial: minor improvements of IRQ related code Jiang Liu
                   ` (27 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

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 <jiang.liu@linux.intel.com>
---
 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 8b8ff786af12..dccf9e88db30 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -508,7 +508,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;
 	}
@@ -913,6 +914,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;
 }
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 10/37] x86, irq, trivial: minor improvements of IRQ related code
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (8 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 09/37] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 11/37] x86, ioapic: kill unused global variable timer_through_8259 Jiang Liu
                   ` (26 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiri Kosina, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/hardirq.h |    3 ---
 arch/x86/include/asm/io_apic.h |   16 +++++++---------
 arch/x86/kernel/apic/io_apic.c |   10 +++++-----
 3 files changed, 12 insertions(+), 17 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..4d7d46650faa 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);
 	}
@@ -3546,7 +3546,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 11/37] x86, ioapic: kill unused global variable timer_through_8259
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (9 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 10/37] x86, irq, trivial: minor improvements of IRQ related code Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 12/37] x86, ioapic: kill static variable nr_irqs_gsi Jiang Liu
                   ` (25 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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 4d7d46650faa..e8dd12a04cea 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2649,8 +2649,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
@@ -2755,7 +2753,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 12/37] x86, ioapic: kill static variable nr_irqs_gsi
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (10 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 11/37] x86, ioapic: kill unused global variable timer_through_8259 Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 13/37] x86, ioapic: introduce helper utilities to walk ioapics and pins Jiang Liu
                   ` (24 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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 <jiang.liu@linux.intel.com>
---
 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 e8dd12a04cea..397fb9a02e11 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
@@ -3333,20 +3330,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)
@@ -3356,12 +3344,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;
@@ -3634,8 +3622,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 13/37] x86, ioapic: introduce helper utilities to walk ioapics and pins
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (11 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 12/37] x86, ioapic: kill static variable nr_irqs_gsi Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 14/37] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability Jiang Liu
                   ` (23 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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 <jiang.liu@linux.intel.com>
---
 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 397fb9a02e11..55fb3c1385c5 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);
@@ -2874,7 +2877,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();
@@ -3464,9 +3467,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);
@@ -3524,8 +3526,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;
@@ -3554,29 +3555,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;
@@ -3590,8 +3595,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
@@ -3636,7 +3641,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++;
 	}
@@ -3644,16 +3649,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;
 	}
 
@@ -3665,7 +3669,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 14/37] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (12 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 13/37] x86, ioapic: introduce helper utilities to walk ioapics and pins Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 15/37] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain Jiang Liu
                   ` (22 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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 55fb3c1385c5..18d0e8a831c0 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;
@@ -2526,7 +2526,7 @@ static inline void init_IO_APIC_traps(void)
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
 	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,
@@ -2659,7 +2659,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;
@@ -2923,7 +2923,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);
@@ -3052,7 +3052,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");
 
@@ -3187,7 +3187,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 15/37] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (13 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 14/37] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 16/37] x86, irq: introduce some helper utilities to improve readability Jiang Liu
                   ` (21 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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 18d0e8a831c0..b14241915262 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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 16/37] x86, irq: introduce some helper utilities to improve readability
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (14 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 15/37] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 17/37] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
                   ` (20 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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 <jiang.liu@linux.intel.com>
---
 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 b14241915262..99acd633287b 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),
@@ -3535,9 +3550,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 17/37] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (15 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 16/37] x86, irq: introduce some helper utilities to improve readability Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 18/37] x86, irq, ACPI: change __acpi_register_gsi to return IRQ number instead of GSI Jiang Liu
                   ` (19 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Len Brown, Pavel Machek,
	Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar, linux-pm

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 <jiang.liu@linux.intel.com>
---
 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 dccf9e88db30..932fdbb5f254 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -99,27 +99,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_IRQS_LEGACY;
-	unsigned int i;
+	int i;
 
-	for (i = 0; i < NR_IRQS_LEGACY; i++) {
-		if (isa_irq_to_gsi[i] == gsi) {
+	for (i = 0; i < NR_IRQS_LEGACY; 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_IRQS_LEGACY)
-		irq = gsi;
-	else
-		irq = gsi_top + gsi;
 
-	return irq;
+	return mp_map_gsi_to_irq(gsi);
 }
 
 /*
@@ -493,16 +481,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);
 
@@ -556,11 +548,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;
 }
@@ -1029,6 +1021,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;
@@ -1041,6 +1034,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);
@@ -1062,7 +1059,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;
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 99acd633287b..cd3a886431b8 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -963,11 +963,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_IRQS_LEGACY ? 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!
@@ -975,17 +983,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_IRQS_LEGACY)
-			irq = gsi;
-		else
-			irq = gsi_top + gsi;
-	}
-
 #ifdef CONFIG_X86_32
 	/*
 	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
@@ -1000,11 +997,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 18/37] x86, irq, ACPI: change __acpi_register_gsi to return IRQ number instead of GSI
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (16 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 17/37] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (18 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

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 <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/acpi/boot.c |   20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 932fdbb5f254..f740d2766c42 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -526,11 +526,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,
@@ -548,13 +550,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);
 
@@ -1036,7 +1032,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) {
@@ -1061,9 +1057,9 @@ 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;
 }
 
 /*
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (17 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 18/37] x86, irq, ACPI: change __acpi_register_gsi to return IRQ number instead of GSI Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27 19:58   ` Thomas Gleixner
  2014-05-27  8:07 ` [Patch V3 20/37] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
                   ` (17 subsequent siblings)
  36 siblings, 1 reply; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Len Brown, Pavel Machek,
	Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar, linux-pm

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 as below:
1) 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.
2) Build identity mapping for GSIs between NR_IRQS_LEGACY and
   arch_dynirq_lower_bound(0). This is typically used to support legacy
   IRQs and simple platforms.
3) Dynamically allocate IRQs for GSIs above arch_dynirq_lower_bound(0).
   This may be used to support big system and IOAPIC hotplug.
4) Dynamically allocate IRQs for non-ISA IRQs below NR_IRQS_LEGACY
   if platform doens't request identity mapping. This is to support
   some really weired platforms.
5) Build identity mapping for GSIs below NR_IRQS_LEGACY if platform requests
   identity mapping. This is to support MID and CE41000 etc.

Function arch_dynirq_lower_bound(0) will be enhanced in coming patch
to enable dynamic IRQ allocation for IOAPIC. To ease our life,
arch_dynirq_lower_bound(0) must be greater than or equal to
NR_IRQS_LEGACY, otherwise it may break backward compatibilities.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/Kconfig               |    1 +
 arch/x86/include/asm/io_apic.h |   11 +++-
 arch/x86/kernel/acpi/boot.c    |    8 +--
 arch/x86/kernel/apic/io_apic.c |  142 ++++++++++++++++++++++++++++++----------
 4 files changed, 120 insertions(+), 42 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 47247708c9eb..ebdb1193821b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -832,6 +832,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..4778d129f225 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
 
@@ -130,6 +132,9 @@ extern int noioapicquirk;
 /* -1 if "noapic" boot option passed */
 extern int noioapicreroute;
 
+/* Build identity mapping for non-ISA IRQs below NR_IRQS_LEGACY */
+extern int ioapic_identity_map;
+
 /*
  * If we use the IO-APIC for IRQ routing, disable automatic
  * assignment of PCI IRQ's.
@@ -169,10 +174,12 @@ struct mp_ioapic_gsi{
 };
 extern u32 gsi_top;
 
+typedef struct irq_domain *(*ioapic_create_domain_fn)(int idx, void *arg);
+
 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 +222,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 f740d2766c42..9bbdd685df64 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -99,7 +99,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;
 
@@ -107,7 +107,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);
 }
 
 /*
@@ -483,7 +483,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
@@ -1030,7 +1030,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;
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index cd3a886431b8..b16e74133686 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,9 @@ static struct ioapic {
 	struct mpc_ioapic mp_config;
 	/* IO APIC gsi routing info */
 	struct mp_ioapic_gsi  gsi_config;
+	struct irq_domain *irqdomain;
+	ioapic_create_domain_fn irqdomain_cb;
+	void *irqdomain_arg;
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } ioapics[MAX_IO_APICS];
 
@@ -135,6 +140,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
 	return ioapic == 0 || (irq >= 0 && irq < NR_IRQS_LEGACY);
 }
 
+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 */
@@ -153,6 +163,7 @@ int mp_bus_id_to_type[MAX_MP_BUSSES];
 DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 
 int skip_ioapic_setup;
+int ioapic_identity_map;
 
 /**
  * disable_ioapic_support() - disables ioapic support at runtime
@@ -963,19 +974,75 @@ 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;
+
+	if (gsi >= arch_dynirq_lower_bound(0)) {
+		irq = irq_create_mapping(domain, pin);
+	} else if (gsi < NR_IRQS_LEGACY) {
+		if (!ioapic_identity_map)
+			irq = irq_create_mapping(domain, pin);
+		else if (irq_domain_associate(domain, gsi, pin) == 0)
+			irq = gsi;
+	} else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0) {
+		irq = gsi;
+	}
+
+	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.
 	 */
-	return gsi >= NR_IRQS_LEGACY ? 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_IRQS_LEGACY ? 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)
+int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
 {
-	int irq;
-	int bus = mp_irqs[idx].srcbus;
+	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);
+}
+
+static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
+{
+	u32 gsi = mp_pin_to_gsi(ioapic, pin);
 
 	/*
 	 * Debugging check, we are in big trouble if this message pops up!
@@ -993,7 +1060,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);
@@ -1003,12 +1070,7 @@ 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 irq;
+	return  mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
 }
 
 /*
@@ -1018,7 +1080,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",
@@ -1047,30 +1109,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);
 
@@ -1261,7 +1330,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);
 	}
 	/*
@@ -1387,8 +1456,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;
 
 		/*
@@ -1438,8 +1508,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),
@@ -3554,8 +3624,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 20/37] x86, irq: enhance mp_register_ioapic() to support irqdomain
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (18 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 21/37] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
                   ` (16 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Len Brown, Pavel Machek,
	Jiang Liu, Rob Herring, Michal Simek, Tony Lindgren
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar, linux-pm, sfi-devel

Add extra arguments to function mp_register_ioapic() to support
irqdomain. When registering IOAPIC, caller may provide a callback
and corresponding argument to create irqdomain for this IOAPIC.
The callback will be called later when initializing IOAPIC subsystem.

We also provide a common implementation mp_create_irqdomain()
to create irqdomain for IOAPICs, which may be used by platform drivers.

Global variable ioapic_dynirq_base is provided for platform drivers
to override return value of arch_dynirq_lower_bound(), thus enable
or disable dynamic IRQ allocation for IOAPIC.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/io_apic.h |   10 ++++++++-
 arch/x86/kernel/acpi/boot.c    |    3 ++-
 arch/x86/kernel/apic/io_apic.c |   48 ++++++++++++++++++++++++++++++++++++++--
 arch/x86/kernel/devicetree.c   |    2 +-
 arch/x86/kernel/mpparse.c      |    2 +-
 arch/x86/platform/sfi/sfi.c    |    2 +-
 6 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 4778d129f225..8837074dfd64 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -135,6 +135,9 @@ extern int noioapicreroute;
 /* Build identity mapping for non-ISA IRQs below NR_IRQS_LEGACY */
 extern int ioapic_identity_map;
 
+/* Build identity mapping for GSIs below it */
+extern int ioapic_dynirq_base;
+
 /*
  * If we use the IO-APIC for IRQ routing, disable automatic
  * assignment of PCI IRQ's.
@@ -174,13 +177,18 @@ struct mp_ioapic_gsi{
 };
 extern u32 gsi_top;
 
+struct device_node;
+struct irq_domain_ops;
 typedef struct irq_domain *(*ioapic_create_domain_fn)(int idx, void *arg);
 
 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,
+				      ioapic_create_domain_fn cb, void *arg);
+extern struct irq_domain *mp_irqdomain_create(int ioapic,
+		struct device_node *np, const struct irq_domain_ops *ops);
 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 9bbdd685df64..9525498e41d5 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -337,7 +337,8 @@ 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, NULL);
 
 	return 0;
 }
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index b16e74133686..86c0497257c4 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -165,6 +165,15 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 int skip_ioapic_setup;
 int ioapic_identity_map;
 
+/*
+ * If not zero:
+ * . build identity mapping for GSIs below it.
+ * . must be bigger than or equal to max(NR_IRQS_LEGACY, pins_on_ioapic0).
+ * If zero:
+ * . build identity mapping for all GSIs
+ */
+int ioapic_dynirq_base;
+
 /**
  * disable_ioapic_support() - disables ioapic support at runtime
  */
@@ -2917,15 +2926,28 @@ out:
  */
 #define PIC_IRQS	(1UL << PIC_CASCADE_IR)
 
-void __init setup_IO_APIC(void)
+static void ioapic_create_irqdomains(void)
 {
+	int i;
+	struct ioapic *ip;
 
+	for_each_ioapic(i) {
+		ip = &ioapics[i];
+		if (ip->irqdomain_cb)
+			ip->irqdomain = ip->irqdomain_cb(i, ip->irqdomain_arg);
+	}
+}
+
+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;
 
 	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+	ioapic_create_irqdomains();
+
 	/*
          * Set up IO-APIC IRQ routing.
          */
@@ -3430,6 +3452,9 @@ unsigned int arch_dynirq_lower_bound(unsigned int from)
 {
 	unsigned int min = gsi_top + NR_IRQS_LEGACY;
 
+	if (ioapic_dynirq_base)
+		return ioapic_dynirq_base;
+
 	return from < min ? min : from;
 }
 
@@ -3805,7 +3830,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,
+			       ioapic_create_domain_fn cb, void *arg)
 {
 	int idx = 0;
 	int entries;
@@ -3819,6 +3845,9 @@ 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_cb = cb;
+	ioapics[idx].irqdomain_arg = arg;
+	ioapics[idx].irqdomain = NULL;
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
 
@@ -3855,6 +3884,21 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
 	nr_ioapics++;
 }
 
+struct irq_domain *mp_irqdomain_create(int ioapic, struct device_node *np,
+				       const struct irq_domain_ops *ops)
+{
+	struct irq_domain *domain;
+	struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+	int hwirqs = mp_ioapic_pin_count(ioapic);
+
+	domain = irq_domain_add_linear(np, hwirqs, ops, (void *)(long)ioapic);
+	BUG_ON(!domain);
+	if (gsi_cfg->gsi_base == 0)
+		irq_set_default_host(domain);
+
+	return domain;
+}
+
 /* Enable IOAPIC early just for system timer */
 void __init pre_init_apic_IRQ0(void)
 {
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index d35078ea1446..1ab002c045c9 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -176,7 +176,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, NULL);
 }
 
 static void __init dtb_ioapic_setup(void)
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 24da837389b7..6cb9a43ecde1 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, 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..3bd7cf642680 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, NULL);
 		pentry++;
 	}
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 21/37] x86, ACPI, irq: provide basic irqdomain support
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (19 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 20/37] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 22/37] x86, mpparse, " Jiang Liu
                   ` (15 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

Enhance ACPI driver to provide basic irqdomain support for IOAPIC.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/acpi/boot.c |   20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 9525498e41d5..0632622a3798 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>
@@ -324,6 +325,23 @@ static void  mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
 static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 			   int polarity);
 
+static struct irq_domain_ops acpi_irqdomain_ops;
+
+static struct irq_domain *acpi_create_irqdomain(int idx, void *arg)
+{
+	struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(idx);
+
+	/*
+	 * Statically allocate IRQ number for legacy IRQs and all pins on the
+	 * first IOAPIC.
+	 */
+	if (gsi_cfg->gsi_base < NR_IRQS_LEGACY &&
+	    ioapic_dynirq_base < gsi_cfg->gsi_end)
+		ioapic_dynirq_base = gsi_cfg->gsi_end + 1;
+
+	return mp_irqdomain_create(idx, NULL, &acpi_irqdomain_ops);
+}
+
 static int __init
 acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
 {
@@ -338,7 +356,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
 
 	mp_register_ioapic(ioapic->id,
 			   ioapic->address, ioapic->global_irq_base,
-			   NULL, NULL);
+			   acpi_create_irqdomain, NULL);
 
 	return 0;
 }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 22/37] x86, mpparse, irq: provide basic irqdomain support
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (20 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 21/37] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 23/37] x86, SFI, " Jiang Liu
                   ` (14 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/mpparse.c |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 6cb9a43ecde1..b9823bea332a 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,18 @@ 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 *mp_ioapic_create_irqdomain(int ioapic, void *arg)
+{
+	return mp_irqdomain_create(ioapic, NULL, &mp_ioapic_irqdomain_ops);
+}
+
 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, NULL, NULL);
+		mp_register_ioapic(m->apicid, m->apicaddr, gsi_top,
+				   mp_ioapic_create_irqdomain, NULL);
 }
 
 static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 23/37] x86, SFI, irq: provide basic irqdomain support
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (21 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 22/37] x86, mpparse, " Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:07 ` [Patch V3 24/37] x86, devicetree, irq: use common mechanism to support irqdomain Jiang Liu
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Len Brown, David Cohen,
	Kuppuswamy Sathyanarayanan, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, H. Peter Anvin, sfi-devel

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/pci/intel_mid_pci.c      |    3 +++
 arch/x86/platform/intel-mid/sfi.c |    2 ++
 arch/x86/platform/sfi/sfi.c       |   11 ++++++++++-
 3 files changed, 15 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 3bd7cf642680..cda31be8dbe5 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,6 +71,13 @@ 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 *sfi_ioapic_create_irqdomain(int ioapic, void *arg)
+{
+	ioapic_identity_map = 1;
+	return mp_irqdomain_create(ioapic, NULL, &sfi_ioapic_irqdomain_ops);
+}
 
 static int __init sfi_parse_ioapic(struct sfi_table_header *table)
 {
@@ -82,7 +90,8 @@ 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, NULL, NULL);
+		mp_register_ioapic(i, pentry->phys_addr, gsi_top,
+				   sfi_ioapic_create_irqdomain, NULL);
 		pentry++;
 	}
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 24/37] x86, devicetree, irq: use common mechanism to support irqdomain
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (22 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 23/37] x86, SFI, " Jiang Liu
@ 2014-05-27  8:07 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 25/37] x86, irq: introduce two helper functions to support irqdomain map operation Jiang Liu
                   ` (12 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Rob Herring, Michal Simek,
	Jiang Liu, Tony Lindgren
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/prom.h  |    2 --
 arch/x86/kernel/devicetree.c |   81 +++++-------------------------------------
 arch/x86/kernel/irqinit.c    |    6 ----
 3 files changed, 8 insertions(+), 81 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 1ab002c045c9..e2270343d3f0 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -164,6 +164,7 @@ static void __init dtb_lapic_setup(void)
 
 #ifdef CONFIG_X86_IO_APIC
 static unsigned int ioapic_id;
+static struct irq_domain *dt_add_ioapic_domain(int ioapic_num, void *arg);
 
 static void __init dtb_add_ioapic(struct device_node *dn)
 {
@@ -176,7 +177,8 @@ static void __init dtb_add_ioapic(struct device_node *dn)
 				dn->full_name);
 		return;
 	}
-	mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL, NULL);
+	mp_register_ioapic(++ioapic_id, r.start, gsi_top,
+			   dt_add_ioapic_domain, dn);
 }
 
 static void __init dtb_ioapic_setup(void)
@@ -293,7 +295,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),
@@ -310,78 +312,11 @@ 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 struct irq_domain *dt_add_ioapic_domain(int ioapic, void *arg)
 {
-	struct irq_domain *id;
-	struct mp_ioapic_gsi *gsi_cfg;
-	int ret;
-	int num;
-
-	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_IRQS_LEGACY 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);
-
-		if (num > NR_IRQS_LEGACY) {
-			ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
-					NR_IRQS_LEGACY, num - NR_IRQS_LEGACY);
-			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);
-	}
-}
-
-static void __init ioapic_add_ofnode(struct device_node *np)
-{
-	struct resource r;
-	int i, ret;
+	struct device_node *np = arg;
 
-	ret = of_address_to_resource(np, 0, &r);
-	if (ret) {
-		printk(KERN_ERR "Failed to obtain address for %s\n",
-				np->full_name);
-		return;
-	}
-
-	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);
-}
-
-void __init x86_add_irq_domains(void)
-{
-	struct device_node *dp;
-
-	if (!of_have_populated_dt())
-		return;
-
-	for_each_node_with_property(dp, "interrupt-controller") {
-		if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
-			ioapic_add_ofnode(dp);
-	}
+	ioapic_identity_map = 1;
+	return mp_irqdomain_create(ioapic, np, &ioapic_irq_domain_ops);
 }
-#else
-void __init x86_add_irq_domains(void) { }
 #endif
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 7f50156542fb..a9c0066762e5 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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 25/37] x86, irq: introduce two helper functions to support irqdomain map operation
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (23 preceding siblings ...)
  2014-05-27  8:07 ` [Patch V3 24/37] x86, devicetree, irq: use common mechanism to support irqdomain Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 26/37] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
                   ` (11 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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 <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/io_apic.h |    3 ++
 arch/x86/kernel/apic/io_apic.c |   93 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 8837074dfd64..6d7a856ae045 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -189,6 +189,9 @@ extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
 				      ioapic_create_domain_fn cb, void *arg);
 extern struct irq_domain *mp_irqdomain_create(int ioapic,
 		struct device_node *np, const struct irq_domain_ops *ops);
+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 86c0497257c4..6bb3485693dc 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -86,6 +86,14 @@ static DEFINE_RAW_SPINLOCK(ioapic_lock);
 static DEFINE_RAW_SPINLOCK(vector_lock);
 static DEFINE_MUTEX(ioapic_mutex);
 
+struct mp_pin_info {
+	int trigger;
+	int polarity;
+	int node;
+	int set;
+	u32 count;
+};
+
 static struct ioapic {
 	/*
 	 * # of IRQ routing registers
@@ -99,6 +107,7 @@ static struct ioapic {
 	struct mpc_ioapic mp_config;
 	/* IO APIC gsi routing info */
 	struct mp_ioapic_gsi  gsi_config;
+	struct mp_pin_info *pin_info;
 	struct irq_domain *irqdomain;
 	ioapic_create_domain_fn irqdomain_cb;
 	void *irqdomain_arg;
@@ -140,6 +149,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
 	return ioapic == 0 || (irq >= 0 && irq < NR_IRQS_LEGACY);
 }
 
+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
@@ -1028,6 +1043,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;
@@ -2928,11 +2950,14 @@ out:
 
 static void ioapic_create_irqdomains(void)
 {
-	int i;
+	int i, size;
 	struct ioapic *ip;
 
 	for_each_ioapic(i) {
 		ip = &ioapics[i];
+		size = sizeof(struct mp_pin_info) * mp_ioapic_pin_count(i);
+		ip->pin_info = kzalloc(size, GFP_KERNEL);
+		BUG_ON(!ip->pin_info);
 		if (ip->irqdomain_cb)
 			ip->irqdomain = ip->irqdomain_cb(i, ip->irqdomain_arg);
 	}
@@ -3899,6 +3924,72 @@ struct irq_domain *mp_irqdomain_create(int ioapic, struct device_node *np,
 	return domain;
 }
 
+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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 26/37] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (24 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 25/37] x86, irq: introduce two helper functions to support irqdomain map operation Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 27/37] x86, irq, mpparse: " Jiang Liu
                   ` (10 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

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 <jiang.liu@linux.intel.com>
---
 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 0632622a3798..4788b3f50f69 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -325,7 +325,9 @@ static void  mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
 static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 			   int polarity);
 
-static struct irq_domain_ops acpi_irqdomain_ops;
+static struct irq_domain_ops acpi_irqdomain_ops = {
+	.map = mp_irqdomain_map,
+};
 
 static struct irq_domain *acpi_create_irqdomain(int idx, void *arg)
 {
@@ -505,10 +507,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;
 	}
@@ -1036,11 +1034,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;
@@ -1049,35 +1043,21 @@ 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;
 }
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 27/37] x86, irq, mpparse: use common irqdomain map interface to program IOAPIC pins
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (25 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 26/37] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 28/37] x86, irq, SFI: " Jiang Liu
                   ` (9 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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 b9823bea332a..55acf55b41e7 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 struct irq_domain *mp_ioapic_create_irqdomain(int ioapic, void *arg)
 {
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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 28/37] x86, irq, SFI: use common irqdomain map interface to program IOAPIC pins
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (26 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 27/37] x86, irq, mpparse: " Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 29/37] x86, irq, devicetree: " Jiang Liu
                   ` (8 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Len Brown, David Cohen,
	Kuppuswamy Sathyanarayanan, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, H. Peter Anvin, sfi-devel

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 <jiang.liu@linux.intel.com>
---
 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 cda31be8dbe5..ed0e131c1202 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 struct irq_domain *sfi_ioapic_create_irqdomain(int ioapic, void *arg)
 {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 29/37] x86, irq, devicetree: use common irqdomain map interface to program IOAPIC pins
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (27 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 28/37] x86, irq, SFI: " Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 30/37] x86, irq: clean up unused IOAPIC interface Jiang Liu
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Rob Herring, Michal Simek,
	Jiang Liu, Tony Lindgren
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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 e2270343d3f0..17535c5bbe65 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -280,10 +280,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;
@@ -296,12 +294,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;
@@ -309,6 +304,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 30/37] x86, irq: clean up unused IOAPIC interface
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (28 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 29/37] x86, irq, devicetree: " Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 31/37] x86, irq: simplify the way to handle ISA IRQ Jiang Liu
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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 <jiang.liu@linux.intel.com>
---
 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 6d7a856ae045..073358c12d90 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -147,9 +147,6 @@ extern int ioapic_dynirq_base;
 
 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 *,
@@ -161,8 +158,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);
@@ -235,10 +230,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 6bb3485693dc..25a2877a5788 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 irq_domain *irqdomain;
 	ioapic_create_domain_fn irqdomain_cb;
 	void *irqdomain_arg;
-	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
@@ -1518,38 +1517,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,
@@ -3436,27 +3403,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;
@@ -3503,22 +3449,6 @@ int __init arch_probe_nr_irqs(void)
 	return NR_IRQS_LEGACY;
 }
 
-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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 31/37] x86, irq: simplify the way to handle ISA IRQ
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (29 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 30/37] x86, irq: clean up unused IOAPIC interface Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 32/37] genirq: export irq_domain_disassociate() to architecture interrupt drivers Jiang Liu
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86,
	Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar, linux-pm

On startup, setup_IO_APIC_irqs() will program all IOAPIC pins for ISA
IRQs. Later when mp_map_pin_to_irq() is called, it just returns ISA IRQ
number without programming corresponding IOAPIC pin.

This patch consolidates the way to program IOAPIC pins for both ISA and
non-ISA IRQs into mp_map_pin_to_irq() as below:
1) For ISA IRQs, mp_irqs array is used to map IOAPIC pin to IRQ and
   mp_irqdomain_map() is used to actually program the pin.
2) For non-ISA IRQs, irqdomain is used to map IOAPIC pin to IRQ, and
   mp_irqdomain_map() is also used to actually program the pin.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/acpi/boot.c    |   15 +------
 arch/x86/kernel/apic/io_apic.c |   88 ++++++++++++----------------------------
 2 files changed, 29 insertions(+), 74 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 4788b3f50f69..0592c38d9952 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -100,17 +100,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_IRQS_LEGACY; 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.
@@ -504,7 +493,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;
@@ -1051,7 +1040,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;
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 25a2877a5788..7fc34fcf3ea3 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -207,9 +207,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);
-
 /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
 void mp_save_irq(struct mpc_intsrc *m)
 {
@@ -1021,34 +1018,35 @@ 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)
+		return -1;
+
+	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
 	 * irqdomain only supports 1:1 mapping between IOAPIC pin and
 	 * IRQ number.
 	 */
-	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_IRQS_LEGACY ? 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) && info->count == 0 &&
+		    mp_irqdomain_map(domain, irq, pin) != 0)
+			irq = -1;
+	} 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;
@@ -1465,55 +1463,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 32/37] genirq: export irq_domain_disassociate() to architecture interrupt drivers
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (30 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 31/37] x86, irq: simplify the way to handle ISA IRQ Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 33/37] x86, irq: introduce helper functions to release IOAPIC pin Jiang Liu
                   ` (4 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 33/37] x86, irq: introduce helper functions to release IOAPIC pin
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (31 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 32/37] genirq: export irq_domain_disassociate() to architecture interrupt drivers Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 34/37] x86, irq, ACPI: release IOAPIC pin when PCI device is disabled Jiang Liu
                   ` (3 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Ingo Molnar

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 <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/io_apic.h |    3 ++
 arch/x86/kernel/apic/io_apic.c |   60 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 073358c12d90..6b40122bec0c 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -180,12 +180,14 @@ 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,
 				      ioapic_create_domain_fn cb, void *arg);
 extern struct irq_domain *mp_irqdomain_create(int ioapic,
 		struct device_node *np, const struct irq_domain_ops *ops);
 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);
 
@@ -229,6 +231,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 7fc34fcf3ea3..c7c84d5c0e57 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -480,6 +480,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))
@@ -1068,6 +1083,30 @@ 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_IRQS_LEGACY)
+			irq_domain_disassociate(data->domain, irq);
+		else
+			irq_dispose_mapping(irq);
+	}
+	mutex_unlock(&ioapic_mutex);
+}
+
 static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
 {
 	u32 gsi = mp_pin_to_gsi(ioapic, pin);
@@ -3857,6 +3896,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 34/37] x86, irq, ACPI: release IOAPIC pin when PCI device is disabled
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (32 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 33/37] x86, irq: introduce helper functions to release IOAPIC pin Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 35/37] x86, irq, mpparse: " Jiang Liu
                   ` (2 subsequent siblings)
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Len Brown, Pavel Machek, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, linux-pm

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/acpi/boot.c |   28 ++++++++++++++++++++++++++++
 drivers/acpi/pci_irq.c      |    3 ++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 0592c38d9952..c8e8fe67bbc8 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -313,9 +313,11 @@ 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 void mp_unregister_gsi(u32 gsi);
 
 static struct irq_domain_ops acpi_irqdomain_ops = {
 	.map = mp_irqdomain_map,
+	.unmap = mp_irqdomain_unmap,
 };
 
 static struct irq_domain *acpi_create_irqdomain(int idx, void *arg)
@@ -541,8 +543,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;
@@ -562,6 +572,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);
 
@@ -569,6 +581,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;
 }
 
@@ -1050,6 +1063,21 @@ 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);
+}
+
 /*
  * Parse IOAPIC related entries in MADT
  * returns 0 on success, < 0 on error
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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 35/37] x86, irq, mpparse: release IOAPIC pin when PCI device is disabled
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (33 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 34/37] x86, irq, ACPI: release IOAPIC pin when PCI device is disabled Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 36/37] x86, irq, SFI: " Jiang Liu
  2014-05-27  8:08 ` [Patch V3 37/37] x86, irq, devicetree: " Jiang Liu
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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 55acf55b41e7..f6559942952d 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 struct irq_domain *mp_ioapic_create_irqdomain(int ioapic, void *arg)
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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 36/37] x86, irq, SFI: release IOAPIC pin when PCI device is disabled
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (34 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 35/37] x86, irq, mpparse: " Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  2014-05-27  8:08 ` [Patch V3 37/37] x86, irq, devicetree: " Jiang Liu
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Patch V3 37/37] x86, irq, devicetree: release IOAPIC pin when PCI device is disabled
  2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (35 preceding siblings ...)
  2014-05-27  8:08 ` [Patch V3 36/37] x86, irq, SFI: " Jiang Liu
@ 2014-05-27  8:08 ` Jiang Liu
  36 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Rob Herring, Michal Simek,
	Jiang Liu, Tony Lindgren
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi

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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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 17535c5bbe65..9beb9f28b5bd 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -305,6 +305,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* Re: [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ
  2014-05-27  8:07 ` [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
@ 2014-05-27  8:11   ` Thomas Gleixner
  2014-05-27  8:50     ` Jiang Liu
  0 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2014-05-27  8:11 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, Ingo Molnar

On Tue, 27 May 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.

That should be tagged for stable, right?
 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>  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
> 
> 

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ
  2014-05-27  8:11   ` Thomas Gleixner
@ 2014-05-27  8:50     ` Jiang Liu
  0 siblings, 0 replies; 52+ messages in thread
From: Jiang Liu @ 2014-05-27  8:50 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, Ingo Molnar

Yes, I think it should be marked for stable branches.

On 2014/5/27 16:11, Thomas Gleixner wrote:
> On Tue, 27 May 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.
> 
> That should be tagged for stable, right?
>  
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> ---
>>  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
>>
>>

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance
  2014-05-27  8:07 ` [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
@ 2014-05-27 13:50   ` Bjorn Helgaas
  2014-05-27 21:22   ` David Rientjes
  1 sibling, 0 replies; 52+ messages in thread
From: Bjorn Helgaas @ 2014-05-27 13:50 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, x86, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi

On Tue, May 27, 2014 at 2:07 AM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
> Use kmalloc_node() instead of kmalloc() when possible to optimize
> for performance on NUMA platforms.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

I think this is micro-optimization, because I don't think these
structures are referenced often.  It might be nicer if we could
arrange to run this path on the local node, as we do in
pci_call_probe(), so all allocs would happen there.  But I'm OK with
this as-is.

> ---
>  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
>

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-27  8:07 ` [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
@ 2014-05-27 19:58   ` Thomas Gleixner
  2014-05-28  5:01     ` Jiang Liu
  2014-05-28  8:01     ` Sebastian Andrzej Siewior
  0 siblings, 2 replies; 52+ messages in thread
From: Thomas Gleixner @ 2014-05-27 19:58 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, linux-pm

Jiang,

On Tue, 27 May 2014, Jiang Liu wrote:

> +static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
>  {
> +	int irq = -1;
> +
> +	if (gsi >= arch_dynirq_lower_bound(0)) {
> +		irq = irq_create_mapping(domain, pin);
> +	} else if (gsi < NR_IRQS_LEGACY) {
> +		if (!ioapic_identity_map)
> +			irq = irq_create_mapping(domain, pin);
> +		else if (irq_domain_associate(domain, gsi, pin) == 0)
> +			irq = gsi;
> +	} else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0) {
> +		irq = gsi;
> +	}

So you have these cases covered here:

1) The ACPI case of secondary ioapics. You only have the strict 1:1
   mapping for the first ioapic

2) The gsi < NR_IRQS_LEGACY case where you have two options:

    a) Let the core create a random virq number if ioapic_identity_map
       is 0

       ioapic_identity_map is only set by SFI and devicetree

       So in all other cases we fall into that code path for all
       legacy interrupts. So how is that supposed to work lets say for
       i8042 which has hardcoded irq 1 and 12?

       irq_create_mapping(1)
       
	    hint = 1 % nr_irqs; --> 1
	    virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node));

	    This returns something >= 16, because the irq descriptors
	    for 0-15 (LEGACY) are allocated already.

       The pin association works, but how is the i8042 driver supposed
       to figure out that it should request the virq >=16 which was
       created instead of the hardcoded 1 ?
	
    b) Associate the gsi and the pin

       This only works because the virqs are already allocated at boot
       time unconditionally due to arch_probe_nr_irqs() returning
       NR_IRQS_LEGACY. So irq_domain_associate() works.
       Undocumented works by chance behaviour.

3) The case where gsi < arch_dynirq_lower_bound()

   You create a strict mapping here, fine.

This is confusing at best.

First of all, we should use legacy_pic->nr_legacy_irqs instead of
NR_IRQS_LEGACY all over the place.

mshyperv, ce4100 and intel-mid use the null_legacy_pic which has
nr_legacy_irqs = 0 and everything else uses the real pic which has
nr_legacy_irqs = NR_IRQS_LEGACY. So why do we even bother to allocate
and deal with NR_IRQS_LEGACY in the cases where we have no legacy?

ce4100 is an oddball though. The ioapic is registered way before the
interrupt subsystem is initialized and I have a hard time to
understand that comment:

        /* We can't set this earlier, because we need to calibrate the timer */
        legacy_pic = &null_legacy_pic;

The timer calibration happens after the interrupts are set up. I
assume it's check_timer() which wants that, but we know exactly how
the ce4100 works, so we might be able to avoid that whole "testing"
stuff. Sebastian, any input on this?

If it turns out that ce4100 needs the inital real legacy pic for some
magic reason we still can be clever by extending the legacy pic data
structure to tell us about that change, i.e. instead of using
legacy_pic->nr_legacy_irqs having a field "nr_allocated_irqs", which
is set to NR_IRQS_LEGACY for the real pic and to 0 for the null_pic
and let ce4100 set that field to NR_IRQS_LEGACY before switching the
legacy_pic over to the null implementation.


But what's really disgusting is the magic ioapic_identity_map and the
extra ACPI specific ioapic_dynirq_base hackery.

Why do we need strict mappings in the non ACPI case for all ioapic
pins? What's so different about ACPI? Or is this just to avoid
breaking the existing SFI/devicetree stuff. If that's the reason I'm
fine with it, but ...

independent of this question we want to be more clever about the
handling of strict, legacy and freely associated linux irq numbers.

So you have this weird ioapic_create_domain_fn callback in
mp_register_ioapic, which is solely there so the different callers can
hand in their domain ops and eventually set the magic
ioapic_identity_map flag.

+void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+                              ioapic_create_domain_fn cb, void *arg)

What about having

struct ioapic_domain {
       struct irqdomain             *domain;
       const struct irq_domain_ops  *ops;
       void                         *arg;
       enum domain_type             type;
};

and add this struct to the ioapic struct. type is:

enum domain_type {
       IOAPIC_STRICT,
       IOAPIC_LEGACY,
       IOAPIC_DYNAMIC,
};     


Now the register function changes to:

void mp_register_ioapic(int id, u32 address, u32 gsi_base,
     			const struct irq_domain_ops *ops,
			int type)
{
	...

        ioapics[idx].irqdomain.ops = ops;
        ioapics[idx].irqdomain.arg = arg;
	ioapics[idx].irqdomain.type = type;
        ioapics[idx].irqdomain.domain = NULL;
	
	...
}

and you can use mp_irqdomain_create() unconditionally for creating all
domains. And there you do:

static int dynirq_lower_bound;

mp_irqdomain_create()
{
       ioapic->irqdomain.domain = irq_domain_add_linear(...);
       
       switch (ioapic->irqdomain.type) {
       case IOAPIC_LEGACY:
       	    /*
	     * Associate the legacy interrupts which have been
	     * already allocated.
	     */
	    for (i = 0; i < legacy_pic->nr_allocated_irqs; i++)
		irq_domain_associate(domain, i, i);

       case IOAPIC_STRICT:
       	    dynirq_lower_bound += ioapic->nr_gsis;

       case IOAPIC_DYNAMIC:
       	    break;
       }
}

So arch_dynirq_lower_bound() gets simplified to:
{
     return dynirq_lower_bound;
}

And alloc_irq_from_domain() becomes:

int alloc_irq_from_domain(struct ioapic_domain *domain, int gsi, int pin)
{
	switch (domain->type) {
	case IOAPIC_DYNAMIC:
	     return irq_create_mapping(domain->domain, pin);
	case IOAPIC_LEGACY:
	case IOAPIC_STRICT:     	    
	     return irq_create_strict_mappings(domain, gsi, pin, 1);
	}
}

At the call site of alloc_irq_from_domain() you have already:

       irq = irq_find_mapping(domain, pin);
       if (irq <=0 ....)
       	       alloc_irq_from_domain(domain, gsi, pin);

So because we associated the legacy_pic->nr_allocated_irqs in
mp_irqdomain_create() already, you'll never call into
alloc_irq_from_domain() for those and the remaining ones for that
first ioapic are handled by the IOAPIC_STRICT fall through.

For simplicity you can let SFI and devicetree register the ioapics
with their specific domain ops plus IOAPIC_LEGACY for the first ioapic
and IOAPIC_STRICT for all others. That also covers the case where the
null_legacy_pic with legacy_pic->nr_allocated_irqs == 0 is used.

In the ACPI case you register with the acpi domain ops and
IOAPIC_LEGACY for the first and IOAPIC_DYNAMIC for the extra ioapics.

Should be way cleaner and understandable, at least to me :)

Now there is that last oddity which bugs me in mp_map_pin_to_irq()

 	/*
	 * 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.
 	 */
	if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
		if ((flags & IOAPIC_MAP_ALLOC) && info->count == 0 &&
		    mp_irqdomain_map(domain, irq, pin) != 0)
			irq = -1;

That really looks like a hack. I'm aware that the current irqdomain
code cannot deal with that oddball case.

So what you are saying is that there are devices which have a separate
physical wire to different ioapic pins, but the ioapic is supposed to
bundle them to a shared interrupt.

I agree that this is odd enough to handle at the ioapic level, but
it'd be nice to have a more elaborative comment on this.

Aside of the above I'm pretty happy about the progress of this patch
set. One thing, which needs to be looked at are the usage sites of
irq_data->irq, whether they are safe. I did not spot any unsafe ones,
but a few functions which are called with irq_data->irq and make no
use of it.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance
  2014-05-27  8:07 ` [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
  2014-05-27 13:50   ` Bjorn Helgaas
@ 2014-05-27 21:22   ` David Rientjes
  1 sibling, 0 replies; 52+ messages in thread
From: David Rientjes @ 2014-05-27 21:22 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi

On Tue, 27 May 2014, Jiang Liu wrote:

> Use kmalloc_node() instead of kmalloc() when possible to optimize
> for performance on NUMA platforms.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>

Acked-by: David Rientjes <rientjes@google.com>

All the handling to make sure sd->node refers to either NUMA_NO_NODE 
(fallback to local allocation) or an online node looks to be handled 
properly.

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-27 19:58   ` Thomas Gleixner
@ 2014-05-28  5:01     ` Jiang Liu
  2014-05-28 21:08       ` Thomas Gleixner
  2014-05-28  8:01     ` Sebastian Andrzej Siewior
  1 sibling, 1 reply; 52+ messages in thread
From: Jiang Liu @ 2014-05-28  5:01 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, linux-pm

Hi Thomas,
	Thanks for your comments. Please refer to inline
comments below.

On 2014/5/28 3:58, Thomas Gleixner wrote:
> Jiang,
> 
> On Tue, 27 May 2014, Jiang Liu wrote:
> 
>> +static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
>>  {
>> +	int irq = -1;
>> +
>> +	if (gsi >= arch_dynirq_lower_bound(0)) {
>> +		irq = irq_create_mapping(domain, pin);
>> +	} else if (gsi < NR_IRQS_LEGACY) {
>> +		if (!ioapic_identity_map)
>> +			irq = irq_create_mapping(domain, pin);
>> +		else if (irq_domain_associate(domain, gsi, pin) == 0)
>> +			irq = gsi;
>> +	} else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0) {
>> +		irq = gsi;
>> +	}
> 
> So you have these cases covered here:
> 
> 1) The ACPI case of secondary ioapics. You only have the strict 1:1
>    mapping for the first ioapic
> 
> 2) The gsi < NR_IRQS_LEGACY case where you have two options:
> 
>     a) Let the core create a random virq number if ioapic_identity_map
>        is 0
> 
>        ioapic_identity_map is only set by SFI and devicetree
> 
>        So in all other cases we fall into that code path for all
>        legacy interrupts. So how is that supposed to work lets say for
>        i8042 which has hardcoded irq 1 and 12?
> 
>        irq_create_mapping(1)
>        
> 	    hint = 1 % nr_irqs; --> 1
> 	    virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node));
> 
> 	    This returns something >= 16, because the irq descriptors
> 	    for 0-15 (LEGACY) are allocated already.
> 
>        The pin association works, but how is the i8042 driver supposed
>        to figure out that it should request the virq >=16 which was
>        created instead of the hardcoded 1 ?
This is used to work around special non-ISA interrupts with GSI below
NR_IRQS_LEGACY. The original code for the special case is:
/*
 * 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_IRQS_LEGACY ? gsi : gsi_top + gsi;

We have one path to handle ISA IRQs before calling
alloc_irq_from_domain() as below:
        if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci))
                return mp_irqs[idx].srcbusirq;

> 	
>     b) Associate the gsi and the pin
> 
>        This only works because the virqs are already allocated at boot
>        time unconditionally due to arch_probe_nr_irqs() returning
>        NR_IRQS_LEGACY. So irq_domain_associate() works.
>        Undocumented works by chance behaviour.
Yes. It's a good suggestion to enhance legacy_pic to make this
code more clear.

> 
> 3) The case where gsi < arch_dynirq_lower_bound()
> 
>    You create a strict mapping here, fine.
> 
> This is confusing at best.
> 
> First of all, we should use legacy_pic->nr_legacy_irqs instead of
> NR_IRQS_LEGACY all over the place.
> 
> mshyperv, ce4100 and intel-mid use the null_legacy_pic which has
> nr_legacy_irqs = 0 and everything else uses the real pic which has
> nr_legacy_irqs = NR_IRQS_LEGACY. So why do we even bother to allocate
> and deal with NR_IRQS_LEGACY in the cases where we have no legacy?
I'm not sure whether it works with ce4100, so used NR_IRQS_LEGACY
instead of legacy_pic->nr_legacy_irqs for safety. Will try to refine
it in next version.

> 
> ce4100 is an oddball though. The ioapic is registered way before the
> interrupt subsystem is initialized and I have a hard time to
> understand that comment:
> 
>         /* We can't set this earlier, because we need to calibrate the timer */
>         legacy_pic = &null_legacy_pic;
I haven't figured out the story behind the comment yet:(

> 
> The timer calibration happens after the interrupts are set up. I
> assume it's check_timer() which wants that, but we know exactly how
> the ce4100 works, so we might be able to avoid that whole "testing"
> stuff. Sebastian, any input on this?
> 
> If it turns out that ce4100 needs the inital real legacy pic for some
> magic reason we still can be clever by extending the legacy pic data
> structure to tell us about that change, i.e. instead of using
> legacy_pic->nr_legacy_irqs having a field "nr_allocated_irqs", which
> is set to NR_IRQS_LEGACY for the real pic and to 0 for the null_pic
> and let ce4100 set that field to NR_IRQS_LEGACY before switching the
> legacy_pic over to the null implementation.
Good suggestion, will try this way.

> But what's really disgusting is the magic ioapic_identity_map and the
> extra ACPI specific ioapic_dynirq_base hackery.
> 
> Why do we need strict mappings in the non ACPI case for all ioapic
> pins? What's so different about ACPI? Or is this just to avoid
> breaking the existing SFI/devicetree stuff. If that's the reason I'm
> fine with it, but ...
It's to avoid breaking SFI/intel_mid stuff. intel_mid assumes IRQ
number equals to pin number and use pci_dev->irq to save both IRQ
number and pin number.

> 
> independent of this question we want to be more clever about the
> handling of strict, legacy and freely associated linux irq numbers.
> 
> So you have this weird ioapic_create_domain_fn callback in
> mp_register_ioapic, which is solely there so the different callers can
> hand in their domain ops and eventually set the magic
> ioapic_identity_map flag.
> 
> +void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
> +                              ioapic_create_domain_fn cb, void *arg)
> 
> What about having
> 
> struct ioapic_domain {
>        struct irqdomain             *domain;
>        const struct irq_domain_ops  *ops;
>        void                         *arg;
>        enum domain_type             type;
> };
> 
> and add this struct to the ioapic struct. type is:
> 
> enum domain_type {
>        IOAPIC_STRICT,
>        IOAPIC_LEGACY,
>        IOAPIC_DYNAMIC,
> };     
> 
> 
> Now the register function changes to:
> 
> void mp_register_ioapic(int id, u32 address, u32 gsi_base,
>      			const struct irq_domain_ops *ops,
> 			int type)
> {
> 	...
> 
>         ioapics[idx].irqdomain.ops = ops;
>         ioapics[idx].irqdomain.arg = arg;
> 	ioapics[idx].irqdomain.type = type;
>         ioapics[idx].irqdomain.domain = NULL;
> 	
> 	...
> }
> 
> and you can use mp_irqdomain_create() unconditionally for creating all
> domains. And there you do:
> 
> static int dynirq_lower_bound;
> 
> mp_irqdomain_create()
> {
>        ioapic->irqdomain.domain = irq_domain_add_linear(...);
>        
>        switch (ioapic->irqdomain.type) {
>        case IOAPIC_LEGACY:
>        	    /*
> 	     * Associate the legacy interrupts which have been
> 	     * already allocated.
> 	     */
> 	    for (i = 0; i < legacy_pic->nr_allocated_irqs; i++)
> 		irq_domain_associate(domain, i, i);
> 
>        case IOAPIC_STRICT:
>        	    dynirq_lower_bound += ioapic->nr_gsis;
> 
>        case IOAPIC_DYNAMIC:
>        	    break;
>        }
> }
> 
> So arch_dynirq_lower_bound() gets simplified to:
> {
>      return dynirq_lower_bound;
> }
> 
> And alloc_irq_from_domain() becomes:
> 
> int alloc_irq_from_domain(struct ioapic_domain *domain, int gsi, int pin)
> {
> 	switch (domain->type) {
> 	case IOAPIC_DYNAMIC:
> 	     return irq_create_mapping(domain->domain, pin);
> 	case IOAPIC_LEGACY:
> 	case IOAPIC_STRICT:     	    
> 	     return irq_create_strict_mappings(domain, gsi, pin, 1);
> 	}
> }
> 
> At the call site of alloc_irq_from_domain() you have already:
> 
>        irq = irq_find_mapping(domain, pin);
>        if (irq <=0 ....)
>        	       alloc_irq_from_domain(domain, gsi, pin);
> 
> So because we associated the legacy_pic->nr_allocated_irqs in
> mp_irqdomain_create() already, you'll never call into
> alloc_irq_from_domain() for those and the remaining ones for that
> first ioapic are handled by the IOAPIC_STRICT fall through.
> 
> For simplicity you can let SFI and devicetree register the ioapics
> with their specific domain ops plus IOAPIC_LEGACY for the first ioapic
> and IOAPIC_STRICT for all others. That also covers the case where the
> null_legacy_pic with legacy_pic->nr_allocated_irqs == 0 is used.
> 
> In the ACPI case you register with the acpi domain ops and
> IOAPIC_LEGACY for the first and IOAPIC_DYNAMIC for the extra ioapics.
> 
> Should be way cleaner and understandable, at least to me :)
Really good suggestions! Make thing much more clear.

> 
> Now there is that last oddity which bugs me in mp_map_pin_to_irq()
> 
>  	/*
> 	 * 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.
>  	 */
> 	if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
>  		irq = mp_irqs[idx].srcbusirq;
> 		if ((flags & IOAPIC_MAP_ALLOC) && info->count == 0 &&
> 		    mp_irqdomain_map(domain, irq, pin) != 0)
> 			irq = -1;
> 
> That really looks like a hack. I'm aware that the current irqdomain
> code cannot deal with that oddball case.
> 
> So what you are saying is that there are devices which have a separate
> physical wire to different ioapic pins, but the ioapic is supposed to
> bundle them to a shared interrupt.
> 
> I agree that this is odd enough to handle at the ioapic level, but
> it'd be nice to have a more elaborative comment on this.
Will try to improve the comment.

> 
> Aside of the above I'm pretty happy about the progress of this patch
> set. One thing, which needs to be looked at are the usage sites of
> irq_data->irq, whether they are safe. I did not spot any unsafe ones,
> but a few functions which are called with irq_data->irq and make no
> use of it.
Sure, will check usages of irq_data->irq.

Really appreciate you suggestions, it will improve the code a lot.
Thanks!
Gerry
> 
> Thanks,
> 
> 	tglx
> 

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-27 19:58   ` Thomas Gleixner
  2014-05-28  5:01     ` Jiang Liu
@ 2014-05-28  8:01     ` Sebastian Andrzej Siewior
  2014-05-28 10:07       ` Thomas Gleixner
  1 sibling, 1 reply; 52+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-05-28  8:01 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu
  Cc: Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, linux-pm

On 05/27/2014 09:58 PM, Thomas Gleixner wrote:
> ce4100 is an oddball though. The ioapic is registered way before the
> interrupt subsystem is initialized and I have a hard time to
> understand that comment:
> 
>         /* We can't set this earlier, because we need to calibrate the timer */
>         legacy_pic = &null_legacy_pic;
> 
> The timer calibration happens after the interrupts are set up. I
> assume it's check_timer() which wants that, but we know exactly how
> the ce4100 works, so we might be able to avoid that whole "testing"
> stuff. Sebastian, any input on this?

According to my memory there was some PIC init we need but I don't
recall the details. However, booting the system with "legacy_pic =
&null_legacy_pic;" in x86_ce4100_early_setup() gives me this:

[    0.001000] Enabling APIC mode:  Flat.  Using 2 I/O APICs
[    0.001000] leaving PIC mode, enabling APIC mode.
[    0.001000] enabled ExtINT on CPU#0
[    0.001000] ENABLING IO-APIC IRQs
[    0.001000] Setting 1 in the phys_id_present_map
[    0.001000] ...changing IO-APIC physical APIC ID to 1 ... ok.
[    0.001000] Setting 2 in the phys_id_present_map
[    0.001000] ...changing IO-APIC physical APIC ID to 2 ... ok.
[    0.001000] smpboot: CPU0: Intel(R) Atom(TM) CPU CE4150   @ 1.20GHz
(fam: 06, model: 1c, stepping: 0a)
[    0.001000] Using local APIC timer interrupts.
[    0.001000] calibrating APIC timer ...

and we stand still. With the assignment as it is now:

[    0.001000] Enabling APIC mode:  Flat.  Using 2 I/O APICs
[    0.001000] leaving PIC mode, enabling APIC mode.
[    0.001000] enabled ExtINT on CPU#0
[    0.002312] ENABLING IO-APIC IRQs
[    0.003009] Setting 1 in the phys_id_present_map
[    0.004007] ...changing IO-APIC physical APIC ID to 1 ... ok.
[    0.005533] Setting 2 in the phys_id_present_map
[    0.006006] ...changing IO-APIC physical APIC ID to 2 ... ok.
[    0.008373] ..TIMER: vector=0x30 apic1=-1 pin1=-1 apic2=-1 pin2=-1
[    0.009000] ...trying to set up timer as Virtual Wire IRQ...
[    0.019490] ..... works.
[    0.020005] smpboot: CPU0: Intel(R) Atom(TM) CPU CE4150   @ 1.20GHz
(fam: 06, model: 1c, stepping: 0a)
[    0.024005] Using local APIC timer interrupts.
[    0.024005] calibrating APIC timer ...
[    0.026000] ... lapic delta = 624992
[    0.026000] ... PM-Timer delta = 0
[    0.026000] ..... delta 624992
[    0.026000] ..... mult: 26843202
[    0.026000] ..... calibration result: 99998
[    0.026000] ..... CPU clock speed is 1199.0984 MHz.
[    0.026000] ..... host bus clock speed is 99.0998 MHz.
[    0.026000] ... verify APIC timer
[    0.128565] ... jiffies delta = 100
[    0.129004] ... jiffies result ok

and it goes on. As you see, "..TIMER:" is missing in the upper output.

> 
> Thanks,
> 
> 	tglx

Sebastian

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-28  8:01     ` Sebastian Andrzej Siewior
@ 2014-05-28 10:07       ` Thomas Gleixner
  2014-05-28 10:39         ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2014-05-28 10:07 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Jiang Liu, Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, linux-pm

On Wed, 28 May 2014, Sebastian Andrzej Siewior wrote:
> On 05/27/2014 09:58 PM, Thomas Gleixner wrote:
> > ce4100 is an oddball though. The ioapic is registered way before the
> > interrupt subsystem is initialized and I have a hard time to
> > understand that comment:
> > 
> >         /* We can't set this earlier, because we need to calibrate the timer */
> >         legacy_pic = &null_legacy_pic;
> > 
> > The timer calibration happens after the interrupts are set up. I
> > assume it's check_timer() which wants that, but we know exactly how
> > the ce4100 works, so we might be able to avoid that whole "testing"
> > stuff. Sebastian, any input on this?
> 
> According to my memory there was some PIC init we need but I don't
> recall the details. However, booting the system with "legacy_pic =
> &null_legacy_pic;" in x86_ce4100_early_setup() gives me this:
> 
> [    0.001000] Enabling APIC mode:  Flat.  Using 2 I/O APICs
> [    0.001000] leaving PIC mode, enabling APIC mode.
> [    0.001000] enabled ExtINT on CPU#0
> [    0.001000] ENABLING IO-APIC IRQs
> [    0.001000] Setting 1 in the phys_id_present_map
> [    0.001000] ...changing IO-APIC physical APIC ID to 1 ... ok.
> [    0.001000] Setting 2 in the phys_id_present_map
> [    0.001000] ...changing IO-APIC physical APIC ID to 2 ... ok.
> [    0.001000] smpboot: CPU0: Intel(R) Atom(TM) CPU CE4150   @ 1.20GHz
> (fam: 06, model: 1c, stepping: 0a)
> [    0.001000] Using local APIC timer interrupts.
> [    0.001000] calibrating APIC timer ...
> 
> and we stand still. With the assignment as it is now:
> 
> [    0.001000] Enabling APIC mode:  Flat.  Using 2 I/O APICs
> [    0.001000] leaving PIC mode, enabling APIC mode.
> [    0.001000] enabled ExtINT on CPU#0
> [    0.002312] ENABLING IO-APIC IRQs
> [    0.003009] Setting 1 in the phys_id_present_map
> [    0.004007] ...changing IO-APIC physical APIC ID to 1 ... ok.
> [    0.005533] Setting 2 in the phys_id_present_map
> [    0.006006] ...changing IO-APIC physical APIC ID to 2 ... ok.
> [    0.008373] ..TIMER: vector=0x30 apic1=-1 pin1=-1 apic2=-1 pin2=-1
> [    0.009000] ...trying to set up timer as Virtual Wire IRQ...
> [    0.019490] ..... works.

Right, so it needs the setup of irq 0 and that only happens when the
legacy_pic->nr_legacy_irqs > 0.

Do you remember, why we switch to the null_pic later on?

Thanks,

	tglx



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-28 10:07       ` Thomas Gleixner
@ 2014-05-28 10:39         ` Sebastian Andrzej Siewior
  2014-06-05  7:04           ` [RFC Patch 3/3] x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY Jiang Liu
  0 siblings, 1 reply; 52+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-05-28 10:39 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jiang Liu, Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, linux-pm

On 05/28/2014 12:07 PM, Thomas Gleixner wrote:
> 
> Right, so it needs the setup of irq 0 and that only happens when the
> legacy_pic->nr_legacy_irqs > 0.
>
> Do you remember, why we switch to the null_pic later on?

According to my memory all interrupts are serviced by the IOAPIC. The
first 16 by the first IOAPIC, 17+ (everything behind the "PCI-bus") by
the second IOAPIC. For that reason I didn't see a reason for the legacy
PIC and set it to null_pic. Due to the timer problem it is delayed.

> Thanks,
> 
> 	tglx

Sebastian

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-28  5:01     ` Jiang Liu
@ 2014-05-28 21:08       ` Thomas Gleixner
  2014-05-28 21:22         ` Thomas Gleixner
  0 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2014-05-28 21:08 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, linux-pm

On Wed, 28 May 2014, Jiang Liu wrote:
> On 2014/5/28 3:58, Thomas Gleixner wrote:
> > So you have these cases covered here:
> > 
> > 1) The ACPI case of secondary ioapics. You only have the strict 1:1
> >    mapping for the first ioapic
> > 
> > 2) The gsi < NR_IRQS_LEGACY case where you have two options:
> > 
> >     a) Let the core create a random virq number if ioapic_identity_map
> >        is 0
> > 
> >        ioapic_identity_map is only set by SFI and devicetree
> > 
> >        So in all other cases we fall into that code path for all
> >        legacy interrupts. So how is that supposed to work lets say for
> >        i8042 which has hardcoded irq 1 and 12?
> > 
> >        irq_create_mapping(1)
> >        
> > 	    hint = 1 % nr_irqs; --> 1
> > 	    virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node));
> > 
> > 	    This returns something >= 16, because the irq descriptors
> > 	    for 0-15 (LEGACY) are allocated already.
> > 
> >        The pin association works, but how is the i8042 driver supposed
> >        to figure out that it should request the virq >=16 which was
> >        created instead of the hardcoded 1 ?
> This is used to work around special non-ISA interrupts with GSI below
> NR_IRQS_LEGACY. The original code for the special case is:
> /*
>  * 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_IRQS_LEGACY ? gsi : gsi_top + gsi;

That looks really, really wrong. What's wrong with assigning that irq
irq number on those platforms?

The weird stuff is SFI and devicetree, if I understand your code
correctly.

So if those platforms do not have actual legacy irqs, what's wrong
with giving out the legacy numbers?

> We have one path to handle ISA IRQs before calling
> alloc_irq_from_domain() as below:
>         if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci))
>                 return mp_irqs[idx].srcbusirq;

Ok.
 
> >         /* We can't set this earlier, because we need to calibrate the timer */
> >         legacy_pic = &null_legacy_pic;
> I haven't figured out the story behind the comment yet:(

Sebastian gave some insight.
 
> > Why do we need strict mappings in the non ACPI case for all ioapic
> > pins? What's so different about ACPI? Or is this just to avoid
> > breaking the existing SFI/devicetree stuff. If that's the reason I'm
> > fine with it, but ...
> It's to avoid breaking SFI/intel_mid stuff. intel_mid assumes IRQ
> number equals to pin number and use pci_dev->irq to save both IRQ
> number and pin number.

Fair enough.

Thanks,

	tglx

 

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-28 21:08       ` Thomas Gleixner
@ 2014-05-28 21:22         ` Thomas Gleixner
  0 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2014-05-28 21:22 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Grant Likely, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
	Ingo Molnar, linux-pm

On Wed, 28 May 2014, Thomas Gleixner wrote:
> On Wed, 28 May 2014, Jiang Liu wrote:
> > This is used to work around special non-ISA interrupts with GSI below
> > NR_IRQS_LEGACY. The original code for the special case is:
> > /*
> >  * 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_IRQS_LEGACY ? gsi : gsi_top + gsi;
> 
> That looks really, really wrong. What's wrong with assigning that irq
> irq number on those platforms?
> 
> The weird stuff is SFI and devicetree, if I understand your code
> correctly.
> 
> So if those platforms do not have actual legacy irqs, what's wrong
> with giving out the legacy numbers?

Though if it's a real issue, we can simply mark the ioapic on those
devices as DYNAMIC and avoid that whole magic.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Patch V3 03/37] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL)
  2014-05-27  8:07 ` [Patch V3 03/37] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL) Jiang Liu
@ 2014-06-03  0:41   ` David Rientjes
  0 siblings, 0 replies; 52+ messages in thread
From: David Rientjes @ 2014-06-03  0:41 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, x86, Konrad Rzeszutek Wilk,
	Andrew Morton, Tony Luck, Joerg Roedel, Paul Gortmaker,
	Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi

On Tue, 27 May 2014, Jiang Liu wrote:

> Use pr_lvl() helper utilities to replace printk(KERN_LVL) for readability,
> no function changes.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>

Acked-by: David Rientjes <rientjes@google.com>

Eek, lots of newlines in single printks without pr_cont() that are 
existing, probably to make them more visible during debugging.  I think we 
could clean this up even further, but the printk(KERN_LVL) -> pr_lvl() 
conversion of this patch is a step in the right direction.

^ permalink raw reply	[flat|nested] 52+ messages in thread

* [RFC Patch 3/3] x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY
  2014-05-28 10:39         ` Sebastian Andrzej Siewior
@ 2014-06-05  7:04           ` Jiang Liu
  2014-06-05  8:15             ` Thomas Gleixner
  0 siblings, 1 reply; 52+ messages in thread
From: Jiang Liu @ 2014-06-05  7:04 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Yinghai Lu,
	Sebastian Andrzej Siewior, Ingo Molnar, x86, Rafael J. Wysocki,
	Len Brown, Pavel Machek, Konrad Rzeszutek Wilk, Bjorn Helgaas,
	Jiang Liu, Grant Likely, Rob Herring, Michal Simek,
	Tony Lindgren
  Cc: linux-kernel, Ingo Molnar, linux-pm, xen-devel, linux-pci

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 <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/i8259.h   |    2 ++
 arch/x86/kernel/acpi/boot.c    |   13 ++++++------
 arch/x86/kernel/apic/io_apic.c |   43 +++++++++++++++++++++++-----------------
 arch/x86/kernel/devicetree.c   |   12 +++++------
 arch/x86/kernel/irqinit.c      |    6 +++---
 arch/x86/pci/xen.c             |    6 +++---
 6 files changed, 46 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index a20365953bf8..fdac75b8782a 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -67,4 +67,6 @@ struct legacy_pic {
 extern struct legacy_pic *legacy_pic;
 extern struct legacy_pic null_legacy_pic;
 
+#define	nr_legacy_irqs()	(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..68f8805401be 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -316,7 +316,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 +326,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..8debddd2c6d1 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -40,7 +40,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 +511,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 +522,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


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* Re: [RFC Patch 3/3] x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY
  2014-06-05  7:04           ` [RFC Patch 3/3] x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY Jiang Liu
@ 2014-06-05  8:15             ` Thomas Gleixner
  0 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2014-06-05  8:15 UTC (permalink / raw)
  To: Jiang Liu
  Cc: H. Peter Anvin, Yinghai Lu, Sebastian Andrzej Siewior,
	Ingo Molnar, x86, Rafael J. Wysocki, Len Brown, Pavel Machek,
	Konrad Rzeszutek Wilk, Bjorn Helgaas, Grant Likely, Rob Herring,
	Michal Simek, Tony Lindgren, linux-kernel, Ingo Molnar, linux-pm,
	xen-devel, linux-pci

On Thu, 5 Jun 2014, 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.

Nice patch set!
 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>  arch/x86/include/asm/i8259.h   |    2 ++
>  arch/x86/kernel/acpi/boot.c    |   13 ++++++------
>  arch/x86/kernel/apic/io_apic.c |   43 +++++++++++++++++++++++-----------------
>  arch/x86/kernel/devicetree.c   |   12 +++++------
>  arch/x86/kernel/irqinit.c      |    6 +++---
>  arch/x86/pci/xen.c             |    6 +++---
>  6 files changed, 46 insertions(+), 36 deletions(-)
> 
> diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
> index a20365953bf8..fdac75b8782a 100644
> --- a/arch/x86/include/asm/i8259.h
> +++ b/arch/x86/include/asm/i8259.h
> @@ -67,4 +67,6 @@ struct legacy_pic {
>  extern struct legacy_pic *legacy_pic;
>  extern struct legacy_pic null_legacy_pic;
>  
> +#define	nr_legacy_irqs()	(legacy_pic->nr_legacy_irqs)

That wants to be a static inline, please.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2014-06-05  8:15 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-27  8:07 [Patch V3 00/37] use irqdomain to dynamically allocate IRQ for IOAPIC Jiang Liu
2014-05-27  8:07 ` [Patch V3 01/37] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
2014-05-27  8:11   ` Thomas Gleixner
2014-05-27  8:50     ` Jiang Liu
2014-05-27  8:07 ` [Patch V3 02/37] genirq, trivial: improve documentation to match current implementation Jiang Liu
2014-05-27  8:07 ` [Patch V3 03/37] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL) Jiang Liu
2014-06-03  0:41   ` David Rientjes
2014-05-27  8:07 ` [Patch V3 04/37] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
2014-05-27  8:07 ` [Patch V3 05/37] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
2014-05-27 13:50   ` Bjorn Helgaas
2014-05-27 21:22   ` David Rientjes
2014-05-27  8:07 ` [Patch V3 06/37] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
2014-05-27  8:07 ` [Patch V3 07/37] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
2014-05-27  8:07 ` [Patch V3 08/37] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
2014-05-27  8:07 ` [Patch V3 09/37] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
2014-05-27  8:07 ` [Patch V3 10/37] x86, irq, trivial: minor improvements of IRQ related code Jiang Liu
2014-05-27  8:07 ` [Patch V3 11/37] x86, ioapic: kill unused global variable timer_through_8259 Jiang Liu
2014-05-27  8:07 ` [Patch V3 12/37] x86, ioapic: kill static variable nr_irqs_gsi Jiang Liu
2014-05-27  8:07 ` [Patch V3 13/37] x86, ioapic: introduce helper utilities to walk ioapics and pins Jiang Liu
2014-05-27  8:07 ` [Patch V3 14/37] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability Jiang Liu
2014-05-27  8:07 ` [Patch V3 15/37] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain Jiang Liu
2014-05-27  8:07 ` [Patch V3 16/37] x86, irq: introduce some helper utilities to improve readability Jiang Liu
2014-05-27  8:07 ` [Patch V3 17/37] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
2014-05-27  8:07 ` [Patch V3 18/37] x86, irq, ACPI: change __acpi_register_gsi to return IRQ number instead of GSI Jiang Liu
2014-05-27  8:07 ` [Patch V3 19/37] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
2014-05-27 19:58   ` Thomas Gleixner
2014-05-28  5:01     ` Jiang Liu
2014-05-28 21:08       ` Thomas Gleixner
2014-05-28 21:22         ` Thomas Gleixner
2014-05-28  8:01     ` Sebastian Andrzej Siewior
2014-05-28 10:07       ` Thomas Gleixner
2014-05-28 10:39         ` Sebastian Andrzej Siewior
2014-06-05  7:04           ` [RFC Patch 3/3] x86, irq: count legacy IRQs by legacy_pic->nr_legacy_irqs instead of NR_IRQS_LEGACY Jiang Liu
2014-06-05  8:15             ` Thomas Gleixner
2014-05-27  8:07 ` [Patch V3 20/37] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
2014-05-27  8:07 ` [Patch V3 21/37] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
2014-05-27  8:07 ` [Patch V3 22/37] x86, mpparse, " Jiang Liu
2014-05-27  8:07 ` [Patch V3 23/37] x86, SFI, " Jiang Liu
2014-05-27  8:07 ` [Patch V3 24/37] x86, devicetree, irq: use common mechanism to support irqdomain Jiang Liu
2014-05-27  8:08 ` [Patch V3 25/37] x86, irq: introduce two helper functions to support irqdomain map operation Jiang Liu
2014-05-27  8:08 ` [Patch V3 26/37] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
2014-05-27  8:08 ` [Patch V3 27/37] x86, irq, mpparse: " Jiang Liu
2014-05-27  8:08 ` [Patch V3 28/37] x86, irq, SFI: " Jiang Liu
2014-05-27  8:08 ` [Patch V3 29/37] x86, irq, devicetree: " Jiang Liu
2014-05-27  8:08 ` [Patch V3 30/37] x86, irq: clean up unused IOAPIC interface Jiang Liu
2014-05-27  8:08 ` [Patch V3 31/37] x86, irq: simplify the way to handle ISA IRQ Jiang Liu
2014-05-27  8:08 ` [Patch V3 32/37] genirq: export irq_domain_disassociate() to architecture interrupt drivers Jiang Liu
2014-05-27  8:08 ` [Patch V3 33/37] x86, irq: introduce helper functions to release IOAPIC pin Jiang Liu
2014-05-27  8:08 ` [Patch V3 34/37] x86, irq, ACPI: release IOAPIC pin when PCI device is disabled Jiang Liu
2014-05-27  8:08 ` [Patch V3 35/37] x86, irq, mpparse: " Jiang Liu
2014-05-27  8:08 ` [Patch V3 36/37] x86, irq, SFI: " Jiang Liu
2014-05-27  8:08 ` [Patch V3 37/37] x86, irq, devicetree: " Jiang Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).