linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin
@ 2014-05-16  8:05 Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 01/30] genirq, trivial: improve documentation to match current implementation Jiang Liu
                   ` (31 more replies)
  0 siblings, 32 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel

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 v3.15-rc4-260-g38583f095c5a and 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)

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

TODO list:
1) check whether it affects Xen or not

Patch 1-17 are trivial code improvements, bugfixes and preparation.

Patch 18-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 cleans up unused interfaces and functions in IOAPIC driver.

Tests and comments are warmly welcomed!

Jiang Liu (30):
  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: replace get_nr_irqs_gsi() with
    arch_dynirq_lower_bound(0)
  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: update high address field when updating affinity for MSI
    IRQ
  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: 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, devicetree, irq: use common mechanism to support irqdomain
  x86, SFI, irq: provide basic irqdomain support
  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

 Documentation/IRQ-domain.txt      |    3 +-
 arch/x86/include/asm/apic.h       |    4 +-
 arch/x86/include/asm/hardirq.h    |    3 -
 arch/x86/include/asm/io_apic.h    |   44 ++-
 arch/x86/include/asm/mpspec.h     |   13 -
 arch/x86/include/asm/prom.h       |    2 -
 arch/x86/kernel/acpi/boot.c       |  205 ++++++------
 arch/x86/kernel/apic/apic.c       |    2 +-
 arch/x86/kernel/apic/io_apic.c    |  623 +++++++++++++++++++++----------------
 arch/x86/kernel/devicetree.c      |   92 +-----
 arch/x86/kernel/irqinit.c         |    6 -
 arch/x86/kernel/mpparse.c         |   97 +++---
 arch/x86/pci/acpi.c               |    6 +-
 arch/x86/pci/intel_mid_pci.c      |   17 +-
 arch/x86/pci/irq.c                |    2 -
 arch/x86/platform/intel-mid/sfi.c |   18 +-
 arch/x86/platform/sfi/sfi.c       |   12 +-
 drivers/iommu/irq_remapping.c     |    4 +-
 drivers/xen/events/events_base.c  |    2 +-
 kernel/irq/internals.h            |    2 +-
 kernel/irq/irqdomain.c            |    6 +-
 21 files changed, 581 insertions(+), 582 deletions(-)

-- 
1.7.10.4


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

* [RFC Patch Part1 V1 01/30] genirq, trivial: improve documentation to match current implementation
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 02/30] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL) Jiang Liu
                   ` (30 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 ddf1ffeb79f1..9552a0c123c8 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] 37+ messages in thread

* [RFC Patch Part1 V1 02/30] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL)
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 01/30] genirq, trivial: improve documentation to match current implementation Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 03/30] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
                   ` (29 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel

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] 37+ messages in thread

* [RFC Patch Part1 V1 03/30] x86, mpparse: simplify arch/x86/include/asm/mpspec.h
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 01/30] genirq, trivial: improve documentation to match current implementation Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 02/30] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL) Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 04/30] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
                   ` (28 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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,
	sfi-devel, 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 459e50a424d1..677e599c275e 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] 37+ messages in thread

* [RFC Patch Part1 V1 04/30] x86, PCI, ACPI: use kmalloc_node() to optimize for performance
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (2 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 03/30] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 05/30] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
                   ` (27 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel

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] 37+ messages in thread

* [RFC Patch Part1 V1 05/30] x86, acpi, irq: kill static function irq_to_gsi()
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (3 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 04/30] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 06/30] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
                   ` (26 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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] 37+ messages in thread

* [RFC Patch Part1 V1 06/30] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (4 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 05/30] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 07/30] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
                   ` (25 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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] 37+ messages in thread

* [RFC Patch Part1 V1 07/30] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (5 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 06/30] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 08/30] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
                   ` (24 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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] 37+ messages in thread

* [RFC Patch Part1 V1 08/30] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (6 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 07/30] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 09/30] x86, irq, trivial: minor improvements of IRQ related code Jiang Liu
                   ` (23 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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] 37+ messages in thread

* [RFC Patch Part1 V1 09/30] x86, irq, trivial: minor improvements of IRQ related code
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (7 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 08/30] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 10/30] x86, ioapic: kill unused global variable timer_through_8259 Jiang Liu
                   ` (22 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 677e599c275e..8f472daea221 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);
@@ -174,11 +172,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 992060e09897..1041b227726a 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1025,7 +1025,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);
@@ -1374,7 +1374,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;
 
 		/*
@@ -1403,7 +1403,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
  */
@@ -2240,7 +2240,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);
 	}
@@ -3624,7 +3624,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] 37+ messages in thread

* [RFC Patch Part1 V1 10/30] x86, ioapic: kill unused global variable timer_through_8259
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (8 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 09/30] x86, irq, trivial: minor improvements of IRQ related code Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 11/30] x86, ioapic: replace get_nr_irqs_gsi() with arch_dynirq_lower_bound(0) Jiang Liu
                   ` (21 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 8f472daea221..0c448ac14abf 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.
@@ -214,7 +211,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 1041b227726a..a338d9601841 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2664,8 +2664,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
@@ -2770,7 +2768,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] 37+ messages in thread

* [RFC Patch Part1 V1 11/30] x86, ioapic: replace get_nr_irqs_gsi() with arch_dynirq_lower_bound(0)
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (9 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 10/30] x86, ioapic: kill unused global variable timer_through_8259 Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 12/30] x86, ioapic: kill static variable nr_irqs_gsi Jiang Liu
                   ` (20 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Joerg Roedel, Konrad Rzeszutek Wilk,
	Boris Ostrovsky, David Vrabel, Jiang Liu
  Cc: Andrew Morton, Tony Luck, Paul Gortmaker, Greg Kroah-Hartman,
	linux-kernel, linux-pci, linux-acpi, sfi-devel, Ingo Molnar,
	iommu, xen-devel

Currently all callers use get_nr_irqs_gsi() to get the lowest dynamic
allocatable IRQ number, and arch_dynirq_lower_bound(0) achieves the same
goal with a better name. So replace get_nr_irqs_gsi() with
arch_dynirq_lower_bound(0). It will also help to support dynamic IRQ
allocation for IOAPIC by using arch_dynirq_lower_bound().

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   |    5 -----
 drivers/iommu/irq_remapping.c    |    4 ++--
 drivers/xen/events/events_base.c |    2 +-
 4 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 0c448ac14abf..de3d8b04cf64 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -160,8 +160,6 @@ extern int save_ioapic_entries(void);
 extern void mask_ioapic_entries(void);
 extern int restore_ioapic_entries(void);
 
-extern int get_nr_irqs_gsi(void);
-
 extern void setup_ioapic_ids_from_mpc(void);
 extern void setup_ioapic_ids_from_mpc_nocheck(void);
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index a338d9601841..2c91a7fc9915 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3417,11 +3417,6 @@ static void __init probe_nr_irqs_gsi(void)
 	printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
 }
 
-int get_nr_irqs_gsi(void)
-{
-	return nr_irqs_gsi;
-}
-
 unsigned int arch_dynirq_lower_bound(unsigned int from)
 {
 	return from < nr_irqs_gsi ? nr_irqs_gsi : from;
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index 228632c99adb..f874344409df 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -62,7 +62,7 @@ static int do_setup_msi_irqs(struct pci_dev *dev, int nvec)
 	WARN_ON(msidesc->nvec_used);
 
 	node = dev_to_node(&dev->dev);
-	irq = __create_irqs(get_nr_irqs_gsi(), nvec, node);
+	irq = __create_irqs(arch_dynirq_lower_bound(0), nvec, node);
 	if (irq == 0)
 		return -ENOSPC;
 
@@ -109,7 +109,7 @@ static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
 	unsigned int irq;
 
 	node		= dev_to_node(&dev->dev);
-	irq		= get_nr_irqs_gsi();
+	irq		= arch_dynirq_lower_bound(0);
 	sub_handle	= 0;
 
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index dfa12a4a0a48..004e9bb293c6 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -402,7 +402,7 @@ static int __must_check xen_allocate_irqs_dynamic(int nvec)
 	 * collisions.
 	 */
 	if (xen_initial_domain() || xen_hvm_domain())
-		first = get_nr_irqs_gsi();
+		first = arch_dynirq_lower_bound(0);
 #endif
 
 	irq = irq_alloc_descs_from(first, nvec, -1);
-- 
1.7.10.4


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

* [RFC Patch Part1 V1 12/30] x86, ioapic: kill static variable nr_irqs_gsi
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (10 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 11/30] x86, ioapic: replace get_nr_irqs_gsi() with arch_dynirq_lower_bound(0) Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 13/30] x86, ioapic: introduce helper utilities to walk ioapics and pins Jiang Liu
                   ` (19 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 |   35 ++++++++---------------------------
 1 file changed, 8 insertions(+), 27 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 2c91a7fc9915..fe515583a927 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
@@ -2921,9 +2918,7 @@ unsigned int __create_irqs(unsigned int from, unsigned int count, int node)
 	unsigned long flags;
 	int irq, i;
 
-	if (from < nr_irqs_gsi)
-		from = nr_irqs_gsi;
-
+	from = arch_dynirq_lower_bound(from);
 	cfg = kzalloc_node(count * sizeof(cfg[0]), GFP_KERNEL, node);
 	if (!cfg)
 		return 0;
@@ -2972,12 +2967,9 @@ unsigned int create_irq_nr(unsigned int from, int node)
 int create_irq(void)
 {
 	int node = cpu_to_node(0);
-	unsigned int irq_want;
 	int irq;
 
-	irq_want = nr_irqs_gsi;
-	irq = create_irq_nr(irq_want, node);
-
+	irq = create_irq_nr(arch_dynirq_lower_bound(0), node);
 	if (irq == 0)
 		irq = -1;
 
@@ -3142,7 +3134,7 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		return 1;
 
 	node = dev_to_node(&dev->dev);
-	irq_want = nr_irqs_gsi;
+	irq_want = arch_dynirq_lower_bound(0);
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
 		irq = create_irq_nr(irq_want, node);
 		if (irq == 0)
@@ -3406,20 +3398,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)
@@ -3429,12 +3412,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;
@@ -3707,8 +3690,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] 37+ messages in thread

* [RFC Patch Part1 V1 13/30] x86, ioapic: introduce helper utilities to walk ioapics and pins
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (11 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 12/30] x86, ioapic: kill static variable nr_irqs_gsi Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 14/30] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability Jiang Liu
                   ` (18 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 fe515583a927..86f9511c97a0 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);
@@ -639,9 +649,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
@@ -690,13 +699,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);
 	}
@@ -711,11 +720,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];
@@ -734,11 +743,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]);
 	}
@@ -797,7 +806,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;
 	}
@@ -1016,7 +1025,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;
@@ -1239,12 +1248,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
@@ -1364,7 +1371,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;
@@ -1395,7 +1402,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);
 }
 
@@ -1598,7 +1605,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);
@@ -1609,7 +1616,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");
@@ -1840,26 +1847,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:
@@ -1962,7 +1965,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);
@@ -2889,7 +2892,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();
@@ -3532,9 +3535,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);
@@ -3592,8 +3594,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;
@@ -3622,29 +3623,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;
@@ -3658,8 +3663,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
@@ -3704,7 +3709,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++;
 	}
@@ -3712,16 +3717,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;
 	}
 
@@ -3733,7 +3737,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] 37+ messages in thread

* [RFC Patch Part1 V1 14/30] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (12 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 13/30] x86, ioapic: introduce helper utilities to walk ioapics and pins Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 15/30] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
                   ` (17 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 86f9511c97a0..8d6e4c7e7011 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -233,7 +233,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);
 }
@@ -275,7 +275,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;
 	}
@@ -1219,7 +1219,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;
 
@@ -1627,7 +1627,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;
@@ -2268,7 +2268,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;
@@ -2541,7 +2541,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,
@@ -2674,7 +2674,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;
@@ -2981,7 +2981,7 @@ int create_irq(void)
 
 void destroy_irq(unsigned int irq)
 {
-	struct irq_cfg *cfg = irq_get_chip_data(irq);
+	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned long flags;
 
 	irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
@@ -3117,7 +3117,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");
 
@@ -3255,7 +3255,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] 37+ messages in thread

* [RFC Patch Part1 V1 15/30] x86, irq: update high address field when updating affinity for MSI IRQ
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (13 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 14/30] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 16/30] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain Jiang Liu
                   ` (16 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 8d6e4c7e7011..b74ec1183d34 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3073,6 +3073,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] 37+ messages in thread

* [RFC Patch Part1 V1 16/30] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (14 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 15/30] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 17/30] x86, irq: introduce some helper utilities to improve readability Jiang Liu
                   ` (15 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 |   62 ++++++++++++++++++++++------------------
 1 file changed, 34 insertions(+), 28 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index b74ec1183d34..dd81b58cce95 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1012,7 +1012,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",
@@ -1022,41 +1022,47 @@ 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 (test_bit(lbus, mp_bus_not_pci) || (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] 37+ messages in thread

* [RFC Patch Part1 V1 17/30] x86, irq: introduce some helper utilities to improve readability
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (15 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 16/30] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 18/30] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
                   ` (14 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, Ingo Molnar

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/apic/io_apic.c |   41 +++++++++++++++++++++++++++++-----------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index dd81b58cce95..faed9b62977d 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -117,6 +117,26 @@ 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;
+}
+
+static inline u32 mp_pin_2_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_pin_at_boot(int ioapic, int pin)
+{
+	u32 gsi = mp_pin_2_gsi(ioapic, pin);
+
+	return ioapic == 0 || gsi < NR_IRQS_LEGACY;
+}
+
 int nr_ioapics;
 
 /* The one past the highest gsi number used */
@@ -1378,15 +1398,15 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
 	unsigned int pin, irq;
 
 	for_each_pin(ioapic_idx, pin) {
+		if (!mp_init_pin_at_boot(ioapic_idx, pin))
+			continue;
+
 		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);
 
-		if ((ioapic_idx > 0) && (irq > NR_IRQS_LEGACY))
-			continue;
-
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -1430,16 +1450,15 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	pin = mp_find_ioapic_pin(ioapic_idx, gsi);
+	if (mp_init_pin_at_boot(ioapic_idx, pin))
+		return;
+
 	idx = find_irq_entry(ioapic_idx, pin, mp_INT);
 	if (idx == -1)
 		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)
-		return;
-
 	set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
 			     irq_polarity(idx));
 
@@ -3605,14 +3624,14 @@ void __init setup_ioapic_dest(void)
 		return;
 
 	for_each_ioapic_pin(ioapic, pin) {
-		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
-		if (irq_entry == -1)
+		if (!mp_init_pin_at_boot(ioapic, pin))
 			continue;
-		irq = pin_2_irq(irq_entry, ioapic, pin);
 
-		if ((ioapic > 0) && (irq > NR_IRQS_LEGACY))
+		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+		if (irq_entry == -1)
 			continue;
 
+		irq = pin_2_irq(irq_entry, ioapic, pin);
 		idata = irq_get_irq_data(irq);
 
 		/*
-- 
1.7.10.4


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

* [RFC Patch Part1 V1 18/30] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (16 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 17/30] x86, irq: introduce some helper utilities to improve readability Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 19/30] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
                   ` (13 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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_pin_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    |   52 +++++++++++++++++++++-------------------
 arch/x86/kernel/apic/io_apic.c |   30 +++++++++++++----------
 3 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index de3d8b04cf64..f4fd0be26cec 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 int mp_map_pin_to_irq(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 int mp_map_pin_to_irq(int ioapic, int pin) { return -1; }
 
 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..6eae9a7231c4 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -99,27 +99,22 @@ 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, ioapic, pin;
 
-	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;
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic >= 0) {
+		pin = mp_find_ioapic_pin(ioapic, gsi);
+		return mp_map_pin_to_irq(ioapic, pin);
+	}
 
-	return irq;
+	pr_err("Failed to map GSI%d to IRQ number.\n", gsi);
+	return -1;
 }
 
 /*
@@ -493,16 +488,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 +555,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 +1028,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 +1041,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 +1066,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 faed9b62977d..f55357bd0e07 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -980,11 +980,22 @@ static int irq_trigger(int idx)
 	return trigger;
 }
 
+int mp_map_pin_to_irq(int apic, int pin)
+{
+	struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
+	u32 gsi = gsi_cfg->gsi_base + pin;
+
+	/*
+	 * 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!
@@ -992,17 +1003,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.
@@ -1017,11 +1017,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_pin_to_irq(apic, pin);
+
 	return irq;
 }
 
-- 
1.7.10.4


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

* [RFC Patch Part1 V1 19/30] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (17 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 18/30] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 20/30] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
                   ` (12 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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.

This patch enhances ioapic.c to provide basic mechanisms to support
dynamically allocate IRQ number for IOAPIC by using irqdomain.

It first adds several fields into struct ioapic to support irqdomain.
Then it implements an algorithm to dynamically allocate IRQ number
on demand.
1) Build identity mapping for GSIs below arch_dynirq_lower_bound(0).
   This is typically used to support legacy IRQs and simple platforms.
   There's an exception for overridden ISA IRQs, whose GSI number
   may be different from assigned IRQ number.
2) Dynamically allocate IRQs for GSIs above  arch_dynirq_lower_bound(0).
   This may be used to support big system and IOAPIC hotplug.

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/include/asm/io_apic.h |    9 ++-
 arch/x86/kernel/acpi/boot.c    |   10 ++--
 arch/x86/kernel/apic/io_apic.c |  125 +++++++++++++++++++++++++++++++---------
 3 files changed, 110 insertions(+), 34 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index f4fd0be26cec..13209bdf318d 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -169,9 +169,11 @@ 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 int mp_map_pin_to_irq(int ioapic, int pin);
+extern int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc);
 extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
 extern void __init pre_init_apic_IRQ0(void);
 
@@ -213,7 +215,10 @@ 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 int mp_map_pin_to_irq(int ioapic, int pin) { return -1; }
+static inline int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc)
+{
+	return -1;
+}
 
 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 6eae9a7231c4..cdf6908e9f75 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, int alloc)
 {
 	int i, ioapic, pin;
 
@@ -110,7 +110,7 @@ static int map_gsi_to_irq(unsigned int gsi)
 	ioapic = mp_find_ioapic(gsi);
 	if (ioapic >= 0) {
 		pin = mp_find_ioapic_pin(ioapic, gsi);
-		return mp_map_pin_to_irq(ioapic, pin);
+		return mp_map_pin_to_irq(-1, ioapic, pin, alloc);
 	}
 
 	pr_err("Failed to map GSI%d to IRQ number.\n", gsi);
@@ -490,7 +490,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, 1);
 
 	if (irq >= 0) {
 #ifdef CONFIG_X86_IO_APIC
@@ -559,7 +559,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 
 	plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
 	if (plat_gsi != ACPI_INVALID_GSI)
-		return map_gsi_to_irq(plat_gsi);
+		return map_gsi_to_irq(plat_gsi, 0);
 
 	return -1;
 }
@@ -1041,7 +1041,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, 1);
 	if (irq < 0)
 		return ACPI_INVALID_GSI;
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index f55357bd0e07..fb87bdbb4307 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];
 
@@ -137,6 +142,11 @@ static inline int mp_init_pin_at_boot(int ioapic, int pin)
 	return ioapic == 0 || gsi < 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 */
@@ -980,19 +990,68 @@ static int irq_trigger(int idx)
 	return trigger;
 }
 
-int mp_map_pin_to_irq(int apic, int pin)
+/*
+ * Dynamically allocate IRQ for GSI above arch_dynirq_lower_bound(0),
+ * and build identity mapping for statically assigned IRQ, but need
+ * special handling for ISA IRQ overriden.
+ */
+static int alloc_irq_from_domain(struct irq_domain *domain,
+				 int idx, int apic, int pin, u32 gsi)
 {
-	struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
-	u32 gsi = gsi_cfg->gsi_base + pin;
+	int irq;
+
+	if (gsi >= arch_dynirq_lower_bound(0))
+		return irq_create_mapping(domain, pin);
+
+	irq = irq_find_mapping(domain, pin);
+	if (irq > 0)
+		return irq;
+
+	if (idx < 0)
+		idx = find_irq_entry(apic, pin, mp_INT);
+
+	/* Handle ISA IRQ overridden */
+	if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci))
+		irq = mp_irqs[idx].srcbusirq;
+	else
+		irq = gsi;
 
 	/*
-	 * Provide an identity mapping of gsi == irq except on truly weird
-	 * platforms that have non isa irqs in the first 16 gsis.
+	 * The first NR_IRQS_LEGACY irq descs are allocated in early_irq_init()
+	 * and need just a mapping. The remaining irqs need both.
 	 */
-	return gsi >= NR_IRQS_LEGACY ? gsi : gsi_top + gsi;
+	if (irq < NR_IRQS_LEGACY)
+		return irq_domain_associate(domain, irq, pin);
+
+	return irq_create_strict_mappings(domain, irq, pin, 1) ? -1 : irq;
 }
 
-static int pin_2_irq(int idx, int apic, int pin)
+int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc)
+{
+	int irq;
+	u32 gsi = mp_pin_2_gsi(ioapic, pin);
+	struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+
+	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);
+	if (alloc) {
+		irq = alloc_irq_from_domain(domain, idx, ioapic, pin, gsi);
+	} else {
+		irq = irq_find_mapping(domain, pin);
+	}
+	mutex_unlock(&ioapic_mutex);
+
+	return irq > 0 ? irq : -1;
+}
+
+static int pin_2_irq(int idx, int apic, int pin, int alloc)
 {
 	int irq;
 	int bus = mp_irqs[idx].srcbus;
@@ -1026,7 +1085,7 @@ static int pin_2_irq(int idx, int apic, int pin)
 	if (test_bit(bus, mp_bus_not_pci))
 		irq = mp_irqs[idx].srcbusirq;
 	else
-		irq = mp_map_pin_to_irq(apic, pin);
+		irq = mp_map_pin_to_irq(idx, apic, pin, alloc);
 
 	return irq;
 }
@@ -1038,7 +1097,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",
@@ -1052,6 +1111,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;
 		int ioapic_idx, found = 0;
+		int gsi;
 
 		if (test_bit(lbus, mp_bus_not_pci) || (bus != lbus) ||
 		    mp_irqs[i].irqtype != mp_INT ||
@@ -1068,30 +1128,36 @@ 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))
+		gsi = mp_pin_2_gsi(ioapic_idx, mp_irqs[i].dstirq);
+		if (gsi < arch_dynirq_lower_bound(0) && !IO_APIC_IRQ(gsi))
 			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, 1);
+	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);
 
@@ -1282,7 +1348,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);
 	}
 	/*
@@ -1411,7 +1477,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);
+		irq = pin_2_irq(idx, ioapic_idx, pin, 1);
+		if (irq < 0)
+			continue;
 
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
@@ -1463,7 +1531,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 	if (idx == -1)
 		return;
 
-	irq = pin_2_irq(idx, ioapic_idx, pin);
+	irq = pin_2_irq(idx, ioapic_idx, pin, 1);
 
 	set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
 			     irq_polarity(idx));
@@ -3637,7 +3705,10 @@ void __init setup_ioapic_dest(void)
 		if (irq_entry == -1)
 			continue;
 
-		irq = pin_2_irq(irq_entry, ioapic, pin);
+		irq = pin_2_irq(irq_entry, ioapic, pin, 0);
+		if (irq < 0)
+			continue;
+
 		idata = irq_get_irq_data(irq);
 
 		/*
-- 
1.7.10.4


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

* [RFC Patch Part1 V1 20/30] x86, irq: enhance mp_register_ioapic() to support irqdomain
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (18 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 19/30] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 21/30] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
                   ` (11 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Pavel Machek, Jiang Liu,
	Grant Likely, 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, sfi-devel, Ingo Molnar, linux-pm

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 |    9 +++++++-
 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, 59 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 13209bdf318d..f3afa86e5bb6 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -130,6 +130,9 @@ extern int noioapicquirk;
 /* -1 if "noapic" boot option passed */
 extern int noioapicreroute;
 
+/* 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.
@@ -169,12 +172,16 @@ struct mp_ioapic_gsi{
 };
 extern u32 gsi_top;
 
+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 int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc);
-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 cdf6908e9f75..f70f4f318316 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -344,7 +344,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 fb87bdbb4307..0bdf50988d75 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -166,6 +166,15 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 
 int skip_ioapic_setup;
 
+/*
+ * 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
  */
@@ -2938,15 +2947,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.
          */
@@ -3508,6 +3530,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;
 }
 
@@ -3886,7 +3911,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;
@@ -3900,6 +3926,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);
 
@@ -3936,6 +3965,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] 37+ messages in thread

* [RFC Patch Part1 V1 21/30] x86, ACPI, irq: provide basic irqdomain support
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (19 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 20/30] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 22/30] x86, mpparse, " Jiang Liu
                   ` (10 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 f70f4f318316..1ee639e74d50 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>
@@ -331,6 +332,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)
 {
@@ -345,7 +363,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] 37+ messages in thread

* [RFC Patch Part1 V1 22/30] x86, mpparse, irq: provide basic irqdomain support
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (20 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 21/30] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 23/30] x86, devicetree, irq: use common mechanism to support irqdomain Jiang Liu
                   ` (9 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel

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] 37+ messages in thread

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

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 |   80 ++++--------------------------------------
 arch/x86/kernel/irqinit.c    |    6 ----
 3 files changed, 7 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..a44d45df49f5 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,10 @@ 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);
-	}
+	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] 37+ messages in thread

* [RFC Patch Part1 V1 24/30] x86, SFI, irq: provide basic irqdomain support
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (22 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 23/30] x86, devicetree, irq: use common mechanism to support irqdomain Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 25/30] x86, irq: introduce two helper functions to support irqdomain map operation Jiang Liu
                   ` (7 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Yinghai Lu, Len Brown, x86
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi, 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/platform/sfi/sfi.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index 3bd7cf642680..2c3522dfa05d 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,12 @@ 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)
+{
+	return mp_irqdomain_create(ioapic, NULL, &sfi_ioapic_irqdomain_ops);
+}
 
 static int __init sfi_parse_ioapic(struct sfi_table_header *table)
 {
@@ -82,7 +89,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] 37+ messages in thread

* [RFC Patch Part1 V1 25/30] x86, irq: introduce two helper functions to support irqdomain map operation
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (23 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 24/30] x86, SFI, irq: provide basic irqdomain support Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 26/30] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
                   ` (6 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 |    4 ++
 arch/x86/kernel/apic/io_apic.c |   79 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index f3afa86e5bb6..2f37df00d6f8 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -182,6 +182,10 @@ 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_pin_attr(int ioapic, int pin, 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 0bdf50988d75..0489fb2393ec 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;
@@ -142,6 +151,11 @@ static inline int mp_init_pin_at_boot(int ioapic, int pin)
 	return ioapic == 0 || gsi < 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;
@@ -1051,7 +1065,13 @@ int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc)
 
 	mutex_lock(&ioapic_mutex);
 	if (alloc) {
+		struct mp_pin_info *info = mp_pin_info(ioapic, pin);
+
 		irq = alloc_irq_from_domain(domain, idx, ioapic, pin, gsi);
+		if (irq > 0)
+			info->count++;
+		else if (info->count == 0)
+			info->set = 0;
 	} else {
 		irq = irq_find_mapping(domain, pin);
 	}
@@ -2949,11 +2969,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);
 	}
@@ -3980,6 +4003,60 @@ 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, hwirq))
+		return 0;
+
+	/* Get default attribute if not set by caller yet */
+	if (!info->set) {
+		u32 gsi = mp_pin_2_gsi(ioapic, hwirq);
+		if (acpi_get_override_irq(gsi, &info->trigger,
+					  &info->polarity) < 0) {
+			return -ENODEV;
+		}
+		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_pin_attr(int ioapic, int pin, int trigger, int polarity, int node)
+{
+	int ret = 0;
+	struct mp_pin_info *info = mp_pin_info(ioapic, pin);
+
+	trigger = !!trigger;
+	polarity = !!polarity;
+
+	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] 37+ messages in thread

* [RFC Patch Part1 V1 26/30] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (24 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 25/30] x86, irq: introduce two helper functions to support irqdomain map operation Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 27/30] x86, irq, mpparse: " Jiang Liu
                   ` (5 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, 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 |   48 ++++++++++++++++---------------------------
 1 file changed, 18 insertions(+), 30 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 1ee639e74d50..50f06c9d1e2a 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -332,7 +332,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)
 {
@@ -512,10 +514,6 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 	int irq = map_gsi_to_irq(gsi, 1);
 
 	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;
 	}
@@ -1047,11 +1045,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, ioapic, pin, node;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -1060,35 +1054,29 @@ 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, 1);
-	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);
-		return gsi;
+		pr_warn("No IOAPIC for GSI %u\n", gsi);
+		return ACPI_INVALID_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;
+	pin = mp_find_ioapic_pin(ioapic, gsi);
+	node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
+	if (mp_set_pin_attr(ioapic, pin,
+			    trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
+			    polarity == ACPI_ACTIVE_HIGH ? 0 : 1,
+			    node)) {
+		pr_warn("Failed to set pin attr for GSI%d\n", gsi);
+		return ACPI_INVALID_GSI;
 	}
 
+	irq = map_gsi_to_irq(gsi, 1);
+	if (irq < 0)
+		return ACPI_INVALID_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)
-		gsi = ACPI_INVALID_GSI;
-
 	return gsi;
 }
 
-- 
1.7.10.4


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

* [RFC Patch Part1 V1 27/30] x86, irq, mpparse: use common irqdomain map interface to program IOAPIC pins
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (25 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 26/30] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 28/30] x86, irq, SFI: " Jiang Liu
                   ` (4 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel

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] 37+ messages in thread

* [RFC Patch Part1 V1 28/30] x86, irq, SFI: use common irqdomain map interface to program IOAPIC pins
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (26 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 27/30] x86, irq, mpparse: " Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16  8:05 ` [RFC Patch Part1 V1 29/30] x86, irq, devicetree: " Jiang Liu
                   ` (3 subsequent siblings)
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, H. Peter Anvin

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      |   17 +++++++----------
 arch/x86/platform/intel-mid/sfi.c |   18 +++++++++---------
 arch/x86/platform/sfi/sfi.c       |    4 +++-
 3 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 84b9d672843d..f6f3de857baa 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -208,23 +208,20 @@ 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;
-
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	int ioapic, polarity;
 
 	/*
 	 * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
 	 * IOAPIC RTE entries, so we just enable RTE for the device.
 	 */
-	irq_attr.ioapic = mp_find_ioapic(dev->irq);
-	irq_attr.ioapic_pin = dev->irq;
-	irq_attr.trigger = 1; /* level */
+	ioapic = mp_find_ioapic(dev->irq);
 	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
-		irq_attr.polarity = 0; /* active high */
+		polarity = 0; /* active high */
 	else
-		irq_attr.polarity = 1; /* active low */
-	io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
+		polarity = 1; /* active low */
+	if (mp_set_pin_attr(ioapic, dev->irq, 1, polarity, dev_to_node(dev)))
+		return -EBUSY;
+	mp_map_gsi_to_irq(dev->irq, 1);
 
 	return 0;
 }
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
index 994c40bd7cb7..3fe5c23ba1c5 100644
--- a/arch/x86/platform/intel-mid/sfi.c
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -434,6 +434,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 	struct devs_id *dev = NULL;
 	int num, i;
 	int ioapic;
+	int polarity;
 	struct io_apic_irq_attr irq_attr;
 
 	sb = (struct sfi_table_simple *)table;
@@ -450,30 +451,29 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 			 */
 			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;
+						polarity = 1;
 					else if (!strncmp(pentry->name,
 							"synaptics_3202", 14))
 						/* active low */
-						irq_attr.polarity = 1;
+						polarity = 1;
 					else if (irq == 41)
 						/* fast_int_1 */
-						irq_attr.polarity = 1;
+						polarity = 1;
 					else
 						/* active high */
-						irq_attr.polarity = 0;
+						polarity = 0;
 				} else {
 					/* PNW and CLV go with active low */
-					irq_attr.polarity = 1;
+					polarity = 1;
 				}
-				io_apic_set_pci_routing(NULL, irq, &irq_attr);
+				if (mp_set_pin_attr(ioapic, irq, 1, polarity, NUMA_NO_NODE))
+					return -EBUSY;
+				mp_map_gsi_to_irq(dev->irq, 1);
 			}
 		} else {
 			irq = 0; /* No irq */
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index 2c3522dfa05d..91e5046efae9 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] 37+ messages in thread

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

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 |   12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index a44d45df49f5..3bd30eb92d9d 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;
 
 	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;
+	if (mp_set_pin_attr(idx, line, 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] 37+ messages in thread

* [RFC Patch Part1 V1 30/30] x86, irq: clean up unused IOAPIC interface
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (28 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 29/30] x86, irq, devicetree: " Jiang Liu
@ 2014-05-16  8:05 ` Jiang Liu
  2014-05-16 15:01 ` [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Yinghai Lu
  2014-05-16 15:28 ` Thomas Gleixner
  31 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-16  8:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, 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, sfi-devel, Ingo Molnar

Now we have converted all x86 platforms to use the common irqdomain map
interface, and there are only two callers of io_apic_setup_irq_pin():
mp_irqdomain_map() and pre_init_apic_IRQ0().

There's no caller of io_apic_set_pci_routing(), setup_IO_APIC_irq_extra()
and io_apic_setup_irq_pin_once(), 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 |  145 +++++-----------------------------------
 2 files changed, 16 insertions(+), 138 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 2f37df00d6f8..0fc54499f21a 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -142,9 +142,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 *,
@@ -156,8 +153,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);
@@ -231,10 +226,6 @@ static inline int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc)
 	return -1;
 }
 
-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 0489fb2393ec..3d168a720f56 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
@@ -209,9 +208,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)
 {
@@ -1082,9 +1078,6 @@ int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc)
 
 static int pin_2_irq(int idx, int apic, int pin, int alloc)
 {
-	int irq;
-	int bus = mp_irqs[idx].srcbus;
-
 	/*
 	 * Debugging check, we are in big trouble if this message pops up!
 	 */
@@ -1096,6 +1089,8 @@ static int pin_2_irq(int idx, int apic, int pin, int alloc)
 	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
 	 */
 	if ((pin >= 16) && (pin <= 23)) {
+		int irq;
+
 		if (pirq_entries[pin-16] != -1) {
 			if (!pirq_entries[pin-16]) {
 				apic_printk(APIC_VERBOSE, KERN_DEBUG
@@ -1111,12 +1106,7 @@ static int pin_2_irq(int idx, int apic, int pin, int alloc)
 	}
 #endif
 
-	if (test_bit(bus, mp_bus_not_pci))
-		irq = mp_irqs[idx].srcbusirq;
-	else
-		irq = mp_map_pin_to_irq(idx, apic, pin, alloc);
-
-	return irq;
+	return mp_map_pin_to_irq(idx, apic, pin, alloc);
 }
 
 /*
@@ -1482,90 +1472,24 @@ 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) {
-		if (!mp_init_pin_at_boot(ioapic_idx, pin))
-			continue;
-
-		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, 1);
-		if (irq < 0)
-			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;
+	int idx;
+	unsigned int ioapic, pin;
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-	for_each_ioapic(ioapic_idx)
-		__io_apic_setup_irqs(ioapic_idx);
-}
-
-/*
- * 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);
-	if (mp_init_pin_at_boot(ioapic_idx, pin))
-		return;
-
-	idx = find_irq_entry(ioapic_idx, pin, mp_INT);
-	if (idx == -1)
-		return;
-
-	irq = pin_2_irq(idx, ioapic_idx, pin, 1);
-
-	set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
-			     irq_polarity(idx));
+	for_each_ioapic_pin(ioapic, pin) {
+		if (!mp_init_pin_at_boot(ioapic, pin))
+			continue;
 
-	io_apic_setup_irq_pin_once(irq, node, &attr);
+		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, 1);
+	}
 }
 
 /*
@@ -3512,27 +3436,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;
@@ -3579,22 +3482,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)
 {
@@ -4015,7 +3902,7 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 	 * returns 1:
 	 */
 	if (apic->multi_timer_check &&
-	    apic->multi_timer_check(ioapic, hwirq))
+	    apic->multi_timer_check(ioapic, virq))
 		return 0;
 
 	/* Get default attribute if not set by caller yet */
-- 
1.7.10.4


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

* Re: [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (29 preceding siblings ...)
  2014-05-16  8:05 ` [RFC Patch Part1 V1 30/30] x86, irq: clean up unused IOAPIC interface Jiang Liu
@ 2014-05-16 15:01 ` Yinghai Lu
  2014-05-18  8:58   ` Jiang Liu
  2014-05-16 15:28 ` Thomas Gleixner
  31 siblings, 1 reply; 37+ messages in thread
From: Yinghai Lu @ 2014-05-16 15:01 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, the arch/x86 maintainers,
	Linux Kernel Mailing List, linux-pci, ACPI Devel Maling List,
	sfi-devel

On Fri, May 16, 2014 at 1:05 AM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
> On x86 platforms, IRQ number are statically allocated to IOAPIC pins at boot.
> There are two issues with this design. First it causes trouble to IOAPIC
> hotplug because we need to allocate a block of IRQ numbers for each IOAPIC.
> Second it may waste IRQ nubmers even if some IOAPIC pins are not used because
> IRQ numbers are statically assigned.
>
> This patchset tries to enable dynamic IRQ number allocation for IOAPIC
> by adopting the irqdomain framework, it solves the two issues mentioned
> above. It also simplifies the IOAPIC driver by consolidating ways to
> program IOAPIC pins with the irqdomain map interface.
>
> We will enhance the IOAPIC driver core to support ACPI based IOAPIC hotplug
> once the IOAPIC driver has been converted to irqdomain.
>
> This patchset applies to v3.15-rc4-260-g38583f095c5a and 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)

Great. I don't need to look into using irqdomain for x86 by myself.

Thomas put some irq clean up patches in tip irq branch.

Can you rebase your irqdomain/for x86 on top of that?
Also would be better if you can put your patches in git branch.

Thanks

Yinghai

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

* Re: [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin
  2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
                   ` (30 preceding siblings ...)
  2014-05-16 15:01 ` [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Yinghai Lu
@ 2014-05-16 15:28 ` Thomas Gleixner
  2014-05-18  9:36   ` Jiang Liu
  31 siblings, 1 reply; 37+ messages in thread
From: Thomas Gleixner @ 2014-05-16 15:28 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Ingo Molnar, H. Peter Anvin,
	Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap, Yinghai Lu,
	Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, linux-kernel, linux-pci,
	linux-acpi, sfi-devel

Jiang,

On Fri, 16 May 2014, Jiang Liu wrote:

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

Thanks for tackling this!
 
> This patchset applies to v3.15-rc4-260-g38583f095c5a and has been tested

That's a bit unfortunate, as there are conflicting changes in the tip
tree irq/core branch. Can you please rebase on top of that.

> TODO list:
> 1) check whether it affects Xen or not
> 
> Patch 1-17 are trivial code improvements, bugfixes and preparation.

Can you please move the bugfixes before the other changes, so we can
pick them up independently from the outcome?
 
> Patch 18-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 cleans up unused interfaces and functions in IOAPIC driver.
> 
> Tests and comments are warmly welcomed!

I like the general approach, but we have now a mixture of legacy irq
handling and irq domains. We really want to cleanup the legacy PIC no
ioapic case as well. That will cleanup the code further.

The other thing we discussed here: https://lkml.org/lkml/2014/5/7/901
in several places of the thread is to move the vector allocation into
a irqdomain with a generic matrix allocator as well. We have other use
cases for this as well. It would be nice if you could look at that as
well.

Thanks,

	tglx





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

* Re: [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin
  2014-05-16 15:01 ` [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Yinghai Lu
@ 2014-05-18  8:58   ` Jiang Liu
  0 siblings, 0 replies; 37+ messages in thread
From: Jiang Liu @ 2014-05-18  8:58 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
	Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, the arch/x86 maintainers,
	Linux Kernel Mailing List, linux-pci, ACPI Devel Maling List,
	sfi-devel



On 2014/5/16 23:01, Yinghai Lu wrote:
> On Fri, May 16, 2014 at 1:05 AM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
>> On x86 platforms, IRQ number are statically allocated to IOAPIC pins at boot.
>> There are two issues with this design. First it causes trouble to IOAPIC
>> hotplug because we need to allocate a block of IRQ numbers for each IOAPIC.
>> Second it may waste IRQ nubmers even if some IOAPIC pins are not used because
>> IRQ numbers are statically assigned.
>>
>> This patchset tries to enable dynamic IRQ number allocation for IOAPIC
>> by adopting the irqdomain framework, it solves the two issues mentioned
>> above. It also simplifies the IOAPIC driver by consolidating ways to
>> program IOAPIC pins with the irqdomain map interface.
>>
>> We will enhance the IOAPIC driver core to support ACPI based IOAPIC hotplug
>> once the IOAPIC driver has been converted to irqdomain.
>>
>> This patchset applies to v3.15-rc4-260-g38583f095c5a and 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)
> 
> Great. I don't need to look into using irqdomain for x86 by myself.
> 
> Thomas put some irq clean up patches in tip irq branch.
> 
> Can you rebase your irqdomain/for x86 on top of that?
> Also would be better if you can put your patches in git branch.
Hi Yinghai,
	I have rebased to tip/irq/core branch and will send out new patch set
after basic tests. I have no account at kernel.org, so will
try to setup a gate on github next time.
Thanks!
> 
> Thanks
> 
> Yinghai
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin
  2014-05-16 15:28 ` Thomas Gleixner
@ 2014-05-18  9:36   ` Jiang Liu
  2014-05-19 14:04     ` Thomas Gleixner
  0 siblings, 1 reply; 37+ messages in thread
From: Jiang Liu @ 2014-05-18  9:36 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Benjamin Herrenschmidt, Ingo Molnar, H. Peter Anvin,
	Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap, Yinghai Lu,
	Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, linux-kernel, linux-pci,
	linux-acpi, sfi-devel

Hi Thomas,
	Thanks for review and please refer to inline comments below.

On 2014/5/16 23:28, Thomas Gleixner wrote:
> Jiang,
> 
> On Fri, 16 May 2014, Jiang Liu wrote:
> 
>> On x86 platforms, IRQ number are statically allocated to IOAPIC pins at boot.
>> There are two issues with this design. First it causes trouble to IOAPIC
>> hotplug because we need to allocate a block of IRQ numbers for each IOAPIC.
>> Second it may waste IRQ nubmers even if some IOAPIC pins are not used because
>> IRQ numbers are statically assigned.
>>
>> This patchset tries to enable dynamic IRQ number allocation for IOAPIC
>> by adopting the irqdomain framework, it solves the two issues mentioned
>> above. It also simplifies the IOAPIC driver by consolidating ways to
>> program IOAPIC pins with the irqdomain map interface.
>>
>> We will enhance the IOAPIC driver core to support ACPI based IOAPIC hotplug
>> once the IOAPIC driver has been converted to irqdomain.
> 
> Thanks for tackling this!
>  
>> This patchset applies to v3.15-rc4-260-g38583f095c5a and has been tested
> 
> That's a bit unfortunate, as there are conflicting changes in the tip
> tree irq/core branch. Can you please rebase on top of that.
I have rebased onto tip/irq/core. The conflict is easy to solve.

> 
>> TODO list:
>> 1) check whether it affects Xen or not
>>
>> Patch 1-17 are trivial code improvements, bugfixes and preparation.
> 
> Can you please move the bugfixes before the other changes, so we can
> pick them up independently from the outcome?
Sure, will reorder the patch set in next version.

>  
>> Patch 18-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 cleans up unused interfaces and functions in IOAPIC driver.
>>
>> Tests and comments are warmly welcomed!
> 
> I like the general approach, but we have now a mixture of legacy irq
> handling and irq domains. We really want to cleanup the legacy PIC no
> ioapic case as well. That will cleanup the code further.
> 
> The other thing we discussed here: https://lkml.org/lkml/2014/5/7/901
> in several places of the thread is to move the vector allocation into
> a irqdomain with a generic matrix allocator as well. We have other use
> cases for this as well. It would be nice if you could look at that as
> well.
I have read through the thread, it's an interesting discussion.

After my first thought, I have gotten some ideas about how to reorganize
x86 interrupt subsystem using irqdomain framework based on ideas from
the thread. Because I'm newbie to interrupt subsystem, I will share my
naive ideas first and RFC for whether it's the right direction.

We may build hierarchy irqdomains as below for x86,
[IOAPIC]      [MSI/MSI-x]  [HPET]  [DMAR] [Legacy]
    |            |           |       |       |
    v            v           v       |       |
[           Remapping           ]    |       |
                 |                   |       |
                 v                   v       v
[                   Root/vector                ]

The remapping domain is optional and used to support IRQ remapping unit.
We abstract remapping entry as hardware interrupt pin and will extend
irqdomain interface to support automatic assignment of hardware
interrupt pin.

The root/vector domain is used to manage per CPU vector numbers and
CPU vector is abstracted as hardware interrupt pin. It will support
automatic vector number assignment. To support root/vector domain,
we need to extend irqdomain interface to pass down information
or constraints about the IRQ allocation.

So how about following extension to current irqdomain interfaces?
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index c983ed18c332..2fd7e50cde32 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -42,6 +42,13 @@ struct of_device_id;
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS     16

+#define        IRQDOMAIN_AUTO_ASSIGN_HWIRQ     ULONG_MAX
+#ifdef arch_irq_alloc_info_t
+typedef        arch_irq_alloc_info_t irq_alloc_info_t;
+#else
+typedef        void irq_alloc_info_t;
+#endif
+
 /**
  * struct irq_domain_ops - Methods for irq_domain objects
  * @match: Match an interrupt controller device node to a host, returns
@@ -59,7 +66,11 @@ struct of_device_id;
  */
 struct irq_domain_ops {
        int (*match)(struct irq_domain *d, struct device_node *node);
-       int (*map)(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw);
+       int (*alloc)(struct irq_domain *d, irq_hw_number_t hw,
+                    irq_alloc_info_t *info);
+       int (*free)(struct irq_domain *d, unsigned int virq);
+       int (*map)(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw,
+                  irq_alloc_info_t *info);
        void (*unmap)(struct irq_domain *d, unsigned int virq);
        int (*xlate)(struct irq_domain *d, struct device_node *node,
                     const u32 *intspec, unsigned int intsize,

alloc()/free() interfaces will be used allocate/free IRQ from parent
domain. And irq_alloc_info_t structure is used to host parameters
and constraints for IRQ allocation.

For x86, irq_alloc_info_t structure will be used to host CPU mask,
device pointer, IOAPIC pin attributes, NUMA node info etc.
But I still more thoughts about how to convert set_affinity() to
use irqdomain interfaces.

Any comments about the proposal?
Best regards!
Gerry
> 
> Thanks,
> 
> 	tglx
> 
> 
> 
> 

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

* Re: [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin
  2014-05-18  9:36   ` Jiang Liu
@ 2014-05-19 14:04     ` Thomas Gleixner
  2014-05-19 23:35       ` Thomas Gleixner
  0 siblings, 1 reply; 37+ messages in thread
From: Thomas Gleixner @ 2014-05-19 14:04 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Ingo Molnar, H. Peter Anvin,
	Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap, Yinghai Lu,
	Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, LKML, linux-pci,
	linux-acpi, sfi-devel, Grant Likely

Jiang,

On Sun, 18 May 2014, Jiang Liu wrote:
> On 2014/5/16 23:28, Thomas Gleixner wrote:
> >> Patch 1-17 are trivial code improvements, bugfixes and preparation.
> > 
> > Can you please move the bugfixes before the other changes, so we can
> > pick them up independently from the outcome?
> Sure, will reorder the patch set in next version.

Thanks.
 
> >  
> >> Patch 18-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 cleans up unused interfaces and functions in IOAPIC driver.
> >>
> >> Tests and comments are warmly welcomed!
> > 
> > I like the general approach, but we have now a mixture of legacy irq
> > handling and irq domains. We really want to cleanup the legacy PIC no
> > ioapic case as well. That will cleanup the code further.
> > 
> > The other thing we discussed here: https://lkml.org/lkml/2014/5/7/901
> > in several places of the thread is to move the vector allocation into
> > a irqdomain with a generic matrix allocator as well. We have other use
> > cases for this as well. It would be nice if you could look at that as
> > well.
> I have read through the thread, it's an interesting discussion.
> 
> After my first thought, I have gotten some ideas about how to reorganize
> x86 interrupt subsystem using irqdomain framework based on ideas from
> the thread. Because I'm newbie to interrupt subsystem, I will share my
> naive ideas first and RFC for whether it's the right direction.
> 
> We may build hierarchy irqdomains as below for x86,
> [IOAPIC]      [MSI/MSI-x]  [HPET]  [DMAR] [Legacy]
>     |            |           |       |       |
>     v            v           v       |       |
> [           Remapping           ]    |       |
>                  |                   |       |
>                  v                   v       v
> [                   Root/vector                ]
> 
> The remapping domain is optional and used to support IRQ remapping unit.
> We abstract remapping entry as hardware interrupt pin and will extend
> irqdomain interface to support automatic assignment of hardware
> interrupt pin.
> 
> The root/vector domain is used to manage per CPU vector numbers and
> CPU vector is abstracted as hardware interrupt pin. It will support
> automatic vector number assignment. To support root/vector domain,
> we need to extend irqdomain interface to pass down information
> or constraints about the IRQ allocation.
> 
> So how about following extension to current irqdomain interfaces?

I cc'ed Grant Likely. He might have some opinion on this as well.

> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index c983ed18c332..2fd7e50cde32 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -42,6 +42,13 @@ struct of_device_id;
>  /* Number of irqs reserved for a legacy isa controller */
>  #define NUM_ISA_INTERRUPTS     16
> 
> +#define        IRQDOMAIN_AUTO_ASSIGN_HWIRQ     ULONG_MAX
> +#ifdef arch_irq_alloc_info_t
> +typedef        arch_irq_alloc_info_t irq_alloc_info_t;
> +#else
> +typedef        void irq_alloc_info_t;
> +#endif
> 
>  /**
>   * struct irq_domain_ops - Methods for irq_domain objects
>   * @match: Match an interrupt controller device node to a host, returns
> @@ -59,7 +66,11 @@ struct of_device_id;
>   */
>  struct irq_domain_ops {
>         int (*match)(struct irq_domain *d, struct device_node *node);
> -       int (*map)(struct irq_domain *d, unsigned int virq,
> irq_hw_number_t hw);
> +       int (*alloc)(struct irq_domain *d, irq_hw_number_t hw,
> +                    irq_alloc_info_t *info);
> +       int (*free)(struct irq_domain *d, unsigned int virq);
> +       int (*map)(struct irq_domain *d, unsigned int virq,
> irq_hw_number_t hw,
> +                  irq_alloc_info_t *info);
>         void (*unmap)(struct irq_domain *d, unsigned int virq);
>         int (*xlate)(struct irq_domain *d, struct device_node *node,
>                      const u32 *intspec, unsigned int intsize,
> 
> alloc()/free() interfaces will be used allocate/free IRQ from parent
> domain. And irq_alloc_info_t structure is used to host parameters
> and constraints for IRQ allocation.
> 
> For x86, irq_alloc_info_t structure will be used to host CPU mask,
> device pointer, IOAPIC pin attributes, NUMA node info etc.

Do we really need to hand all of this down?

Thanks,

	tglx

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

* Re: [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin
  2014-05-19 14:04     ` Thomas Gleixner
@ 2014-05-19 23:35       ` Thomas Gleixner
  0 siblings, 0 replies; 37+ messages in thread
From: Thomas Gleixner @ 2014-05-19 23:35 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Ingo Molnar, H. Peter Anvin,
	Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap, Yinghai Lu,
	Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, LKML, linux-pci,
	linux-acpi, sfi-devel, Grant Likely

Jiang,

On Mon, 19 May 2014, Thomas Gleixner wrote:
> > We may build hierarchy irqdomains as below for x86,
> > [IOAPIC]      [MSI/MSI-x]  [HPET]  [DMAR] [Legacy]
> >     |            |           |       |       |
> >     v            v           v       |       |
> > [           Remapping           ]    |       |
> >                  |                   |       |
> >                  v                   v       v
> > [                   Root/vector                ]
> > 
> > For x86, irq_alloc_info_t structure will be used to host CPU mask,
> > device pointer, IOAPIC pin attributes, NUMA node info etc.
> 
> Do we really need to hand all of this down?

having recovered from a 24hr travel, I think we really only need to
hand down cpumask.

If you want to allocate a vector, all the vector domain needs to know
is the cpumask and the number of consecutive vectors you want to
allocate.

The IOAPIC pin attribute is only interesting inside the ioapic domain,
there is no need to have it elsewhere.

Numa node is encoded in the cpumask, IOW the node info selects only
bits for that node in the mask.

Same for the device. It's only relevant for setting up MSI[x] or
legacy PCI interrupts. But the underlying vector domain does not care
at all about it.

Thanks,

	tglx

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

end of thread, other threads:[~2014-05-19 23:35 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-16  8:05 [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 01/30] genirq, trivial: improve documentation to match current implementation Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 02/30] x86, mpparse: use pr_lvl() helper utilities to replace printk(KERN_LVL) Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 03/30] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 04/30] x86, PCI, ACPI: use kmalloc_node() to optimize for performance Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 05/30] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 06/30] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 07/30] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 08/30] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 09/30] x86, irq, trivial: minor improvements of IRQ related code Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 10/30] x86, ioapic: kill unused global variable timer_through_8259 Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 11/30] x86, ioapic: replace get_nr_irqs_gsi() with arch_dynirq_lower_bound(0) Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 12/30] x86, ioapic: kill static variable nr_irqs_gsi Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 13/30] x86, ioapic: introduce helper utilities to walk ioapics and pins Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 14/30] x86, ioapic: use irq_cfg() instead of irq_get_chip_data() for better readability Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 15/30] x86, irq: update high address field when updating affinity for MSI IRQ Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 16/30] x86, irq: reorganize IO_APIC_get_PCI_irq_vector() to prepare for irqdomain Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 17/30] x86, irq: introduce some helper utilities to improve readability Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 18/30] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 19/30] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 20/30] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 21/30] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 22/30] x86, mpparse, " Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 23/30] x86, devicetree, irq: use common mechanism to support irqdomain Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 24/30] x86, SFI, irq: provide basic irqdomain support Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 25/30] x86, irq: introduce two helper functions to support irqdomain map operation Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 26/30] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 27/30] x86, irq, mpparse: " Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 28/30] x86, irq, SFI: " Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 29/30] x86, irq, devicetree: " Jiang Liu
2014-05-16  8:05 ` [RFC Patch Part1 V1 30/30] x86, irq: clean up unused IOAPIC interface Jiang Liu
2014-05-16 15:01 ` [RFC Patch Part1 V1 00/30] use irqdomain to dynamically allocate IRQ for IOAPIC pin Yinghai Lu
2014-05-18  8:58   ` Jiang Liu
2014-05-16 15:28 ` Thomas Gleixner
2014-05-18  9:36   ` Jiang Liu
2014-05-19 14:04     ` Thomas Gleixner
2014-05-19 23:35       ` Thomas Gleixner

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