Skip to contentSkip to conversation

Convert x86 to hierarchy irqdomain and stacked irqchip

PATCH In review Jiang Liu 5 participants 77 messages Apr 13, 2015 – Apr 24, 2015

Subsystems (7)
x86 ACPI PCI IOMMU +3 more subsystems
lore
Share & tools
lore

Jiang Liu

author
#0 lore raw

v8 cover Convert x86 to hierarchy irqdomain and stacked irqchip

Hi all,
The generic hierarchy irqdomain and stacked irqchip implementation
has been merged into v3.19, so this patch set converts x86 interupt management to hierarchy irqdomain and stacked irqchip. You may access it at:
https://github.com/jiangliu/linux.git irqdomain/x86_p1_v8

This patch set has been reviewed several times and it missed v3.19
merging because several bugs got fixed just before the merging window. The main changes since last review are:
1) Rebased the patch set onto v4.0-rc6.
2) Merged bugfixes into the patch introducing the bug so they don't break bisecting.

I will send out another following-on patch set to clean up code and interfaces obseleted by this patch set.

Jiang Liu (36):
x86/irq: Save destination CPU ID in irq_cfg
x86/irq: Use hierarchy irqdomain to manage CPU interrupt vectors x86/hpet: Use new irqdomain interfaces to allocate/free IRQ x86/MSI: Use new irqdomain interfaces to allocate/free IRQ x86/uv: Use new irqdomain interfaces to allocate/free IRQ x86/htirq: Use new irqdomain interfaces to allocate/free IRQ x86/dmar: Use new irqdomain interfaces to allocate/free IRQ
irq_remapping: Introduce new interfaces to support hierarchy
irqdomain
irq_remapping/vt-d: Change prototypes to prepare for enabling
hierarchy irqdomain
irq_remapping/vt-d: Enhance Intel IR driver to support hierarchy
irqdomain
irq_remapping/amd: Enhance AMD IR driver to support hierarchy
irqdomain
x86/hpet: Enhance HPET IRQ to support hierarchy irqdomain x86/MSI: Use hierarchy irqdomain to manage MSI interrupts x86/irq: Directly call native_compose_msi_msg() for DMAR IRQ irq_remapping/vt-d: Clean up unused MSI related code irq_remapping/amd: Clean up unused MSI related code
irq_remapping: Clean up unused MSI related code
x86/MSI: Clean up unused MSI related code and interfaces iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit x86/irq: Use hierarchy irqdomain to manage DMAR interrupts x86/htirq: Use hierarchy irqdomain to manage Hypertransport
interrupts
x86/uv: Use hierarchy irqdomain to manage UV interrupts x86/irq: Normalize x86 irq_chip name
x86/MSI: Simplify the way to deal with remapped MSI interrupts x86/MSI: Replace msi_update_msg() with irq_chip_compose_msi_msg() x86/irq: Implement irq_chip.irq_write_msi_msg for MSI/DMAR/HPET
irq_chips
x86/irq: Simplify MSI/DMAR/HPET implementation by using common code
irq_remapping: Kill unused function irq_remapping_print_chip() x86/intel-mid, trivial: Refine code syntax for sfi_parse_mtmr() x86/irq: Kill unused pre_init_apic_IRQ0()
x86/irq: Prepare IOAPIC interfaces to support hierarchy irqdomain x86/irq: Implement callbacks to enable hierarchy irqdomain on IOAPICs x86/irq: Refine the way to allocate irq_cfg for legacy IRQs x86/irq: Simplify the way to print IOAPIC entry
x86/irq: Introduce helper functions to support hierarchy irqdomain
for IOAPIC
x86/irq: Convert IOAPIC to use hierarchy irqdomain interfaces

Thomas Gleixner (1):
x86/intel-mid: Delay initialization of APB timer

 arch/ia64/include/asm/irq_remapping.h              |    2 -
 arch/ia64/kernel/msi_ia64.c                        |   30 +-
 arch/x86/Kconfig                                   |    4 +-
 arch/x86/include/asm/hpet.h                        |   16 +-
 arch/x86/include/asm/hw_irq.h                      |   91 +++
 arch/x86/include/asm/io_apic.h                     |   25 +-
 arch/x86/include/asm/irq_remapping.h               |   45 +-
 arch/x86/include/asm/msi.h                         |    7 +
 arch/x86/include/asm/pci.h                         |    5 -
 arch/x86/include/asm/x86_init.h                    |    4 -
 arch/x86/kernel/acpi/boot.c                        |   17 +-
 arch/x86/kernel/apb_timer.c                        |    4 -
 arch/x86/kernel/apic/htirq.c                       |  173 ++++--
 arch/x86/kernel/apic/io_apic.c                     |  602 +++++++++++++++-----
 arch/x86/kernel/apic/msi.c                         |  416 ++++++++------
 arch/x86/kernel/apic/vector.c                      |  205 ++++++-
 arch/x86/kernel/devicetree.c                       |   37 +-
 arch/x86/kernel/hpet.c                             |   57 +-
 arch/x86/kernel/mpparse.c                          |    6 +-
 arch/x86/kernel/x86_init.c                         |    2 -
 arch/x86/pci/intel_mid_pci.c                       |    6 +-
 .../platform/intel-mid/device_libs/platform_wdt.c  |    5 +-
 arch/x86/platform/intel-mid/intel-mid.c            |   18 +-
 arch/x86/platform/intel-mid/sfi.c                  |   30 +-
 arch/x86/platform/sfi/sfi.c                        |    5 +-
 arch/x86/platform/uv/uv_irq.c                      |  299 ++++------
 drivers/iommu/amd_iommu.c                          |  376 +++++++++---
 drivers/iommu/amd_iommu_init.c                     |    4 +
 drivers/iommu/amd_iommu_proto.h                    |    9 +
 drivers/iommu/amd_iommu_types.h                    |    5 +
 drivers/iommu/dmar.c                               |   19 +-
 drivers/iommu/intel_irq_remapping.c                |  451 ++++++++++-----
 drivers/iommu/irq_remapping.c                      |  178 ++----
 drivers/iommu/irq_remapping.h                      |   20 +-
 drivers/pci/htirq.c                                |   48 +-
 include/linux/dmar.h                               |    3 +-
 include/linux/htirq.h                              |   22 +-
 include/linux/intel-iommu.h                        |    4 +
 38 files changed, 2100 insertions(+), 1150 deletions(-)
 create mode 100644 arch/x86/include/asm/msi.h
Signature · 1 line
1.7.10.4
author
#1 lore raw

PATCH v8 1/37 x86/irq: Save destination CPU ID in irq_cfg

Cache destination CPU APIC ID into struct irq_cfg when assigning vector for interrupt. Upper layer just needs to read the cached APIC ID instead of calling apic->cpu_mask_to_apicid_and(), it helps to hide APIC driver details from IOAPIC/HPET/MSI drivers..

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/include/asm/hw_irq.h |    1 +
 arch/x86/kernel/apic/vector.c |    6 ++++++
 2 files changed, 7 insertions(+)
arch/x86/include/asm/hw_irq.h +1 -0
index 9662290e0b20..b988ddf7434b 100644
@@ -116,6 +116,7 @@ struct irq_data;
 struct irq_cfg {
 	cpumask_var_t		domain;
 	cpumask_var_t		old_domain;
+	unsigned int		dest_apicid;
 	u8			vector;
 	u8			move_in_progress : 1;
 #ifdef CONFIG_IRQ_REMAP
arch/x86/kernel/apic/vector.c +6 -0
index 6cedd7914581..c724ef6b218c 100644
@@ -188,6 +188,12 @@ next:
 	}
 	free_cpumask_var(tmp_mask);
 
+	if (!err) {
+		/* cache destination APIC IDs into cfg->dest_apicid */
+		err = apic->cpu_mask_to_apicid_and(mask, cfg->domain,
+						   &cfg->dest_apicid);
+	}
+
 	return err;
 }
 
Signature · 1 line
1.7.10.4
#2 lore raw

[tip:x86/apic] x86/irq: Save destination CPU ID in irq_cfg

x86/irq: Save destination CPU ID in irq_cfg
Commit-ID:  5f0052f9522b84269e1b3b435a806f873d992702
Gitweb:     http://git.kernel.org/tip/5f0052f9522b84269e1b3b435a806f873d992702
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:23 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:47 +0200

x86/irq: Save destination CPU ID in irq_cfg

Cache destination CPU APIC ID into struct irq_cfg when assigning vector for interrupt. Upper layer just needs to read the cached APIC ID instead of calling apic->cpu_mask_to_apicid_and(), it helps to hide APIC driver details from IOAPIC/HPET/MSI drivers..

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/include/asm/hw_irq.h | 1 +
 arch/x86/kernel/apic/vector.c | 6 ++++++
 2 files changed, 7 insertions(+)
arch/x86/include/asm/hw_irq.h +1 -0
index e9571dd..cda9695 100644
@@ -116,6 +116,7 @@ struct irq_data;
 struct irq_cfg {
 	cpumask_var_t		domain;
 	cpumask_var_t		old_domain;
+	unsigned int		dest_apicid;
 	u8			vector;
 	u8			move_in_progress : 1;
 #ifdef CONFIG_IRQ_REMAP
arch/x86/kernel/apic/vector.c +6 -0
index 6cedd79..c724ef6 100644
@@ -188,6 +188,12 @@ next:
 	}
 	free_cpumask_var(tmp_mask);
 
+	if (!err) {
+		/* cache destination APIC IDs into cfg->dest_apicid */
+		err = apic->cpu_mask_to_apicid_and(mask, cfg->domain,
+						   &cfg->dest_apicid);
+	}
+
 	return err;
 }
 
author
#3 lore raw

PATCH v8 2/37 x86/irq: Use hierarchy irqdomain to manage CPU interrupt vectors

In reply to Jiang Liu

Abstract CPU local APIC as an interrupt controller and create an irqdomain for it to manage CPU interrupt vectors. It's the base to enable hierarchy irqdomain on x86 systems. Eventually we will build a irqdomain hierarchy as below:

IOAPIC domain-------|
MSI/MSI-x domain------> [Inerrupt Remapping domain] -> CPU vector domain

HPET_IRQ domain_____|                                         ^
DMAR domain---------------------------------------------------|
HT_IRQ domain-------------------------------------------------|
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/Kconfig               |    3 +-
 arch/x86/include/asm/hw_irq.h  |   17 +++++
 arch/x86/kernel/apic/io_apic.c |    3 -
 arch/x86/kernel/apic/vector.c  |  156 ++++++++++++++++++++++++++++++++++++----
 4 files changed, 161 insertions(+), 18 deletions(-)
arch/x86/Kconfig +1 -2
index b7d31ca55187..2ca708961a3c 100644
@@ -460,7 +460,6 @@ config X86_INTEL_CE
 	select X86_REBOOTFIXUPS
 	select OF
 	select OF_EARLY_FLATTREE
-	select IRQ_DOMAIN
 	---help---
 	  Select for the Intel CE media processor (CE4100) SOC.
 	  This option compiles in support for the CE4100 SOC for settop
@@ -923,11 +922,11 @@ config X86_LOCAL_APIC
 	def_bool y
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
 	select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+	select IRQ_DOMAIN_HIERARCHY
 
 config X86_IO_APIC
 	def_bool X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
 	depends on X86_LOCAL_APIC
-	select IRQ_DOMAIN
 
 config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
 	bool "Reroute for broken boot IRQs"
arch/x86/include/asm/hw_irq.h +17 -0
index b988ddf7434b..eb7692c9ab93 100644
@@ -112,6 +112,17 @@ struct irq_2_irte {
 
 #ifdef	CONFIG_X86_LOCAL_APIC
 struct irq_data;
+struct irq_domain;
+
+struct irq_alloc_info {
+	u32			flags;
+	const struct cpumask	*mask;	/* CPU mask for vector allocation */
+};
+
+enum {
+	/* Allocate contigious CPU vectors */
+	X86_IRQ_ALLOC_CONTIGOUS_VECTORS		= 0x1,
+};
 
 struct irq_cfg {
 	cpumask_var_t		domain;
@@ -135,6 +146,12 @@ struct irq_cfg {
 	};
 };
 
+extern struct irq_domain *x86_vector_domain;
+
+extern void init_irq_alloc_info(struct irq_alloc_info *info,
+				const struct cpumask *mask);
+extern void copy_irq_alloc_info(struct irq_alloc_info *dst,
+				struct irq_alloc_info *src);
 extern struct irq_cfg *irq_cfg(unsigned int irq);
 extern struct irq_cfg *irqd_cfg(struct irq_data *irq_data);
 extern struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node);
arch/x86/kernel/apic/io_apic.c +0 -3
index f4dc2462a1ac..56d532106ef3 100644
@@ -2356,9 +2356,6 @@ static int mp_irqdomain_create(int ioapic)
 		ioapic_dynirq_base = max(ioapic_dynirq_base,
 					 gsi_cfg->gsi_end + 1);
 
-	if (gsi_cfg->gsi_base == 0)
-		irq_set_default_host(ip->irqdomain);
-
 	return 0;
 }
 
arch/x86/kernel/apic/vector.c +143 -13

231 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#4 lore raw

[tip:x86/apic] x86/irq: Use hierarchical irqdomain to manage CPU interrupt vectors

x86/irq: Use hierarchical irqdomain to manage CPU interrupt vectors
Commit-ID:  b5dc8e6c21e7ffba0246bf39cea97805c142bf85
Gitweb:     http://git.kernel.org/tip/b5dc8e6c21e7ffba0246bf39cea97805c142bf85
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:24 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:47 +0200

x86/irq: Use hierarchical irqdomain to manage CPU interrupt vectors

Abstract CPU local APIC as an interrupt controller and create an irqdomain for it to manage CPU interrupt vectors. It's the base to enable hierarchical irqdomains on x86 systems.

The final irqdomain hierarchy will look like this:

IOAPIC domain ----|
MSI/MSI-x domain ----> [Interrupt Remapping domain] -> CPU vector domain

HPET_IRQ domain  ----|                                         ^
                                                               |
DMAR domain      ----------------------------------------------|
HT_IRQ domain    ----------------------------------------------|
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/Kconfig               |   3 +-
 arch/x86/include/asm/hw_irq.h  |  17 +++++
 arch/x86/kernel/apic/io_apic.c |   3 -
 arch/x86/kernel/apic/vector.c  | 155 +++++++++++++++++++++++++++++++++++++----
 4 files changed, 160 insertions(+), 18 deletions(-)
arch/x86/Kconfig +1 -2
index 6049d58..e75a96c 100644
@@ -465,7 +465,6 @@ config X86_INTEL_CE
 	select X86_REBOOTFIXUPS
 	select OF
 	select OF_EARLY_FLATTREE
-	select IRQ_DOMAIN
 	---help---
 	  Select for the Intel CE media processor (CE4100) SOC.
 	  This option compiles in support for the CE4100 SOC for settop
@@ -914,11 +913,11 @@ config X86_LOCAL_APIC
 	def_bool y
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
 	select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+	select IRQ_DOMAIN_HIERARCHY
 
 config X86_IO_APIC
 	def_bool y
 	depends on X86_LOCAL_APIC || X86_UP_IOAPIC
-	select IRQ_DOMAIN
 
 config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
 	bool "Reroute for broken boot IRQs"
arch/x86/include/asm/hw_irq.h +17 -0
index cda9695..5b951ac 100644
@@ -112,6 +112,17 @@ struct irq_2_irte {
 
 #ifdef	CONFIG_X86_LOCAL_APIC
 struct irq_data;
+struct irq_domain;
+
+struct irq_alloc_info {
+	u32			flags;
+	const struct cpumask	*mask;	/* CPU mask for vector allocation */
+};
+
+enum {
+	/* Allocate contiguous CPU vectors */
+	X86_IRQ_ALLOC_CONTIGUOUS_VECTORS		= 0x1,
+};
 
 struct irq_cfg {
 	cpumask_var_t		domain;
@@ -135,6 +146,12 @@ struct irq_cfg {
 	};
 };
 
+extern struct irq_domain *x86_vector_domain;
+
+extern void init_irq_alloc_info(struct irq_alloc_info *info,
+				const struct cpumask *mask);
+extern void copy_irq_alloc_info(struct irq_alloc_info *dst,
+				struct irq_alloc_info *src);
 extern struct irq_cfg *irq_cfg(unsigned int irq);
 extern struct irq_cfg *irqd_cfg(struct irq_data *irq_data);
 extern struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node);
arch/x86/kernel/apic/io_apic.c +0 -3
index f4dc246..56d5321 100644
@@ -2356,9 +2356,6 @@ static int mp_irqdomain_create(int ioapic)
 		ioapic_dynirq_base = max(ioapic_dynirq_base,
 					 gsi_cfg->gsi_end + 1);
 
-	if (gsi_cfg->gsi_base == 0)
-		irq_set_default_host(ip->irqdomain);
-
 	return 0;
 }
 
arch/x86/kernel/apic/vector.c +142 -13

230 lines not on this page · raw message

author
#5 lore raw

PATCH v8 3/37 x86/hpet: Use new irqdomain interfaces to allocate/free IRQ

In reply to Jiang Liu

Use new irqdomain interfaces to allocate/free IRQ for HPET, so we could kill GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Srivatsa S. Bhat <[email protected]>
Cc Andy Lutomirski <[email protected]>
---
 arch/x86/kernel/hpet.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
arch/x86/kernel/hpet.c +5 -3
index 3acbff4716b0..ae29554f57ea 100644
@@ -11,6 +11,7 @@
 #include <linux/cpu.h>
 #include <linux/pm.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 
 #include <asm/fixmap.h>
 #include <asm/hpet.h>
@@ -476,7 +477,7 @@ static int hpet_msi_next_event(unsigned long delta,
 static int hpet_setup_msi_irq(unsigned int irq)
 {
 	if (x86_msi.setup_hpet_msi(irq, hpet_blockid)) {
-		irq_free_hwirq(irq);
+		irq_domain_free_irqs(irq, 1);
 		return -EINVAL;
 	}
 	return 0;
@@ -484,9 +485,10 @@ static int hpet_setup_msi_irq(unsigned int irq)
 
 static int hpet_assign_irq(struct hpet_dev *dev)
 {
-	unsigned int irq = irq_alloc_hwirq(-1);
+	int irq;
 
-	if (!irq)
+	irq = irq_domain_alloc_irqs(NULL, 1, NUMA_NO_NODE, NULL);
+	if (irq <= 0)
 		return -EINVAL;
 
 	irq_set_handler_data(irq, dev);
Signature · 1 line
1.7.10.4
author
#6 lore raw

PATCH v8 4/37 x86/MSI: Use new irqdomain interfaces to allocate/free IRQ

In reply to Jiang Liu

Use new irqdomain interfaces to allocate/free IRQ for PCI MSI, so we could kill GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/msi.c |   14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
arch/x86/kernel/apic/msi.c +6 -8
index d6ba2d660dc5..76cc2c902176 100644
@@ -14,6 +14,7 @@
 #include <linux/dmar.h>
 #include <linux/hpet.h>
 #include <linux/msi.h>
+#include <linux/irqdomain.h>
 #include <asm/msidef.h>
 #include <asm/hpet.h>
 #include <asm/hw_irq.h>
@@ -146,23 +147,20 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	struct msi_desc *msidesc;
-	unsigned int irq;
-	int node, ret;
+	int irq, ret;
 
 	/* Multiple MSI vectors only supported with interrupt remapping */
 	if (type == PCI_CAP_ID_MSI && nvec > 1)
 		return 1;
 
-	node = dev_to_node(&dev->dev);
-
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = irq_alloc_hwirq(node);
-		if (!irq)
+		irq = irq_domain_alloc_irqs(NULL, 1, NUMA_NO_NODE, NULL);
+		if (irq <= 0)
 			return -ENOSPC;
 
 		ret = setup_msi_irq(dev, msidesc, irq, 0);
 		if (ret < 0) {
-			irq_free_hwirq(irq);
+			irq_domain_free_irqs(irq, 1);
 			return ret;
 		}
 
@@ -172,7 +170,7 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 
 void native_teardown_msi_irq(unsigned int irq)
 {
-	irq_free_hwirq(irq);
+	irq_domain_free_irqs(irq, 1);
 }
 
 #ifdef CONFIG_DMAR_TABLE
Signature · 1 line
1.7.10.4
author
#7 lore raw

PATCH v8 5/37 x86/uv: Use new irqdomain interfaces to allocate/free IRQ

In reply to Jiang Liu

Use new irqdomain interfaces to allocate/free IRQ, so we could kill GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/platform/uv/uv_irq.c |   27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)
arch/x86/platform/uv/uv_irq.c +11 -16
index 0ce673645432..474912d03f40 100644
@@ -12,6 +12,7 @@
 #include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/apic.h>
 #include <asm/uv/uv_irq.h>
@@ -130,24 +131,14 @@ static int
 arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
 		       unsigned long mmr_offset, int limit)
 {
-	const struct cpumask *eligible_cpu = cpumask_of(cpu);
 	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned long mmr_value;
 	struct uv_IO_APIC_route_entry *entry;
-	int mmr_pnode, err;
-	unsigned int dest;
+	int mmr_pnode;
 
 	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
 			sizeof(unsigned long));
 
-	err = assign_irq_vector(irq, cfg, eligible_cpu);
-	if (err != 0)
-		return err;
-
-	err = apic->cpu_mask_to_apicid_and(eligible_cpu, eligible_cpu, &dest);
-	if (err != 0)
-		return err;
-
 	if (limit == UV_AFFINITY_CPU)
 		irq_set_status_flags(irq, IRQ_NO_BALANCING);
 	else
@@ -164,7 +155,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
 	entry->polarity		= 0;
 	entry->trigger		= 0;
 	entry->mask		= 0;
-	entry->dest		= dest;
+	entry->dest		= cfg->dest_apicid;
 
 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
@@ -238,9 +229,13 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
 int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
 		 unsigned long mmr_offset, int limit)
 {
-	int ret, irq = irq_alloc_hwirq(uv_blade_to_memory_nid(mmr_blade));
+	int ret, irq;
+	struct irq_alloc_info info;
 
-	if (!irq)
+	init_irq_alloc_info(&info, cpumask_of(cpu));
+	irq = irq_domain_alloc_irqs(NULL, 1, uv_blade_to_memory_nid(mmr_blade),
+				    &info);
+	if (irq <= 0)
 		return -EBUSY;
 
 	ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset,
@@ -248,7 +243,7 @@ int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
 	if (ret == irq)
 		uv_set_irq_2_mmr_info(irq, mmr_offset, mmr_blade);
 	else
-		irq_free_hwirq(irq);
+		irq_domain_free_irqs(irq, 1);
 
 	return ret;
 }
@@ -283,6 +278,6 @@ void uv_teardown_irq(unsigned int irq)
 			n = n->rb_right;
 	}
 	spin_unlock_irqrestore(&uv_irq_lock, irqflags);
-	irq_free_hwirq(irq);
+	irq_domain_free_irqs(irq, 1);
 }
 EXPORT_SYMBOL_GPL(uv_teardown_irq);
Signature · 1 line
1.7.10.4
#8 lore raw

[tip:x86/apic] x86/uv: Use new irqdomain interfaces to allocate/ free IRQ

x86/uv: Use new irqdomain interfaces to allocate/free IRQ
Commit-ID:  331dd19eee243e1b7e670c5993609121817afeaa
Gitweb:     http://git.kernel.org/tip/331dd19eee243e1b7e670c5993609121817afeaa
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:27 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:48 +0200

x86/uv: Use new irqdomain interfaces to allocate/free IRQ

Use new irqdomain interfaces to allocate/free IRQ, so we can remove GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/platform/uv/uv_irq.c | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)
arch/x86/platform/uv/uv_irq.c +11 -16
index 0ce6736..474912d 100644
@@ -12,6 +12,7 @@
 #include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/apic.h>
 #include <asm/uv/uv_irq.h>
@@ -130,24 +131,14 @@ static int
 arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
 		       unsigned long mmr_offset, int limit)
 {
-	const struct cpumask *eligible_cpu = cpumask_of(cpu);
 	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned long mmr_value;
 	struct uv_IO_APIC_route_entry *entry;
-	int mmr_pnode, err;
-	unsigned int dest;
+	int mmr_pnode;
 
 	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
 			sizeof(unsigned long));
 
-	err = assign_irq_vector(irq, cfg, eligible_cpu);
-	if (err != 0)
-		return err;
-
-	err = apic->cpu_mask_to_apicid_and(eligible_cpu, eligible_cpu, &dest);
-	if (err != 0)
-		return err;
-
 	if (limit == UV_AFFINITY_CPU)
 		irq_set_status_flags(irq, IRQ_NO_BALANCING);
 	else
@@ -164,7 +155,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
 	entry->polarity		= 0;
 	entry->trigger		= 0;
 	entry->mask		= 0;
-	entry->dest		= dest;
+	entry->dest		= cfg->dest_apicid;
 
 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
@@ -238,9 +229,13 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
 int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
 		 unsigned long mmr_offset, int limit)
 {
-	int ret, irq = irq_alloc_hwirq(uv_blade_to_memory_nid(mmr_blade));
+	int ret, irq;
+	struct irq_alloc_info info;
 
-	if (!irq)
+	init_irq_alloc_info(&info, cpumask_of(cpu));
+	irq = irq_domain_alloc_irqs(NULL, 1, uv_blade_to_memory_nid(mmr_blade),
+				    &info);
+	if (irq <= 0)
 		return -EBUSY;
 
 	ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset,
@@ -248,7 +243,7 @@ int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
 	if (ret == irq)
 		uv_set_irq_2_mmr_info(irq, mmr_offset, mmr_blade);
 	else
-		irq_free_hwirq(irq);
+		irq_domain_free_irqs(irq, 1);
 
 	return ret;
 }
@@ -283,6 +278,6 @@ void uv_teardown_irq(unsigned int irq)
 			n = n->rb_right;
 	}
 	spin_unlock_irqrestore(&uv_irq_lock, irqflags);
-	irq_free_hwirq(irq);
+	irq_domain_free_irqs(irq, 1);
 }
 EXPORT_SYMBOL_GPL(uv_teardown_irq);
author
#9 lore raw

PATCH v8 6/37 x86/htirq: Use new irqdomain interfaces to allocate/free IRQ

In reply to Jiang Liu

Use new irqdomain interfaces to allocate/free IRQ for HTIRQ, so we could kill GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

This patch changes the interfaces between arch independent PCI driver and arch specific code. Currently HT_IRQ is only enabled on x86, so it shouldn't break other architectures.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/htirq.c |   26 +++++++++++++-------------
 drivers/pci/htirq.c          |    7 +++----
 include/linux/htirq.h        |    2 ++
 3 files changed, 18 insertions(+), 17 deletions(-)
arch/x86/kernel/apic/htirq.c +13 -13
index 816f36e979ad..b307ee7a7148 100644
@@ -14,6 +14,7 @@
 #include <linux/device.h>
 #include <linux/pci.h>
 #include <linux/htirq.h>
+#include <linux/irqdomain.h>
 #include <asm/hw_irq.h>
 #include <asm/apic.h>
 #include <asm/hypertransport.h>
@@ -61,31 +62,30 @@ static struct irq_chip ht_irq_chip = {
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
+int arch_alloc_ht_irq(struct pci_dev *dev)
+{
+	return irq_domain_alloc_irqs(NULL, 1, dev_to_node(&dev->dev), NULL);
+}
+
+void arch_free_ht_irq(int irq)
+{
+	irq_domain_free_irqs(irq, 1);
+}
+
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
 	struct irq_cfg *cfg;
 	struct ht_irq_msg msg;
-	unsigned dest;
-	int err;
 
 	if (disable_apic)
 		return -ENXIO;
 
 	cfg = irq_cfg(irq);
-	err = assign_irq_vector(irq, cfg, apic->target_cpus());
-	if (err)
-		return err;
-
-	err = apic->cpu_mask_to_apicid_and(cfg->domain,
-					   apic->target_cpus(), &dest);
-	if (err)
-		return err;
-
-	msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+	msg.address_hi = HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid);
 
 	msg.address_lo =
 		HT_IRQ_LOW_BASE |
-		HT_IRQ_LOW_DEST_ID(dest) |
+		HT_IRQ_LOW_DEST_ID(cfg->dest_apicid) |
 		HT_IRQ_LOW_VECTOR(cfg->vector) |
 		((apic->irq_dest_mode == 0) ?
 			HT_IRQ_LOW_DM_PHYSICAL :
drivers/pci/htirq.c +3 -4
index a94dd2c4183a..ceb0ebeb7b5f 100644
@@ -117,8 +117,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
 	cfg->msg.address_lo = 0xffffffff;
 	cfg->msg.address_hi = 0xffffffff;
 
-	irq = irq_alloc_hwirq(dev_to_node(&dev->dev));
-	if (!irq) {
+	irq = arch_alloc_ht_irq(dev);
+	if (irq <= 0) {
 		kfree(cfg);
 		return -EBUSY;
 	}
@@ -163,8 +163,7 @@ void ht_destroy_irq(unsigned int irq)
 	cfg = irq_get_handler_data(irq);
 	irq_set_chip(irq, NULL);
 	irq_set_handler_data(irq, NULL);
-	irq_free_hwirq(irq);
-
+	arch_free_ht_irq(irq);
 	kfree(cfg);
 }
 EXPORT_SYMBOL(ht_destroy_irq);
include/linux/htirq.h +2 -0
index 70a1dbbf2093..5caa51b7b95c 100644
@@ -15,6 +15,8 @@ void unmask_ht_irq(struct irq_data *data);
 
 /* The arch hook for getting things started */
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
+int arch_alloc_ht_irq(struct pci_dev *dev);
+void arch_free_ht_irq(int irq);
 
 /* For drivers of buggy hardware */
 typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
Signature · 1 line
1.7.10.4
#10 lore raw

[tip:x86/apic] x86/htirq: Use new irqdomain interfaces to allocate/free IRQ

x86/htirq: Use new irqdomain interfaces to allocate/free IRQ
Commit-ID:  af87baedf2c23b1181f51323339210a26a64f7fc
Gitweb:     http://git.kernel.org/tip/af87baedf2c23b1181f51323339210a26a64f7fc
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:28 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:48 +0200

x86/htirq: Use new irqdomain interfaces to allocate/free IRQ

Use new irqdomain interfaces to allocate/free IRQ for HTIRQ, so we can remove GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

This patch changes the interfaces between arch independent PCI driver and arch specific code. Currently HT_IRQ is only enabled on x86, so it does not affect other architectures.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/kernel/apic/htirq.c | 26 +++++++++++++-------------
 drivers/pci/htirq.c          |  7 +++----
 include/linux/htirq.h        |  2 ++
 3 files changed, 18 insertions(+), 17 deletions(-)
arch/x86/kernel/apic/htirq.c +13 -13
index 816f36e..b307ee7 100644
@@ -14,6 +14,7 @@
 #include <linux/device.h>
 #include <linux/pci.h>
 #include <linux/htirq.h>
+#include <linux/irqdomain.h>
 #include <asm/hw_irq.h>
 #include <asm/apic.h>
 #include <asm/hypertransport.h>
@@ -61,31 +62,30 @@ static struct irq_chip ht_irq_chip = {
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
+int arch_alloc_ht_irq(struct pci_dev *dev)
+{
+	return irq_domain_alloc_irqs(NULL, 1, dev_to_node(&dev->dev), NULL);
+}
+
+void arch_free_ht_irq(int irq)
+{
+	irq_domain_free_irqs(irq, 1);
+}
+
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
 	struct irq_cfg *cfg;
 	struct ht_irq_msg msg;
-	unsigned dest;
-	int err;
 
 	if (disable_apic)
 		return -ENXIO;
 
 	cfg = irq_cfg(irq);
-	err = assign_irq_vector(irq, cfg, apic->target_cpus());
-	if (err)
-		return err;
-
-	err = apic->cpu_mask_to_apicid_and(cfg->domain,
-					   apic->target_cpus(), &dest);
-	if (err)
-		return err;
-
-	msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+	msg.address_hi = HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid);
 
 	msg.address_lo =
 		HT_IRQ_LOW_BASE |
-		HT_IRQ_LOW_DEST_ID(dest) |
+		HT_IRQ_LOW_DEST_ID(cfg->dest_apicid) |
 		HT_IRQ_LOW_VECTOR(cfg->vector) |
 		((apic->irq_dest_mode == 0) ?
 			HT_IRQ_LOW_DM_PHYSICAL :
drivers/pci/htirq.c +3 -4
index a94dd2c..ceb0ebe 100644
@@ -117,8 +117,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
 	cfg->msg.address_lo = 0xffffffff;
 	cfg->msg.address_hi = 0xffffffff;
 
-	irq = irq_alloc_hwirq(dev_to_node(&dev->dev));
-	if (!irq) {
+	irq = arch_alloc_ht_irq(dev);
+	if (irq <= 0) {
 		kfree(cfg);
 		return -EBUSY;
 	}
@@ -163,8 +163,7 @@ void ht_destroy_irq(unsigned int irq)
 	cfg = irq_get_handler_data(irq);
 	irq_set_chip(irq, NULL);
 	irq_set_handler_data(irq, NULL);
-	irq_free_hwirq(irq);
-
+	arch_free_ht_irq(irq);
 	kfree(cfg);
 }
 EXPORT_SYMBOL(ht_destroy_irq);
include/linux/htirq.h +2 -0
index 70a1dbb..5caa51b 100644
@@ -15,6 +15,8 @@ void unmask_ht_irq(struct irq_data *data);
 
 /* The arch hook for getting things started */
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
+int arch_alloc_ht_irq(struct pci_dev *dev);
+void arch_free_ht_irq(int irq);
 
 /* For drivers of buggy hardware */
 typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
author
#11 lore raw

PATCH v8 7/37 x86/dmar: Use new irqdomain interfaces to allocate/free IRQ

In reply to Jiang Liu

Use new irqdomain interfaces to allocate/free IRQ for DMAR and interrupt remapping, so we could kill GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

The private definition of irq_alloc_hwirqs()/irq_free_hwirqs() are temporary solution, it will be removed once we have converted interrupt remapping driver to use irqdomain framework.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/x86/include/asm/irq_remapping.h |    4 ++--
 arch/x86/kernel/apic/msi.c           |   10 ++++++++++
 drivers/iommu/irq_remapping.c        |   17 +++++++++++++++--
 3 files changed, 27 insertions(+), 4 deletions(-)
arch/x86/include/asm/irq_remapping.h +2 -2
index 6224d316c405..86d897bc15dd 100644
@@ -99,7 +99,7 @@ static inline bool setup_remapped_irq(int irq,
 }
 #endif /* CONFIG_IRQ_REMAP */
 
-#define dmar_alloc_hwirq()	irq_alloc_hwirq(-1)
-#define dmar_free_hwirq		irq_free_hwirq
+extern int dmar_alloc_hwirq(void);
+extern void dmar_free_hwirq(int irq);
 
 #endif /* __X86_IRQ_REMAPPING_H */
arch/x86/kernel/apic/msi.c +10 -0
index 76cc2c902176..9be7d6d8a579 100644
@@ -223,6 +223,16 @@ int arch_setup_dmar_msi(unsigned int irq)
 				      "edge");
 	return 0;
 }
+
+int dmar_alloc_hwirq(void)
+{
+	return irq_domain_alloc_irqs(NULL, 1, NUMA_NO_NODE, NULL);
+}
+
+void dmar_free_hwirq(int irq)
+{
+	irq_domain_free_irqs(irq, 1);
+}
 #endif
 
 /*
drivers/iommu/irq_remapping.c +15 -2
index 390079ee1350..5617150fd8fb 100644
@@ -6,6 +6,7 @@
 #include <linux/msi.h>
 #include <linux/irq.h>
 #include <linux/pci.h>
+#include <linux/irqdomain.h>
 
 #include <asm/hw_irq.h>
 #include <asm/irq_remapping.h>
@@ -49,6 +50,18 @@ static void irq_remapping_disable_io_apic(void)
 		disconnect_bsp_APIC(0);
 }
 
+#ifndef CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+static unsigned int irq_alloc_hwirqs(int cnt, int node)
+{
+	return irq_domain_alloc_irqs(NULL, -1, cnt, node, NULL);
+}
+
+static void irq_free_hwirqs(unsigned int from, int cnt)
+{
+	irq_domain_free_irqs(from, cnt);
+}
+#endif
+
 static int do_setup_msi_irqs(struct pci_dev *dev, int nvec)
 {
 	int ret, sub_handle, nvec_pow2, index = 0;
@@ -104,7 +117,7 @@ static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
 
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
 
-		irq = irq_alloc_hwirq(node);
+		irq = irq_alloc_hwirqs(1, node);
 		if (irq == 0)
 			return -1;
 
@@ -127,7 +140,7 @@ static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
 	return 0;
 
 error:
-	irq_free_hwirq(irq);
+	irq_free_hwirqs(irq, 1);
 	return ret;
 }
 
Signature · 1 line
1.7.10.4
#12 lore raw

[tip:x86/apic] x86/dmar: Use new irqdomain interfaces to allocate /free IRQ

x86/dmar: Use new irqdomain interfaces to allocate/free IRQ
Commit-ID:  a62b32cdd0a6324c959f40b3c9b928b275297066
Gitweb:     http://git.kernel.org/tip/a62b32cdd0a6324c959f40b3c9b928b275297066
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:29 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:48 +0200

x86/dmar: Use new irqdomain interfaces to allocate/free IRQ

Use new irqdomain interfaces to allocate/free IRQ for DMAR and interrupt remapping, so we can remove GENERIC_IRQ_LEGACY_ALLOC_HWIRQ later.

The private definitions of irq_alloc_hwirqs()/irq_free_hwirqs() are a temporary solution, they will be removed once we have converted the interrupt remapping driver to use irqdomain framework.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/x86/include/asm/irq_remapping.h |  4 ++--
 arch/x86/kernel/apic/msi.c           | 10 ++++++++++
 drivers/iommu/irq_remapping.c        | 17 +++++++++++++++--
 3 files changed, 27 insertions(+), 4 deletions(-)
arch/x86/include/asm/irq_remapping.h +2 -2
index 6224d31..86d897b 100644
@@ -99,7 +99,7 @@ static inline bool setup_remapped_irq(int irq,
 }
 #endif /* CONFIG_IRQ_REMAP */
 
-#define dmar_alloc_hwirq()	irq_alloc_hwirq(-1)
-#define dmar_free_hwirq		irq_free_hwirq
+extern int dmar_alloc_hwirq(void);
+extern void dmar_free_hwirq(int irq);
 
 #endif /* __X86_IRQ_REMAPPING_H */
arch/x86/kernel/apic/msi.c +10 -0
index 76cc2c9..9be7d6d 100644
@@ -223,6 +223,16 @@ int arch_setup_dmar_msi(unsigned int irq)
 				      "edge");
 	return 0;
 }
+
+int dmar_alloc_hwirq(void)
+{
+	return irq_domain_alloc_irqs(NULL, 1, NUMA_NO_NODE, NULL);
+}
+
+void dmar_free_hwirq(int irq)
+{
+	irq_domain_free_irqs(irq, 1);
+}
 #endif
 
 /*
drivers/iommu/irq_remapping.c +15 -2
index 390079e..5617150 100644
@@ -6,6 +6,7 @@
 #include <linux/msi.h>
 #include <linux/irq.h>
 #include <linux/pci.h>
+#include <linux/irqdomain.h>
 
 #include <asm/hw_irq.h>
 #include <asm/irq_remapping.h>
@@ -49,6 +50,18 @@ static void irq_remapping_disable_io_apic(void)
 		disconnect_bsp_APIC(0);
 }
 
+#ifndef CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+static unsigned int irq_alloc_hwirqs(int cnt, int node)
+{
+	return irq_domain_alloc_irqs(NULL, -1, cnt, node, NULL);
+}
+
+static void irq_free_hwirqs(unsigned int from, int cnt)
+{
+	irq_domain_free_irqs(from, cnt);
+}
+#endif
+
 static int do_setup_msi_irqs(struct pci_dev *dev, int nvec)
 {
 	int ret, sub_handle, nvec_pow2, index = 0;
@@ -104,7 +117,7 @@ static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
 
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
 
-		irq = irq_alloc_hwirq(node);
+		irq = irq_alloc_hwirqs(1, node);
 		if (irq == 0)
 			return -1;
 
@@ -127,7 +140,7 @@ static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
 	return 0;
 
 error:
-	irq_free_hwirq(irq);
+	irq_free_hwirqs(irq, 1);
 	return ret;
 }
 
author
#13 lore raw

PATCH v8 8/37 irq_remapping: Introduce new interfaces to support hierarchy irqdomain

In reply to Jiang Liu

Introduce new interfaces for interrupt remapping drivers to support hierarchy irqdomain:
1) irq_remapping_get_ir_irq_domain(): get irqdomain associated with an interrupt remapping unit. IOAPIC/HPET drivers use this interface to get parent interrupt remapping irqdomain.
2) irq_remapping_get_irq_domain(): get irqdomain for an IRQ allocation. This is mainly used to support MSI irqdomain. We must build one MSI irqdomain for each interrupt remapping unit. MSI driver calls this interface to get MSI irqdomain associated with an IR irqdomain which manages the PCI devices. In a further step we will store the irqdomain pointer in the device struct to avoid this call in the irq allocation path.

Architecture specific needs to implement two hooks:
1) arch_get_ir_parent_domain(): get parent irqdomain for IR irqdomain, which is x86_vector_domain on x86 platforms.
2) arch_create_msi_irq_domain(): create an MSI irqdomain associated with the interrupt remapping unit.

We also add following callbacks into struct irq_remap_ops:

	struct irq_domain *(*get_ir_irq_domain)(struct irq_alloc_info *);
	struct irq_domain *(*get_irq_domain)(struct irq_alloc_info *);

Once all clients of IR have been converted to new hierarchy irqdomain interfaces, we will:
1) Remove set_ioapic_entry, set_affinity, free_irq, compose_msi_msg, msi_alloc_irq, msi_setup_irq, setup_hpet_msi from struct remap_osp
2) Kill setup_ioapic_remapped_entry, free_remapped_irq, compose_remapped_msi_msg, setup_hpet_msi_remapped, setup_remapped_irq.
3) Simplify x86_io_apic_ops and x86_msi.

We could achieve a much more clear architecture with all these changes applied.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/x86/include/asm/hw_irq.h        |   37 +++++++++++++++++++++++++
 arch/x86/include/asm/irq_remapping.h |   36 ++++++++++++++++++++++++
 drivers/iommu/irq_remapping.c        |   50 +++++++++++++++++++++++++++++++++-
 drivers/iommu/irq_remapping.h        |   10 +++++++
 4 files changed, 132 insertions(+), 1 deletion(-)
arch/x86/include/asm/hw_irq.h +37 -0
index eb7692c9ab93..bd7881c5a57a 100644
@@ -113,10 +113,47 @@ struct irq_2_irte {
 #ifdef	CONFIG_X86_LOCAL_APIC
 struct irq_data;
 struct irq_domain;
+struct pci_dev;
+struct msi_desc;
+
+enum irq_alloc_type {
+	X86_IRQ_ALLOC_TYPE_IOAPIC = 1,
+	X86_IRQ_ALLOC_TYPE_HPET,
+	X86_IRQ_ALLOC_TYPE_MSI,
+	X86_IRQ_ALLOC_TYPE_MSIX,
+};
 
 struct irq_alloc_info {
+	enum irq_alloc_type	type;
 	u32			flags;
 	const struct cpumask	*mask;	/* CPU mask for vector allocation */
+	union {
+		int		unused;
+#ifdef	CONFIG_HPET_TIMER
+		struct {
+			int		hpet_id;
+			int		hpet_index;
+			void		*hpet_data;
+		};
+#endif
+#ifdef	CONFIG_PCI_MSI
+		struct {
+			struct pci_dev	*msi_dev;
+			irq_hw_number_t	msi_hwirq;
+		};
+#endif
+#ifdef	CONFIG_X86_IO_APIC
+		struct {
+			int		ioapic_id;
+			int		ioapic_pin;
+			int		ioapic_node;
+			u32		ioapic_trigger : 1;
+			u32		ioapic_polarity : 1;
+			u32		ioapic_valid : 1;
+			struct IO_APIC_route_entry *ioapic_entry;
+		};
+#endif
+	};
 };
 
 enum {
arch/x86/include/asm/irq_remapping.h +36 -0
index 86d897bc15dd..0cd6195cc375 100644
@@ -22,6 +22,8 @@
 #ifndef __X86_IRQ_REMAPPING_H
 #define __X86_IRQ_REMAPPING_H
 
+#include <linux/irqdomain.h>
+#include <asm/hw_irq.h>
 #include <asm/io_apic.h>
 
 struct IO_APIC_route_entry;
@@ -30,6 +32,7 @@ struct irq_chip;
 struct msi_msg;
 struct pci_dev;
 struct irq_cfg;
+struct irq_alloc_info;
 
 #ifdef CONFIG_IRQ_REMAP
 
@@ -56,6 +59,25 @@ extern bool setup_remapped_irq(int irq,
 
 void irq_remap_modify_chip_defaults(struct irq_chip *chip);
 
+extern struct irq_domain *
+irq_remapping_get_ir_irq_domain(struct irq_alloc_info *info);
+extern struct irq_domain *
+irq_remapping_get_irq_domain(struct irq_alloc_info *info);
+extern void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p);
+
+/* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */
+static inline struct irq_domain *
+arch_create_msi_irq_domain(struct irq_domain *parent)
+{
+	return NULL;
+}
+
+/* Get parent irqdomain for interrupt remapping irqdomain */
+static inline struct irq_domain *arch_get_ir_parent_domain(void)
+{
+	return x86_vector_domain;
+}
+
 #else  /* CONFIG_IRQ_REMAP */
 
 static inline void set_irq_remapping_broken(void) { }
@@ -97,6 +119,20 @@ static inline bool setup_remapped_irq(int irq,
 {
 	return false;
 }
+
+static inline struct irq_domain *
+irq_remapping_get_ir_irq_domain(struct irq_alloc_info *info)
+{
+	return NULL;
+}
+
+static inline struct irq_domain *
+irq_remapping_get_irq_domain(struct irq_alloc_info *info)
+{
+	return NULL;
+}
+
+#define	irq_remapping_print_chip	NULL
 #endif /* CONFIG_IRQ_REMAP */
 
 extern int dmar_alloc_hwirq(void);
drivers/iommu/irq_remapping.c +49 -1

65 lines not on this page · raw message

drivers/iommu/irq_remapping.h +10 -0
index 7c70cc29ffe6..3e109b1ea688 100644
@@ -30,6 +30,8 @@ struct irq_data;
 struct cpumask;
 struct pci_dev;
 struct msi_msg;
+struct irq_domain;
+struct irq_alloc_info;
 
 extern int irq_remap_broken;
 extern int disable_sourceid_checking;
@@ -77,11 +79,19 @@ struct irq_remap_ops {
 
 	/* Setup interrupt remapping for an HPET MSI */
 	int (*alloc_hpet_msi)(unsigned int, unsigned int);
+
+	/* Get the irqdomain associated the IOMMU device */
+	struct irq_domain *(*get_ir_irq_domain)(struct irq_alloc_info *);
+
+	/* Get the MSI irqdomain associated with the IOMMU device */
+	struct irq_domain *(*get_irq_domain)(struct irq_alloc_info *);
 };
 
 extern struct irq_remap_ops intel_irq_remap_ops;
 extern struct irq_remap_ops amd_iommu_irq_ops;
 
+extern void ir_ack_apic_edge(struct irq_data *data);
+
 #else  /* CONFIG_IRQ_REMAP */
 
 #define irq_remapping_enabled 0
Signature · 1 line
1.7.10.4
#14 lore raw

[tip:x86/apic] irq_remapping: Introduce new interfaces to support hierarchical irqdomains

irq_remapping: Introduce new interfaces to support hierarchical irqdomains
Commit-ID:  947045a2aac1157c85a24984c9a8128846ae7266
Gitweb:     http://git.kernel.org/tip/947045a2aac1157c85a24984c9a8128846ae7266
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:30 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:48 +0200

irq_remapping: Introduce new interfaces to support hierarchical irqdomains

Introduce new interfaces for interrupt remapping drivers to support hierarchical irqdomains:

1) irq_remapping_get_ir_irq_domain(): get irqdomain associated with an interrupt remapping unit. IOAPIC/HPET drivers use this interface to get parent interrupt remapping irqdomain.

2) irq_remapping_get_irq_domain(): get irqdomain for an IRQ allocation. This is mainly used to support MSI irqdomain. We must build one MSI irqdomain for each interrupt remapping unit. MSI driver calls this interface to get MSI irqdomain associated with an IR irqdomain which manages the PCI devices. In a further step we will store the irqdomain pointer in the device struct to avoid this call in the irq allocation path.

Architecture specific hooks:
1) arch_get_ir_parent_domain(): get parent irqdomain for IR irqdomain, which is x86_vector_domain on x86 platforms.
2) arch_create_msi_irq_domain(): create an MSI irqdomain associated with the interrupt remapping unit.

We also add following callbacks into struct irq_remap_ops:

	struct irq_domain *(*get_ir_irq_domain)(struct irq_alloc_info *);
	struct irq_domain *(*get_irq_domain)(struct irq_alloc_info *);

Once all clients of IR have been converted to the new hierarchical irqdomain interfaces, we will:
1) Remove set_ioapic_entry, set_affinity, free_irq, compose_msi_msg, msi_alloc_irq, msi_setup_irq, setup_hpet_msi from struct remap_osp
2) Remove setup_ioapic_remapped_entry, free_remapped_irq, compose_remapped_msi_msg, setup_hpet_msi_remapped, setup_remapped_irq.
3) Simplify x86_io_apic_ops and x86_msi.

We can achieve a way clearer architecture with all these changes applied.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/x86/include/asm/hw_irq.h        | 37 ++++++++++++++++++++++++++
 arch/x86/include/asm/irq_remapping.h | 36 ++++++++++++++++++++++++++
 drivers/iommu/irq_remapping.c        | 50 +++++++++++++++++++++++++++++++++++-
 drivers/iommu/irq_remapping.h        | 10 ++++++++
 4 files changed, 132 insertions(+), 1 deletion(-)
arch/x86/include/asm/hw_irq.h +37 -0
index 5b951ac..75a97a5 100644
@@ -113,10 +113,47 @@ struct irq_2_irte {
 #ifdef	CONFIG_X86_LOCAL_APIC
 struct irq_data;
 struct irq_domain;
+struct pci_dev;
+struct msi_desc;
+
+enum irq_alloc_type {
+	X86_IRQ_ALLOC_TYPE_IOAPIC = 1,
+	X86_IRQ_ALLOC_TYPE_HPET,
+	X86_IRQ_ALLOC_TYPE_MSI,
+	X86_IRQ_ALLOC_TYPE_MSIX,
+};
 
 struct irq_alloc_info {
+	enum irq_alloc_type	type;
 	u32			flags;
 	const struct cpumask	*mask;	/* CPU mask for vector allocation */
+	union {
+		int		unused;
+#ifdef	CONFIG_HPET_TIMER
+		struct {
+			int		hpet_id;
+			int		hpet_index;
+			void		*hpet_data;
+		};
+#endif
+#ifdef	CONFIG_PCI_MSI
+		struct {
+			struct pci_dev	*msi_dev;
+			irq_hw_number_t	msi_hwirq;
+		};
+#endif
+#ifdef	CONFIG_X86_IO_APIC
+		struct {
+			int		ioapic_id;
+			int		ioapic_pin;
+			int		ioapic_node;
+			u32		ioapic_trigger : 1;
+			u32		ioapic_polarity : 1;
+			u32		ioapic_valid : 1;
+			struct IO_APIC_route_entry *ioapic_entry;
+		};
+#endif
+	};
 };
 
 enum {
arch/x86/include/asm/irq_remapping.h +36 -0
index 86d897b..0cd6195 100644
@@ -22,6 +22,8 @@
 #ifndef __X86_IRQ_REMAPPING_H
 #define __X86_IRQ_REMAPPING_H
 
+#include <linux/irqdomain.h>
+#include <asm/hw_irq.h>
 #include <asm/io_apic.h>
 
 struct IO_APIC_route_entry;
@@ -30,6 +32,7 @@ struct irq_chip;
 struct msi_msg;
 struct pci_dev;
 struct irq_cfg;
+struct irq_alloc_info;
 
 #ifdef CONFIG_IRQ_REMAP
 
@@ -56,6 +59,25 @@ extern bool setup_remapped_irq(int irq,
 
 void irq_remap_modify_chip_defaults(struct irq_chip *chip);
 
+extern struct irq_domain *
+irq_remapping_get_ir_irq_domain(struct irq_alloc_info *info);
+extern struct irq_domain *
+irq_remapping_get_irq_domain(struct irq_alloc_info *info);
+extern void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p);
+
+/* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */
+static inline struct irq_domain *
+arch_create_msi_irq_domain(struct irq_domain *parent)
+{
+	return NULL;
+}
+
+/* Get parent irqdomain for interrupt remapping irqdomain */
+static inline struct irq_domain *arch_get_ir_parent_domain(void)
+{
+	return x86_vector_domain;
+}
+
 #else  /* CONFIG_IRQ_REMAP */
 
 static inline void set_irq_remapping_broken(void) { }
@@ -97,6 +119,20 @@ static inline bool setup_remapped_irq(int irq,
 {
 	return false;
 }
+
+static inline struct irq_domain *
+irq_remapping_get_ir_irq_domain(struct irq_alloc_info *info)
+{
+	return NULL;
+}
+
+static inline struct irq_domain *
+irq_remapping_get_irq_domain(struct irq_alloc_info *info)
+{
+	return NULL;
+}
+
+#define	irq_remapping_print_chip	NULL
 #endif /* CONFIG_IRQ_REMAP */
 
 extern int dmar_alloc_hwirq(void);
drivers/iommu/irq_remapping.c +49 -1

65 lines not on this page · raw message

drivers/iommu/irq_remapping.h +10 -0
index 7c70cc2..3e109b1 100644
@@ -30,6 +30,8 @@ struct irq_data;
 struct cpumask;
 struct pci_dev;
 struct msi_msg;
+struct irq_domain;
+struct irq_alloc_info;
 
 extern int irq_remap_broken;
 extern int disable_sourceid_checking;
@@ -77,11 +79,19 @@ struct irq_remap_ops {
 
 	/* Setup interrupt remapping for an HPET MSI */
 	int (*alloc_hpet_msi)(unsigned int, unsigned int);
+
+	/* Get the irqdomain associated the IOMMU device */
+	struct irq_domain *(*get_ir_irq_domain)(struct irq_alloc_info *);
+
+	/* Get the MSI irqdomain associated with the IOMMU device */
+	struct irq_domain *(*get_irq_domain)(struct irq_alloc_info *);
 };
 
 extern struct irq_remap_ops intel_irq_remap_ops;
 extern struct irq_remap_ops amd_iommu_irq_ops;
 
+extern void ir_ack_apic_edge(struct irq_data *data);
+
 #else  /* CONFIG_IRQ_REMAP */
 
 #define irq_remapping_enabled 0
author
#15 lore raw

PATCH v8 9/37 irq_remapping/vt-d: Change prototypes to prepare for enabling hierarchy irqdomain

In reply to Jiang Liu

Prepare for support hierarchy irqdomain by changing function prototypes, should be no function changes.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/intel_irq_remapping.c |   22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
drivers/iommu/intel_irq_remapping.c +11 -11
index 14de1ab223c8..d3adaf32b3ec 100644
@@ -82,10 +82,10 @@ static int get_irte(int irq, struct irte *entry)
 	return 0;
 }
 
-static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+static int alloc_irte(struct intel_iommu *iommu, int irq,
+		      struct irq_2_iommu *irq_iommu, u16 count)
 {
 	struct ir_table *table = iommu->ir_table;
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned int mask = 0;
 	unsigned long flags;
@@ -173,9 +173,9 @@ static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subha
 	return 0;
 }
 
-static int modify_irte(int irq, struct irte *irte_modified)
+static int modify_irte(struct irq_2_iommu *irq_iommu,
+		       struct irte *irte_modified)
 {
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	struct intel_iommu *iommu;
 	unsigned long flags;
 	struct irte *irte;
@@ -242,7 +242,7 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
 		return 0;
 
 	iommu = irq_iommu->iommu;
-	index = irq_iommu->irte_index + irq_iommu->sub_handle;
+	index = irq_iommu->irte_index;
 
 	start = iommu->ir_table->base + index;
 	end = start + (1 << irq_iommu->irte_mask);
@@ -986,7 +986,7 @@ static int intel_setup_ioapic_entry(int irq,
 		pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
 		index = -ENODEV;
 	} else {
-		index = alloc_irte(iommu, irq, 1);
+		index = alloc_irte(iommu, irq, irq_2_iommu(irq), 1);
 		if (index < 0) {
 			pr_warn("Failed to allocate IRTE for ioapic %d\n",
 				ioapic_id);
@@ -1002,7 +1002,7 @@ static int intel_setup_ioapic_entry(int irq,
 	/* Set source-id of interrupt request */
 	set_ioapic_sid(&irte, ioapic_id);
 
-	modify_irte(irq, &irte);
+	modify_irte(irq_2_iommu(irq), &irte);
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
 		"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
@@ -1089,7 +1089,7 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	 * Atomically updates the IRTE with the new destination, vector
 	 * and flushes the interrupt entry cache.
 	 */
-	modify_irte(irq, &irte);
+	modify_irte(irq_2_iommu(irq), &irte);
 
 	/*
 	 * After this point, all the interrupts will start arriving
@@ -1125,7 +1125,7 @@ static void intel_compose_msi_msg(struct pci_dev *pdev,
 	else
 		set_hpet_sid(&irte, hpet_id);
 
-	modify_irte(irq, &irte);
+	modify_irte(irq_2_iommu(irq), &irte);
 
 	msg->address_hi = MSI_ADDR_BASE_HI;
 	msg->data = sub_handle;
@@ -1152,7 +1152,7 @@ static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec)
 		       "Unable to map PCI %s to iommu\n", pci_name(dev));
 		index = -ENOENT;
 	} else {
-		index = alloc_irte(iommu, irq, nvec);
+		index = alloc_irte(iommu, irq, irq_2_iommu(irq), nvec);
 		if (index < 0) {
 			printk(KERN_ERR
 			       "Unable to allocate %d IRTE for PCI %s\n",
@@ -1196,7 +1196,7 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id)
 	down_read(&dmar_global_lock);
 	iommu = map_hpet_to_ir(id);
 	if (iommu) {
-		index = alloc_irte(iommu, irq, 1);
+		index = alloc_irte(iommu, irq, irq_2_iommu(irq), 1);
 		if (index >= 0)
 			ret = 0;
 	}
Signature · 1 line
1.7.10.4
#16 lore raw

[tip:x86/apic] irq_remapping/vt-d: Change prototypes to prepare for hierarchical irqdomain

irq_remapping/vt-d: Change prototypes to prepare for hierarchical irqdomain
Commit-ID:  8dedf4cf5a52eafd2160609c11d3206c06e32b36
Gitweb:     http://git.kernel.org/tip/8dedf4cf5a52eafd2160609c11d3206c06e32b36
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:31 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:48 +0200

irq_remapping/vt-d: Change prototypes to prepare for hierarchical irqdomain

Prepare for the conversion to hierarchical irqdomains by changing function prototypes. No functional changes.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/intel_irq_remapping.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
drivers/iommu/intel_irq_remapping.c +11 -11
index 6c25b3c..0b89ef1 100644
@@ -82,10 +82,10 @@ static int get_irte(int irq, struct irte *entry)
 	return 0;
 }
 
-static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+static int alloc_irte(struct intel_iommu *iommu, int irq,
+		      struct irq_2_iommu *irq_iommu, u16 count)
 {
 	struct ir_table *table = iommu->ir_table;
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned int mask = 0;
 	unsigned long flags;
@@ -173,9 +173,9 @@ static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subha
 	return 0;
 }
 
-static int modify_irte(int irq, struct irte *irte_modified)
+static int modify_irte(struct irq_2_iommu *irq_iommu,
+		       struct irte *irte_modified)
 {
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	struct intel_iommu *iommu;
 	unsigned long flags;
 	struct irte *irte;
@@ -242,7 +242,7 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
 		return 0;
 
 	iommu = irq_iommu->iommu;
-	index = irq_iommu->irte_index + irq_iommu->sub_handle;
+	index = irq_iommu->irte_index;
 
 	start = iommu->ir_table->base + index;
 	end = start + (1 << irq_iommu->irte_mask);
@@ -986,7 +986,7 @@ static int intel_setup_ioapic_entry(int irq,
 		pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
 		index = -ENODEV;
 	} else {
-		index = alloc_irte(iommu, irq, 1);
+		index = alloc_irte(iommu, irq, irq_2_iommu(irq), 1);
 		if (index < 0) {
 			pr_warn("Failed to allocate IRTE for ioapic %d\n",
 				ioapic_id);
@@ -1002,7 +1002,7 @@ static int intel_setup_ioapic_entry(int irq,
 	/* Set source-id of interrupt request */
 	set_ioapic_sid(&irte, ioapic_id);
 
-	modify_irte(irq, &irte);
+	modify_irte(irq_2_iommu(irq), &irte);
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
 		"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
@@ -1089,7 +1089,7 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	 * Atomically updates the IRTE with the new destination, vector
 	 * and flushes the interrupt entry cache.
 	 */
-	modify_irte(irq, &irte);
+	modify_irte(irq_2_iommu(irq), &irte);
 
 	/*
 	 * After this point, all the interrupts will start arriving
@@ -1125,7 +1125,7 @@ static void intel_compose_msi_msg(struct pci_dev *pdev,
 	else
 		set_hpet_sid(&irte, hpet_id);
 
-	modify_irte(irq, &irte);
+	modify_irte(irq_2_iommu(irq), &irte);
 
 	msg->address_hi = MSI_ADDR_BASE_HI;
 	msg->data = sub_handle;
@@ -1152,7 +1152,7 @@ static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec)
 		       "Unable to map PCI %s to iommu\n", pci_name(dev));
 		index = -ENOENT;
 	} else {
-		index = alloc_irte(iommu, irq, nvec);
+		index = alloc_irte(iommu, irq, irq_2_iommu(irq), nvec);
 		if (index < 0) {
 			printk(KERN_ERR
 			       "Unable to allocate %d IRTE for PCI %s\n",
@@ -1196,7 +1196,7 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id)
 	down_read(&dmar_global_lock);
 	iommu = map_hpet_to_ir(id);
 	if (iommu) {
-		index = alloc_irte(iommu, irq, 1);
+		index = alloc_irte(iommu, irq, irq_2_iommu(irq), 1);
 		if (index >= 0)
 			ret = 0;
 	}
author
#17 lore raw

PATCH v8 10/37 irq_remapping/vt-d: Enhance Intel IR driver to support hierarchy irqdomain

In reply to Jiang Liu

Enhance Intel interrupt remapping driver to support hierarchy irqdomain, it will simplify the code eventually. It also implements intel_ir_chip to support stacked irq_chip.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc David Woodhouse <[email protected]>
---
 drivers/iommu/intel_irq_remapping.c |  337 ++++++++++++++++++++++++++++++++++-
 include/linux/intel-iommu.h         |    4 +
 2 files changed, 333 insertions(+), 8 deletions(-)
drivers/iommu/intel_irq_remapping.c +329 -8
index d3adaf32b3ec..f2dbb0d54d17 100644
@@ -8,6 +8,7 @@
 #include <linux/irq.h>
 #include <linux/intel-iommu.h>
 #include <linux/acpi.h>
+#include <linux/irqdomain.h>
 #include <asm/io_apic.h>
 #include <asm/smp.h>
 #include <asm/cpu.h>
@@ -31,6 +32,14 @@ struct hpet_scope {
 	unsigned int devfn;
 };
 
+struct intel_ir_data {
+	struct irq_2_iommu			irq_2_iommu;
+	struct irte				irte_entry;
+	union {
+		struct msi_msg			msi_entry;
+	};
+};
+
 #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
 #define IRTE_DEST(dest) ((eim_mode) ? dest : dest << 8)
 
@@ -50,6 +59,7 @@ static struct hpet_scope ir_hpet[MAX_HPET_TBS];
  * the dmar_global_lock.
  */
 static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
+static struct irq_domain_ops intel_ir_domain_ops;
 
 static int __init parse_ioapics_under_ir(void);
 
@@ -263,7 +273,7 @@ static int free_irte(int irq)
 	unsigned long flags;
 	int rc;
 
-	if (!irq_iommu)
+	if (!irq_iommu || irq_iommu->iommu == NULL)
 		return -1;
 
 	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
@@ -488,7 +498,6 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
 
 	pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO,
 				 INTR_REMAP_PAGE_ORDER);
-
 	if (!pages) {
 		pr_err("IR%d: failed to allocate pages of order %d\n",
 		       iommu->seq_id, INTR_REMAP_PAGE_ORDER);
@@ -502,11 +511,23 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
 		goto out_free_pages;
 	}
 
+	iommu->ir_domain = irq_domain_add_hierarchy(arch_get_ir_parent_domain(),
+						    0, INTR_REMAP_TABLE_ENTRIES,
+						    NULL, &intel_ir_domain_ops,
+						    iommu);
+	if (!iommu->ir_domain) {
+		pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id);
+		goto out_free_bitmap;
+	}
+	iommu->ir_msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
+
 	ir_table->base = page_address(pages);
 	ir_table->bitmap = bitmap;
 	iommu->ir_table = ir_table;
 	return 0;
 
+out_free_bitmap:
+	kfree(bitmap);
 out_free_pages:
 	__free_pages(pages, INTR_REMAP_PAGE_ORDER);
 out_free_table:
@@ -517,6 +538,14 @@ out_free_table:
 static void intel_teardown_irq_remapping(struct intel_iommu *iommu)
 {
 	if (iommu && iommu->ir_table) {
+		if (iommu->ir_msi_domain) {
+			irq_domain_remove(iommu->ir_msi_domain);
+			iommu->ir_msi_domain = NULL;
+		}
+		if (iommu->ir_domain) {
+			irq_domain_remove(iommu->ir_domain);
+			iommu->ir_domain = NULL;
+		}
 		free_pages((unsigned long)iommu->ir_table->base,
 			   INTR_REMAP_PAGE_ORDER);
 		kfree(iommu->ir_table->bitmap);
@@ -1062,12 +1091,6 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	struct irte irte;
 	int err;
 
-	if (!config_enabled(CONFIG_SMP))
-		return -EINVAL;
-
-	if (!cpumask_intersects(mask, cpu_online_mask))
-		return -EINVAL;
-
 	if (get_irte(irq, &irte))
 		return -EBUSY;
 
@@ -1100,6 +1123,7 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 		send_cleanup_vector(cfg);
 
 	cpumask_copy(data->affinity, mask);
+
 	return 0;
 }
 
@@ -1205,6 +1229,53 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id)
 	return ret;
 }
 
+static struct irq_domain *intel_get_ir_irq_domain(struct irq_alloc_info *info)
+{
+	struct intel_iommu *iommu = NULL;
+
+	if (!info)
+		return NULL;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		iommu = map_ioapic_to_ir(info->ioapic_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_HPET:
+		iommu = map_hpet_to_ir(info->hpet_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		iommu = map_dev_to_ir(info->msi_dev);
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	return iommu ? iommu->ir_domain : NULL;
+}
+
+static struct irq_domain *intel_get_irq_domain(struct irq_alloc_info *info)
+{
+	struct intel_iommu *iommu;
+
+	if (!info)
+		return NULL;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		iommu = map_dev_to_ir(info->msi_dev);
+		if (iommu)
+			return iommu->ir_msi_domain;
+		break;
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
 struct irq_remap_ops intel_irq_remap_ops = {
 	.prepare		= intel_prepare_irq_remapping,
 	.enable			= intel_enable_irq_remapping,
@@ -1218,6 +1289,256 @@ struct irq_remap_ops intel_irq_remap_ops = {
 	.msi_alloc_irq		= intel_msi_alloc_irq,
 	.msi_setup_irq		= intel_msi_setup_irq,
 	.alloc_hpet_msi		= intel_alloc_hpet_msi,
+	.get_ir_irq_domain	= intel_get_ir_irq_domain,
+	.get_irq_domain		= intel_get_irq_domain,
+};
+
+/*
+ * Migrate the IO-APIC irq in the presence of intr-remapping.
+ *
+ * For both level and edge triggered, irq migration is a simple atomic
+ * update(of vector and cpu destination) of IRTE and flush the hardware cache.
+ *
+ * For level triggered, we eliminate the io-apic RTE modification (with the
+ * updated vector information), by using a virtual vector (io-apic pin number).
+ * Real vector that is used for interrupting cpu will be coming from
+ * the interrupt-remapping table entry.
+ *
+ * As the migration is a simple atomic update of IRTE, the same mechanism
+ * is used to migrate MSI irq's in the presence of interrupt-remapping.
+ */
+static int
+intel_ir_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		      bool force)
+{
+	struct intel_ir_data *ir_data = data->chip_data;
+	struct irte *irte = &ir_data->irte_entry;
+	struct irq_cfg *cfg = irqd_cfg(data);
+	struct irq_data *parent = data->parent_data;
+	int ret;
+
+	ret = parent->chip->irq_set_affinity(parent, mask, force);
+	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
+		return ret;
+
+	/*
+	 * Atomically updates the IRTE with the new destination, vector
+	 * and flushes the interrupt entry cache.
+	 */
+	irte->vector = cfg->vector;
+	irte->dest_id = IRTE_DEST(cfg->dest_apicid);
+	modify_irte(&ir_data->irq_2_iommu, irte);
+
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
+	return IRQ_SET_MASK_OK_DONE;
+}
+
+static void intel_ir_compose_msi_msg(struct irq_data *irq_data,
+				     struct msi_msg *msg)
+{
+	struct intel_ir_data *ir_data = irq_data->chip_data;
+
+	*msg = ir_data->msi_entry;
+}
+
+static struct irq_chip intel_ir_chip = {
+	.irq_ack = ir_ack_apic_edge,
+	.irq_set_affinity = intel_ir_set_affinity,
+	.irq_compose_msi_msg = intel_ir_compose_msi_msg,
+};
+
+static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
+					     struct irq_cfg *irq_cfg,
+					     struct irq_alloc_info *info,
+					     int index, int sub_handle)
+{
+	struct IR_IO_APIC_route_entry *entry;
+	struct irte *irte = &data->irte_entry;
+	struct msi_msg *msg = &data->msi_entry;
+
+	prepare_irte(irte, irq_cfg->vector, irq_cfg->dest_apicid);
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		/* Set source-id of interrupt request */
+		set_ioapic_sid(irte, info->ioapic_id);
+		apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: Set IRTE entry (P:%d FPD:%d Dst_Mode:%d Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X Avail:%X Vector:%02X Dest:%08X SID:%04X SQ:%X SVT:%X)\n",
+			info->ioapic_id, irte->present, irte->fpd,
+			irte->dst_mode, irte->redir_hint,
+			irte->trigger_mode, irte->dlvry_mode,
+			irte->avail, irte->vector, irte->dest_id,
+			irte->sid, irte->sq, irte->svt);
+
+		entry = (struct IR_IO_APIC_route_entry *)info->ioapic_entry;
+		info->ioapic_entry = NULL;
+		memset(entry, 0, sizeof(*entry));
+		entry->index2	= (index >> 15) & 0x1;
+		entry->zero	= 0;
+		entry->format	= 1;
+		entry->index	= (index & 0x7fff);
+		/*
+		 * IO-APIC RTE will be configured with virtual vector.
+		 * irq handler will do the explicit EOI to the io-apic.
+		 */
+		entry->vector	= info->ioapic_pin;
+		entry->mask	= 0;			/* enable IRQ */
+		entry->trigger	= info->ioapic_trigger;
+		entry->polarity	= info->ioapic_polarity;
+		if (info->ioapic_trigger)
+			entry->mask = 1; /* Mask level triggered irqs. */
+		break;
+
+	case X86_IRQ_ALLOC_TYPE_HPET:
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		if (info->type == X86_IRQ_ALLOC_TYPE_HPET)
+			set_hpet_sid(irte, info->hpet_id);
+		else
+			set_msi_sid(irte, info->msi_dev);
+
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->data = sub_handle;
+		msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
+				  MSI_ADDR_IR_SHV |
+				  MSI_ADDR_IR_INDEX1(index) |
+				  MSI_ADDR_IR_INDEX2(index);
+		break;
+
+	default:
+		BUG_ON(1);
+		break;
+	}
+}
+
+static void intel_free_irq_resources(struct irq_domain *domain,
+				     unsigned int virq, unsigned int nr_irqs)
+{
+	struct irq_data *irq_data;
+	struct intel_ir_data *data;
+	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq  + i);
+		if (irq_data && irq_data->chip_data) {
+			data = irq_data->chip_data;
+			irq_iommu = &data->irq_2_iommu;
+			raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
+			clear_entries(irq_iommu);
+			raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+			irq_domain_reset_irq_data(irq_data);
+			kfree(data);
+		}
+	}
+}
+
+static int intel_irq_remapping_alloc(struct irq_domain *domain,
+				     unsigned int virq, unsigned int nr_irqs,
+				     void *arg)
+{
+	struct intel_iommu *iommu = domain->host_data;
+	struct irq_alloc_info *info = arg;
+	struct intel_ir_data *data;
+	struct irq_data *irq_data;
+	struct irq_cfg *irq_cfg;
+	int i, ret, index;
+
+	if (!info || !iommu)
+		return -EINVAL;
+	if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_MSI &&
+	    info->type != X86_IRQ_ALLOC_TYPE_MSIX)
+		return -EINVAL;
+
+	/*
+	 * With IRQ remapping enabled, don't need contigious CPU vectors
+	 * to support multiple MSI interrupts.
+	 */
+	if (info->type == X86_IRQ_ALLOC_TYPE_MSI)
+		info->flags &= ~X86_IRQ_ALLOC_CONTIGOUS_VECTORS;
+
+	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		goto out_free_parent;
+
+	down_read(&dmar_global_lock);
+	index = alloc_irte(iommu, virq, &data->irq_2_iommu, nr_irqs);
+	up_read(&dmar_global_lock);
+	if (index < 0) {
+		pr_warn("Failed to allocate IRTE\n");
+		kfree(data);
+		goto out_free_parent;
+	}
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq + i);
+		irq_cfg = irqd_cfg(irq_data);
+		if (!irq_data || !irq_cfg) {
+			ret = -EINVAL;
+			goto out_free_data;
+		}
+
+		if (i > 0) {
+			data = kzalloc(sizeof(*data), GFP_KERNEL);
+			if (!data)
+				goto out_free_data;
+		}
+		irq_data->hwirq = (index << 16) + i;
+		irq_data->chip_data = data;
+		irq_data->chip = &intel_ir_chip;
+		intel_irq_remapping_prepare_irte(data, irq_cfg, info, index, i);
+		irq_set_status_flags(virq + i, IRQ_MOVE_PCNTXT);
+	}
+	return 0;
+
+out_free_data:
+	intel_free_irq_resources(domain, virq, i);
+out_free_parent:
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+	return ret;
+}
+
+static void intel_irq_remapping_free(struct irq_domain *domain,
+				     unsigned int virq, unsigned int nr_irqs)
+{
+	intel_free_irq_resources(domain, virq, nr_irqs);
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+}
+
+static void intel_irq_remapping_activate(struct irq_domain *domain,
+					 struct irq_data *irq_data)
+{
+	struct intel_ir_data *data = irq_data->chip_data;
+
+	modify_irte(&data->irq_2_iommu, &data->irte_entry);
+}
+
+static void intel_irq_remapping_deactivate(struct irq_domain *domain,
+					   struct irq_data *irq_data)
+{
+	struct intel_ir_data *data = irq_data->chip_data;
+	struct irte entry;
+
+	memset(&entry, 0, sizeof(entry));
+	modify_irte(&data->irq_2_iommu, &entry);
+}
+
+static struct irq_domain_ops intel_ir_domain_ops = {
+	.alloc = intel_irq_remapping_alloc,
+	.free = intel_irq_remapping_free,
+	.activate = intel_irq_remapping_activate,
+	.deactivate = intel_irq_remapping_deactivate,
 };
 
 /*
include/linux/intel-iommu.h +4 -0
index a65208a8fe18..ecaf3a937845 100644
@@ -286,6 +286,8 @@ struct q_inval {
 
 #define INTR_REMAP_TABLE_ENTRIES	65536
 
+struct irq_domain;
+
 struct ir_table {
 	struct irte *base;
 	unsigned long *bitmap;
@@ -335,6 +337,8 @@ struct intel_iommu {
 
 #ifdef CONFIG_IRQ_REMAP
 	struct ir_table *ir_table;	/* Interrupt remapping info */
+	struct irq_domain *ir_domain;
+	struct irq_domain *ir_msi_domain;
 #endif
 	struct device	*iommu_dev; /* IOMMU-sysfs device */
 	int		node;
Signature · 1 line
1.7.10.4
#18 lore raw

[tip:x86/apic] irq_remapping/vt-d: Enhance Intel IR driver to support hierarchical irqdomains

irq_remapping/vt-d: Enhance Intel IR driver to support hierarchical irqdomains
Commit-ID:  b106ee63abccbba5f5a52d6e43168a6a30c6d98a
Gitweb:     http://git.kernel.org/tip/b106ee63abccbba5f5a52d6e43168a6a30c6d98a
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:32 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:48 +0200

irq_remapping/vt-d: Enhance Intel IR driver to support hierarchical irqdomains

Enhance Intel interrupt remapping driver to support hierarchical irqdomains. Implement intel_ir_chip to support stacked irq_chip.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc David Woodhouse <[email protected]>
---
 drivers/iommu/intel_irq_remapping.c | 337 +++++++++++++++++++++++++++++++++++-
 include/linux/intel-iommu.h         |   4 +
 2 files changed, 333 insertions(+), 8 deletions(-)
drivers/iommu/intel_irq_remapping.c +329 -8
index 0b89ef1..97ea420 100644
@@ -8,6 +8,7 @@
 #include <linux/irq.h>
 #include <linux/intel-iommu.h>
 #include <linux/acpi.h>
+#include <linux/irqdomain.h>
 #include <asm/io_apic.h>
 #include <asm/smp.h>
 #include <asm/cpu.h>
@@ -31,6 +32,14 @@ struct hpet_scope {
 	unsigned int devfn;
 };
 
+struct intel_ir_data {
+	struct irq_2_iommu			irq_2_iommu;
+	struct irte				irte_entry;
+	union {
+		struct msi_msg			msi_entry;
+	};
+};
+
 #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
 #define IRTE_DEST(dest) ((eim_mode) ? dest : dest << 8)
 
@@ -50,6 +59,7 @@ static struct hpet_scope ir_hpet[MAX_HPET_TBS];
  * the dmar_global_lock.
  */
 static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
+static struct irq_domain_ops intel_ir_domain_ops;
 
 static int __init parse_ioapics_under_ir(void);
 
@@ -263,7 +273,7 @@ static int free_irte(int irq)
 	unsigned long flags;
 	int rc;
 
-	if (!irq_iommu)
+	if (!irq_iommu || irq_iommu->iommu == NULL)
 		return -1;
 
 	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
@@ -488,7 +498,6 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
 
 	pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO,
 				 INTR_REMAP_PAGE_ORDER);
-
 	if (!pages) {
 		pr_err("IR%d: failed to allocate pages of order %d\n",
 		       iommu->seq_id, INTR_REMAP_PAGE_ORDER);
@@ -502,11 +511,23 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
 		goto out_free_pages;
 	}
 
+	iommu->ir_domain = irq_domain_add_hierarchy(arch_get_ir_parent_domain(),
+						    0, INTR_REMAP_TABLE_ENTRIES,
+						    NULL, &intel_ir_domain_ops,
+						    iommu);
+	if (!iommu->ir_domain) {
+		pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id);
+		goto out_free_bitmap;
+	}
+	iommu->ir_msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
+
 	ir_table->base = page_address(pages);
 	ir_table->bitmap = bitmap;
 	iommu->ir_table = ir_table;
 	return 0;
 
+out_free_bitmap:
+	kfree(bitmap);
 out_free_pages:
 	__free_pages(pages, INTR_REMAP_PAGE_ORDER);
 out_free_table:
@@ -517,6 +538,14 @@ out_free_table:
 static void intel_teardown_irq_remapping(struct intel_iommu *iommu)
 {
 	if (iommu && iommu->ir_table) {
+		if (iommu->ir_msi_domain) {
+			irq_domain_remove(iommu->ir_msi_domain);
+			iommu->ir_msi_domain = NULL;
+		}
+		if (iommu->ir_domain) {
+			irq_domain_remove(iommu->ir_domain);
+			iommu->ir_domain = NULL;
+		}
 		free_pages((unsigned long)iommu->ir_table->base,
 			   INTR_REMAP_PAGE_ORDER);
 		kfree(iommu->ir_table->bitmap);
@@ -1062,12 +1091,6 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	struct irte irte;
 	int err;
 
-	if (!config_enabled(CONFIG_SMP))
-		return -EINVAL;
-
-	if (!cpumask_intersects(mask, cpu_online_mask))
-		return -EINVAL;
-
 	if (get_irte(irq, &irte))
 		return -EBUSY;
 
@@ -1100,6 +1123,7 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 		send_cleanup_vector(cfg);
 
 	cpumask_copy(data->affinity, mask);
+
 	return 0;
 }
 
@@ -1205,6 +1229,53 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id)
 	return ret;
 }
 
+static struct irq_domain *intel_get_ir_irq_domain(struct irq_alloc_info *info)
+{
+	struct intel_iommu *iommu = NULL;
+
+	if (!info)
+		return NULL;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		iommu = map_ioapic_to_ir(info->ioapic_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_HPET:
+		iommu = map_hpet_to_ir(info->hpet_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		iommu = map_dev_to_ir(info->msi_dev);
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	return iommu ? iommu->ir_domain : NULL;
+}
+
+static struct irq_domain *intel_get_irq_domain(struct irq_alloc_info *info)
+{
+	struct intel_iommu *iommu;
+
+	if (!info)
+		return NULL;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		iommu = map_dev_to_ir(info->msi_dev);
+		if (iommu)
+			return iommu->ir_msi_domain;
+		break;
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
 struct irq_remap_ops intel_irq_remap_ops = {
 	.prepare		= intel_prepare_irq_remapping,
 	.enable			= intel_enable_irq_remapping,
@@ -1218,6 +1289,256 @@ struct irq_remap_ops intel_irq_remap_ops = {
 	.msi_alloc_irq		= intel_msi_alloc_irq,
 	.msi_setup_irq		= intel_msi_setup_irq,
 	.alloc_hpet_msi		= intel_alloc_hpet_msi,
+	.get_ir_irq_domain	= intel_get_ir_irq_domain,
+	.get_irq_domain		= intel_get_irq_domain,
+};
+
+/*
+ * Migrate the IO-APIC irq in the presence of intr-remapping.
+ *
+ * For both level and edge triggered, irq migration is a simple atomic
+ * update(of vector and cpu destination) of IRTE and flush the hardware cache.
+ *
+ * For level triggered, we eliminate the io-apic RTE modification (with the
+ * updated vector information), by using a virtual vector (io-apic pin number).
+ * Real vector that is used for interrupting cpu will be coming from
+ * the interrupt-remapping table entry.
+ *
+ * As the migration is a simple atomic update of IRTE, the same mechanism
+ * is used to migrate MSI irq's in the presence of interrupt-remapping.
+ */
+static int
+intel_ir_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		      bool force)
+{
+	struct intel_ir_data *ir_data = data->chip_data;
+	struct irte *irte = &ir_data->irte_entry;
+	struct irq_cfg *cfg = irqd_cfg(data);
+	struct irq_data *parent = data->parent_data;
+	int ret;
+
+	ret = parent->chip->irq_set_affinity(parent, mask, force);
+	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
+		return ret;
+
+	/*
+	 * Atomically updates the IRTE with the new destination, vector
+	 * and flushes the interrupt entry cache.
+	 */
+	irte->vector = cfg->vector;
+	irte->dest_id = IRTE_DEST(cfg->dest_apicid);
+	modify_irte(&ir_data->irq_2_iommu, irte);
+
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
+	return IRQ_SET_MASK_OK_DONE;
+}
+
+static void intel_ir_compose_msi_msg(struct irq_data *irq_data,
+				     struct msi_msg *msg)
+{
+	struct intel_ir_data *ir_data = irq_data->chip_data;
+
+	*msg = ir_data->msi_entry;
+}
+
+static struct irq_chip intel_ir_chip = {
+	.irq_ack = ir_ack_apic_edge,
+	.irq_set_affinity = intel_ir_set_affinity,
+	.irq_compose_msi_msg = intel_ir_compose_msi_msg,
+};
+
+static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
+					     struct irq_cfg *irq_cfg,
+					     struct irq_alloc_info *info,
+					     int index, int sub_handle)
+{
+	struct IR_IO_APIC_route_entry *entry;
+	struct irte *irte = &data->irte_entry;
+	struct msi_msg *msg = &data->msi_entry;
+
+	prepare_irte(irte, irq_cfg->vector, irq_cfg->dest_apicid);
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		/* Set source-id of interrupt request */
+		set_ioapic_sid(irte, info->ioapic_id);
+		apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: Set IRTE entry (P:%d FPD:%d Dst_Mode:%d Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X Avail:%X Vector:%02X Dest:%08X SID:%04X SQ:%X SVT:%X)\n",
+			info->ioapic_id, irte->present, irte->fpd,
+			irte->dst_mode, irte->redir_hint,
+			irte->trigger_mode, irte->dlvry_mode,
+			irte->avail, irte->vector, irte->dest_id,
+			irte->sid, irte->sq, irte->svt);
+
+		entry = (struct IR_IO_APIC_route_entry *)info->ioapic_entry;
+		info->ioapic_entry = NULL;
+		memset(entry, 0, sizeof(*entry));
+		entry->index2	= (index >> 15) & 0x1;
+		entry->zero	= 0;
+		entry->format	= 1;
+		entry->index	= (index & 0x7fff);
+		/*
+		 * IO-APIC RTE will be configured with virtual vector.
+		 * irq handler will do the explicit EOI to the io-apic.
+		 */
+		entry->vector	= info->ioapic_pin;
+		entry->mask	= 0;			/* enable IRQ */
+		entry->trigger	= info->ioapic_trigger;
+		entry->polarity	= info->ioapic_polarity;
+		if (info->ioapic_trigger)
+			entry->mask = 1; /* Mask level triggered irqs. */
+		break;
+
+	case X86_IRQ_ALLOC_TYPE_HPET:
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		if (info->type == X86_IRQ_ALLOC_TYPE_HPET)
+			set_hpet_sid(irte, info->hpet_id);
+		else
+			set_msi_sid(irte, info->msi_dev);
+
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->data = sub_handle;
+		msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
+				  MSI_ADDR_IR_SHV |
+				  MSI_ADDR_IR_INDEX1(index) |
+				  MSI_ADDR_IR_INDEX2(index);
+		break;
+
+	default:
+		BUG_ON(1);
+		break;
+	}
+}
+
+static void intel_free_irq_resources(struct irq_domain *domain,
+				     unsigned int virq, unsigned int nr_irqs)
+{
+	struct irq_data *irq_data;
+	struct intel_ir_data *data;
+	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq  + i);
+		if (irq_data && irq_data->chip_data) {
+			data = irq_data->chip_data;
+			irq_iommu = &data->irq_2_iommu;
+			raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
+			clear_entries(irq_iommu);
+			raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+			irq_domain_reset_irq_data(irq_data);
+			kfree(data);
+		}
+	}
+}
+
+static int intel_irq_remapping_alloc(struct irq_domain *domain,
+				     unsigned int virq, unsigned int nr_irqs,
+				     void *arg)
+{
+	struct intel_iommu *iommu = domain->host_data;
+	struct irq_alloc_info *info = arg;
+	struct intel_ir_data *data;
+	struct irq_data *irq_data;
+	struct irq_cfg *irq_cfg;
+	int i, ret, index;
+
+	if (!info || !iommu)
+		return -EINVAL;
+	if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_MSI &&
+	    info->type != X86_IRQ_ALLOC_TYPE_MSIX)
+		return -EINVAL;
+
+	/*
+	 * With IRQ remapping enabled, don't need contiguous CPU vectors
+	 * to support multiple MSI interrupts.
+	 */
+	if (info->type == X86_IRQ_ALLOC_TYPE_MSI)
+		info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
+
+	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		goto out_free_parent;
+
+	down_read(&dmar_global_lock);
+	index = alloc_irte(iommu, virq, &data->irq_2_iommu, nr_irqs);
+	up_read(&dmar_global_lock);
+	if (index < 0) {
+		pr_warn("Failed to allocate IRTE\n");
+		kfree(data);
+		goto out_free_parent;
+	}
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq + i);
+		irq_cfg = irqd_cfg(irq_data);
+		if (!irq_data || !irq_cfg) {
+			ret = -EINVAL;
+			goto out_free_data;
+		}
+
+		if (i > 0) {
+			data = kzalloc(sizeof(*data), GFP_KERNEL);
+			if (!data)
+				goto out_free_data;
+		}
+		irq_data->hwirq = (index << 16) + i;
+		irq_data->chip_data = data;
+		irq_data->chip = &intel_ir_chip;
+		intel_irq_remapping_prepare_irte(data, irq_cfg, info, index, i);
+		irq_set_status_flags(virq + i, IRQ_MOVE_PCNTXT);
+	}
+	return 0;
+
+out_free_data:
+	intel_free_irq_resources(domain, virq, i);
+out_free_parent:
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+	return ret;
+}
+
+static void intel_irq_remapping_free(struct irq_domain *domain,
+				     unsigned int virq, unsigned int nr_irqs)
+{
+	intel_free_irq_resources(domain, virq, nr_irqs);
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+}
+
+static void intel_irq_remapping_activate(struct irq_domain *domain,
+					 struct irq_data *irq_data)
+{
+	struct intel_ir_data *data = irq_data->chip_data;
+
+	modify_irte(&data->irq_2_iommu, &data->irte_entry);
+}
+
+static void intel_irq_remapping_deactivate(struct irq_domain *domain,
+					   struct irq_data *irq_data)
+{
+	struct intel_ir_data *data = irq_data->chip_data;
+	struct irte entry;
+
+	memset(&entry, 0, sizeof(entry));
+	modify_irte(&data->irq_2_iommu, &entry);
+}
+
+static struct irq_domain_ops intel_ir_domain_ops = {
+	.alloc = intel_irq_remapping_alloc,
+	.free = intel_irq_remapping_free,
+	.activate = intel_irq_remapping_activate,
+	.deactivate = intel_irq_remapping_deactivate,
 };
 
 /*
include/linux/intel-iommu.h +4 -0
index a65208a..ecaf3a9 100644
@@ -286,6 +286,8 @@ struct q_inval {
 
 #define INTR_REMAP_TABLE_ENTRIES	65536
 
+struct irq_domain;
+
 struct ir_table {
 	struct irte *base;
 	unsigned long *bitmap;
@@ -335,6 +337,8 @@ struct intel_iommu {
 
 #ifdef CONFIG_IRQ_REMAP
 	struct ir_table *ir_table;	/* Interrupt remapping info */
+	struct irq_domain *ir_domain;
+	struct irq_domain *ir_msi_domain;
 #endif
 	struct device	*iommu_dev; /* IOMMU-sysfs device */
 	int		node;
author
#19 lore raw

PATCH v8 11/37 irq_remapping/amd: Enhance AMD IR driver to support hierarchy irqdomain

In reply to Jiang Liu

Enhance AMD interrupt remapping driver to support hierarchy irqdomain, it will simplify the code eventually.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/amd_iommu.c       |  329 ++++++++++++++++++++++++++++++++++++++-
 drivers/iommu/amd_iommu_init.c  |    4 +
 drivers/iommu/amd_iommu_proto.h |    9 ++
 drivers/iommu/amd_iommu_types.h |    5 +
 4 files changed, 341 insertions(+), 6 deletions(-)
drivers/iommu/amd_iommu.c +323 -6
index 48882c126245..db974bd348a1 100644
@@ -33,6 +33,7 @@
 #include <linux/export.h>
 #include <linux/irq.h>
 #include <linux/msi.h>
+#include <linux/irqdomain.h>
 #include <asm/irq_remapping.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
@@ -3857,6 +3858,16 @@ union irte {
 	} fields;
 };
 
+struct amd_ir_data {
+	struct irq_2_irte			irq_2_irte;
+	union irte				irte_entry;
+	union {
+		struct msi_msg			msi_entry;
+	};
+};
+
+static struct irq_chip amd_ir_chip;
+
 #define DTE_IRQ_PHYS_ADDR_MASK	(((1ULL << 45)-1) << 6)
 #define DTE_IRQ_REMAP_INTCTL    (2ULL << 60)
 #define DTE_IRQ_TABLE_LEN       (8ULL << 1)
@@ -3950,7 +3961,8 @@ out_unlock:
 	return table;
 }
 
-static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count)
+static int alloc_irq_index(struct irq_cfg *cfg, struct irq_2_irte *irte_info,
+			   u16 devid, int count)
 {
 	struct irq_remap_table *table;
 	unsigned long flags;
@@ -3972,15 +3984,12 @@ static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count)
 			c = 0;
 
 		if (c == count)	{
-			struct irq_2_irte *irte_info;
-
 			for (; c != 0; --c)
 				table->table[index - c + 1] = IRTE_ALLOCATED;
 
 			index -= count - 1;
 
 			cfg->remapped	      = 1;
-			irte_info             = &cfg->irq_2_irte;
 			irte_info->devid      = devid;
 			irte_info->index      = index;
 
@@ -4225,7 +4234,7 @@ static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
 		return -EINVAL;
 
 	devid = get_device_id(&pdev->dev);
-	index = alloc_irq_index(cfg, devid, nvec);
+	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, nvec);
 
 	return index < 0 ? MAX_IRQS_PER_TABLE : index;
 }
@@ -4272,7 +4281,7 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id)
 	if (devid < 0)
 		return devid;
 
-	index = alloc_irq_index(cfg, devid, 1);
+	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, 1);
 	if (index < 0)
 		return index;
 
@@ -4283,6 +4292,72 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id)
 	return 0;
 }
 
+static int get_devid(struct irq_alloc_info *info)
+{
+	int devid = -1;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		devid     = get_ioapic_devid(info->ioapic_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_HPET:
+		devid     = get_hpet_devid(info->hpet_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		devid = get_device_id(&info->msi_dev->dev);
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	return devid;
+}
+
+static struct irq_domain *get_ir_irq_domain(struct irq_alloc_info *info)
+{
+	int devid;
+	struct amd_iommu *iommu;
+
+	if (!info)
+		return NULL;
+
+	devid = get_devid(info);
+	if (devid >= 0) {
+		iommu = amd_iommu_rlookup_table[devid];
+		if (iommu)
+			return iommu->ir_domain;
+	}
+
+	return NULL;
+}
+
+static struct irq_domain *get_irq_domain(struct irq_alloc_info *info)
+{
+	int devid;
+	struct amd_iommu *iommu;
+
+	if (!info)
+		return NULL;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		devid = get_device_id(&info->msi_dev->dev);
+		if (devid >= 0) {
+			iommu = amd_iommu_rlookup_table[devid];
+			if (iommu)
+				return iommu->msi_domain;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
 struct irq_remap_ops amd_iommu_irq_ops = {
 	.prepare		= amd_iommu_prepare,
 	.enable			= amd_iommu_enable,
@@ -4296,5 +4371,247 @@ struct irq_remap_ops amd_iommu_irq_ops = {
 	.msi_alloc_irq		= msi_alloc_irq,
 	.msi_setup_irq		= msi_setup_irq,
 	.alloc_hpet_msi		= alloc_hpet_msi,
+	.get_ir_irq_domain	= get_ir_irq_domain,
+	.get_irq_domain		= get_irq_domain,
+};
+
+static void irq_remapping_prepare_irte(struct amd_ir_data *data,
+				       struct irq_cfg *irq_cfg,
+				       struct irq_alloc_info *info,
+				       int devid, int index, int sub_handle)
+{
+	union irte *irte = &data->irte_entry;
+	struct irq_2_irte *irte_info = &data->irq_2_irte;
+	struct msi_msg *msg = &data->msi_entry;
+	struct IO_APIC_route_entry *entry;
+
+	irq_cfg->remapped = 1;
+	data->irq_2_irte.devid = devid;
+	data->irq_2_irte.index = index + sub_handle;
+
+	/* Setup IRTE for IOMMU */
+	irte->val = 0;
+	irte->fields.vector      = irq_cfg->vector;
+	irte->fields.int_type    = apic->irq_delivery_mode;
+	irte->fields.destination = irq_cfg->dest_apicid;
+	irte->fields.dm          = apic->irq_dest_mode;
+	irte->fields.valid       = 1;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		/* Setup IOAPIC entry */
+		entry = info->ioapic_entry;
+		info->ioapic_entry = NULL;
+		memset(entry, 0, sizeof(*entry));
+		entry->vector        = index;
+		entry->mask          = 0;
+		entry->trigger       = info->ioapic_trigger;
+		entry->polarity      = info->ioapic_polarity;
+		/* Mask level triggered irqs. */
+		if (info->ioapic_trigger)
+			entry->mask = 1;
+		break;
+
+	case X86_IRQ_ALLOC_TYPE_HPET:
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->address_lo = MSI_ADDR_BASE_LO;
+		msg->data = irte_info->index;
+		break;
+
+	default:
+		BUG_ON(1);
+		break;
+	}
+}
+
+static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
+			       unsigned int nr_irqs, void *arg)
+{
+	struct irq_alloc_info *info = arg;
+	struct amd_ir_data *data;
+	struct irq_data *irq_data;
+	struct irq_cfg *cfg;
+	int i, ret, devid;
+	int index = -1;
+
+	if (!info)
+		return -EINVAL;
+	if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_MSI &&
+	    info->type != X86_IRQ_ALLOC_TYPE_MSIX)
+		return -EINVAL;
+
+	/*
+	 * With IRQ remapping enabled, don't need contigious CPU vectors
+	 * to support multiple MSI interrupts.
+	 */
+	if (info->type == X86_IRQ_ALLOC_TYPE_MSI)
+		info->flags &= ~X86_IRQ_ALLOC_CONTIGOUS_VECTORS;
+
+	devid = get_devid(info);
+	if (devid < 0)
+		return -EINVAL;
+
+	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		goto out_free_parent;
+
+	if (info->type == X86_IRQ_ALLOC_TYPE_IOAPIC) {
+		if (get_irq_table(devid, true))
+			index = info->ioapic_pin;
+		else
+			ret = -ENOMEM;
+	} else {
+		cfg = irq_cfg(virq);
+		index = alloc_irq_index(cfg, &data->irq_2_irte, devid, nr_irqs);
+	}
+	if (index < 0) {
+		pr_warn("Failed to allocate IRTE\n");
+		kfree(data);
+		goto out_free_parent;
+	}
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq + i);
+		cfg = irqd_cfg(irq_data);
+		if (!irq_data || !cfg) {
+			ret = -EINVAL;
+			goto out_free_data;
+		}
+
+		if (i > 0) {
+			data = kzalloc(sizeof(*data), GFP_KERNEL);
+			if (!data)
+				goto out_free_data;
+		}
+		irq_data->hwirq = (devid << 16) + i;
+		irq_data->chip_data = data;
+		irq_data->chip = &amd_ir_chip;
+		irq_remapping_prepare_irte(data, cfg, info, devid, index, i);
+		irq_set_status_flags(virq + i, IRQ_MOVE_PCNTXT);
+	}
+	return 0;
+
+out_free_data:
+	for (i--; i >= 0; i--) {
+		irq_data = irq_domain_get_irq_data(domain, virq + i);
+		if (irq_data)
+			kfree(irq_data->chip_data);
+	}
+	for (i = 0; i < nr_irqs; i++)
+		free_irte(devid, index + i);
+out_free_parent:
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+	return ret;
+}
+
+static void irq_remapping_free(struct irq_domain *domain, unsigned int virq,
+			       unsigned int nr_irqs)
+{
+	struct irq_data *irq_data;
+	struct amd_ir_data *data;
+	struct irq_2_irte *irte_info;
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq  + i);
+		if (irq_data && irq_data->chip_data) {
+			data = irq_data->chip_data;
+			irte_info = &data->irq_2_irte;
+			free_irte(irte_info->devid, irte_info->index);
+			kfree(data);
+		}
+	}
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+}
+
+static void irq_remapping_activate(struct irq_domain *domain,
+				   struct irq_data *irq_data)
+{
+	struct amd_ir_data *data = irq_data->chip_data;
+	struct irq_2_irte *irte_info = &data->irq_2_irte;
+
+	modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+}
+
+static void irq_remapping_deactivate(struct irq_domain *domain,
+				     struct irq_data *irq_data)
+{
+	struct amd_ir_data *data = irq_data->chip_data;
+	struct irq_2_irte *irte_info = &data->irq_2_irte;
+	union irte entry;
+
+	entry.val = 0;
+	modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+}
+
+static struct irq_domain_ops amd_ir_domain_ops = {
+	.alloc = irq_remapping_alloc,
+	.free = irq_remapping_free,
+	.activate = irq_remapping_activate,
+	.deactivate = irq_remapping_deactivate,
 };
+
+static int amd_ir_set_affinity(struct irq_data *data,
+			       const struct cpumask *mask, bool force)
+{
+	struct amd_ir_data *ir_data = data->chip_data;
+	struct irq_2_irte *irte_info = &ir_data->irq_2_irte;
+	struct irq_cfg *cfg = irqd_cfg(data);
+	struct irq_data *parent = data->parent_data;
+	int ret;
+
+	ret = parent->chip->irq_set_affinity(parent, mask, force);
+	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
+		return ret;
+
+	/*
+	 * Atomically updates the IRTE with the new destination, vector
+	 * and flushes the interrupt entry cache.
+	 */
+	ir_data->irte_entry.fields.vector = cfg->vector;
+	ir_data->irte_entry.fields.destination = cfg->dest_apicid;
+	modify_irte(irte_info->devid, irte_info->index, ir_data->irte_entry);
+
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
+	return IRQ_SET_MASK_OK_DONE;
+}
+
+static void ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
+{
+	struct amd_ir_data *ir_data = irq_data->chip_data;
+
+	*msg = ir_data->msi_entry;
+}
+
+static struct irq_chip amd_ir_chip = {
+	.irq_ack = ir_ack_apic_edge,
+	.irq_set_affinity = amd_ir_set_affinity,
+	.irq_compose_msi_msg = ir_compose_msi_msg,
+};
+
+int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
+{
+	iommu->ir_domain = irq_domain_add_tree(NULL, &amd_ir_domain_ops, iommu);
+	if (!iommu->ir_domain)
+		return -ENOMEM;
+
+	iommu->ir_domain->parent = arch_get_ir_parent_domain();
+	iommu->msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
+
+	return 0;
+}
 #endif
drivers/iommu/amd_iommu_init.c +4 -0
index 450ef5001a65..c17df04d7a7f 100644
@@ -1124,6 +1124,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 	if (ret)
 		return ret;
 
+	ret = amd_iommu_create_irq_domain(iommu);
+	if (ret)
+		return ret;
+
 	/*
 	 * Make sure IOMMU is not considered to translate itself. The IVRS
 	 * table tells us so, but this is a lie!
drivers/iommu/amd_iommu_proto.h +9 -0
index 72b0fd455e24..0a21142d3639 100644
@@ -62,6 +62,15 @@ extern u8 amd_iommu_pc_get_max_counters(u16 devid);
 extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
 				    u64 *value, bool is_write);
 
+#ifdef CONFIG_IRQ_REMAP
+extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu);
+#else
+static inline int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
+{
+	return 0;
+}
+#endif
+
 #define PPR_SUCCESS			0x0
 #define PPR_INVALID			0x1
 #define PPR_FAILURE			0xf
drivers/iommu/amd_iommu_types.h +5 -0
index c4fffb710c58..e2972a38c1ea 100644
@@ -392,6 +392,7 @@ struct amd_iommu_fault {
 
 
 struct iommu_domain;
+struct irq_domain;
 
 /*
  * This structure contains generic data for  IOMMU protection domains
@@ -574,6 +575,10 @@ struct amd_iommu {
 	/* The maximum PC banks and counters/bank (PCSup=1) */
 	u8 max_banks;
 	u8 max_counters;
+#ifdef CONFIG_IRQ_REMAP
+	struct irq_domain *ir_domain;
+	struct irq_domain *msi_domain;
+#endif
 };
 
 struct devid_map {
Signature · 1 line
1.7.10.4
#20 lore raw

[tip:x86/apic] irq_remapping/amd: Enhance AMD IR driver to support hierarchical irqdomains

irq_remapping/amd: Enhance AMD IR driver to support hierarchical irqdomains
Commit-ID:  7c71d306c97bd060e1a97d6905aebcb5769890ca
Gitweb:     http://git.kernel.org/tip/7c71d306c97bd060e1a97d6905aebcb5769890ca
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:33 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:48 +0200

irq_remapping/amd: Enhance AMD IR driver to support hierarchical irqdomains

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/amd_iommu.c       | 329 +++++++++++++++++++++++++++++++++++++++-
 drivers/iommu/amd_iommu_init.c  |   4 +
 drivers/iommu/amd_iommu_proto.h |   9 ++
 drivers/iommu/amd_iommu_types.h |   5 +
 4 files changed, 341 insertions(+), 6 deletions(-)
drivers/iommu/amd_iommu.c +323 -6
index e43d489..a14ba26 100644
@@ -34,6 +34,7 @@
 #include <linux/irq.h>
 #include <linux/msi.h>
 #include <linux/dma-contiguous.h>
+#include <linux/irqdomain.h>
 #include <asm/irq_remapping.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
@@ -3851,6 +3852,16 @@ union irte {
 	} fields;
 };
 
+struct amd_ir_data {
+	struct irq_2_irte			irq_2_irte;
+	union irte				irte_entry;
+	union {
+		struct msi_msg			msi_entry;
+	};
+};
+
+static struct irq_chip amd_ir_chip;
+
 #define DTE_IRQ_PHYS_ADDR_MASK	(((1ULL << 45)-1) << 6)
 #define DTE_IRQ_REMAP_INTCTL    (2ULL << 60)
 #define DTE_IRQ_TABLE_LEN       (8ULL << 1)
@@ -3944,7 +3955,8 @@ out_unlock:
 	return table;
 }
 
-static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count)
+static int alloc_irq_index(struct irq_cfg *cfg, struct irq_2_irte *irte_info,
+			   u16 devid, int count)
 {
 	struct irq_remap_table *table;
 	unsigned long flags;
@@ -3966,15 +3978,12 @@ static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count)
 			c = 0;
 
 		if (c == count)	{
-			struct irq_2_irte *irte_info;
-
 			for (; c != 0; --c)
 				table->table[index - c + 1] = IRTE_ALLOCATED;
 
 			index -= count - 1;
 
 			cfg->remapped	      = 1;
-			irte_info             = &cfg->irq_2_irte;
 			irte_info->devid      = devid;
 			irte_info->index      = index;
 
@@ -4219,7 +4228,7 @@ static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
 		return -EINVAL;
 
 	devid = get_device_id(&pdev->dev);
-	index = alloc_irq_index(cfg, devid, nvec);
+	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, nvec);
 
 	return index < 0 ? MAX_IRQS_PER_TABLE : index;
 }
@@ -4266,7 +4275,7 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id)
 	if (devid < 0)
 		return devid;
 
-	index = alloc_irq_index(cfg, devid, 1);
+	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, 1);
 	if (index < 0)
 		return index;
 
@@ -4277,6 +4286,72 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id)
 	return 0;
 }
 
+static int get_devid(struct irq_alloc_info *info)
+{
+	int devid = -1;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		devid     = get_ioapic_devid(info->ioapic_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_HPET:
+		devid     = get_hpet_devid(info->hpet_id);
+		break;
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		devid = get_device_id(&info->msi_dev->dev);
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	return devid;
+}
+
+static struct irq_domain *get_ir_irq_domain(struct irq_alloc_info *info)
+{
+	struct amd_iommu *iommu;
+	int devid;
+
+	if (!info)
+		return NULL;
+
+	devid = get_devid(info);
+	if (devid >= 0) {
+		iommu = amd_iommu_rlookup_table[devid];
+		if (iommu)
+			return iommu->ir_domain;
+	}
+
+	return NULL;
+}
+
+static struct irq_domain *get_irq_domain(struct irq_alloc_info *info)
+{
+	struct amd_iommu *iommu;
+	int devid;
+
+	if (!info)
+		return NULL;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		devid = get_device_id(&info->msi_dev->dev);
+		if (devid >= 0) {
+			iommu = amd_iommu_rlookup_table[devid];
+			if (iommu)
+				return iommu->msi_domain;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
 struct irq_remap_ops amd_iommu_irq_ops = {
 	.prepare		= amd_iommu_prepare,
 	.enable			= amd_iommu_enable,
@@ -4290,5 +4365,247 @@ struct irq_remap_ops amd_iommu_irq_ops = {
 	.msi_alloc_irq		= msi_alloc_irq,
 	.msi_setup_irq		= msi_setup_irq,
 	.alloc_hpet_msi		= alloc_hpet_msi,
+	.get_ir_irq_domain	= get_ir_irq_domain,
+	.get_irq_domain		= get_irq_domain,
+};
+
+static void irq_remapping_prepare_irte(struct amd_ir_data *data,
+				       struct irq_cfg *irq_cfg,
+				       struct irq_alloc_info *info,
+				       int devid, int index, int sub_handle)
+{
+	struct irq_2_irte *irte_info = &data->irq_2_irte;
+	struct msi_msg *msg = &data->msi_entry;
+	union irte *irte = &data->irte_entry;
+	struct IO_APIC_route_entry *entry;
+
+	irq_cfg->remapped = 1;
+	data->irq_2_irte.devid = devid;
+	data->irq_2_irte.index = index + sub_handle;
+
+	/* Setup IRTE for IOMMU */
+	irte->val = 0;
+	irte->fields.vector      = irq_cfg->vector;
+	irte->fields.int_type    = apic->irq_delivery_mode;
+	irte->fields.destination = irq_cfg->dest_apicid;
+	irte->fields.dm          = apic->irq_dest_mode;
+	irte->fields.valid       = 1;
+
+	switch (info->type) {
+	case X86_IRQ_ALLOC_TYPE_IOAPIC:
+		/* Setup IOAPIC entry */
+		entry = info->ioapic_entry;
+		info->ioapic_entry = NULL;
+		memset(entry, 0, sizeof(*entry));
+		entry->vector        = index;
+		entry->mask          = 0;
+		entry->trigger       = info->ioapic_trigger;
+		entry->polarity      = info->ioapic_polarity;
+		/* Mask level triggered irqs. */
+		if (info->ioapic_trigger)
+			entry->mask = 1;
+		break;
+
+	case X86_IRQ_ALLOC_TYPE_HPET:
+	case X86_IRQ_ALLOC_TYPE_MSI:
+	case X86_IRQ_ALLOC_TYPE_MSIX:
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->address_lo = MSI_ADDR_BASE_LO;
+		msg->data = irte_info->index;
+		break;
+
+	default:
+		BUG_ON(1);
+		break;
+	}
+}
+
+static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
+			       unsigned int nr_irqs, void *arg)
+{
+	struct irq_alloc_info *info = arg;
+	struct irq_data *irq_data;
+	struct amd_ir_data *data;
+	struct irq_cfg *cfg;
+	int i, ret, devid;
+	int index = -1;
+
+	if (!info)
+		return -EINVAL;
+	if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_MSI &&
+	    info->type != X86_IRQ_ALLOC_TYPE_MSIX)
+		return -EINVAL;
+
+	/*
+	 * With IRQ remapping enabled, don't need contiguous CPU vectors
+	 * to support multiple MSI interrupts.
+	 */
+	if (info->type == X86_IRQ_ALLOC_TYPE_MSI)
+		info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
+
+	devid = get_devid(info);
+	if (devid < 0)
+		return -EINVAL;
+
+	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		goto out_free_parent;
+
+	if (info->type == X86_IRQ_ALLOC_TYPE_IOAPIC) {
+		if (get_irq_table(devid, true))
+			index = info->ioapic_pin;
+		else
+			ret = -ENOMEM;
+	} else {
+		cfg = irq_cfg(virq);
+		index = alloc_irq_index(cfg, &data->irq_2_irte, devid, nr_irqs);
+	}
+	if (index < 0) {
+		pr_warn("Failed to allocate IRTE\n");
+		kfree(data);
+		goto out_free_parent;
+	}
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq + i);
+		cfg = irqd_cfg(irq_data);
+		if (!irq_data || !cfg) {
+			ret = -EINVAL;
+			goto out_free_data;
+		}
+
+		if (i > 0) {
+			data = kzalloc(sizeof(*data), GFP_KERNEL);
+			if (!data)
+				goto out_free_data;
+		}
+		irq_data->hwirq = (devid << 16) + i;
+		irq_data->chip_data = data;
+		irq_data->chip = &amd_ir_chip;
+		irq_remapping_prepare_irte(data, cfg, info, devid, index, i);
+		irq_set_status_flags(virq + i, IRQ_MOVE_PCNTXT);
+	}
+	return 0;
+
+out_free_data:
+	for (i--; i >= 0; i--) {
+		irq_data = irq_domain_get_irq_data(domain, virq + i);
+		if (irq_data)
+			kfree(irq_data->chip_data);
+	}
+	for (i = 0; i < nr_irqs; i++)
+		free_irte(devid, index + i);
+out_free_parent:
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+	return ret;
+}
+
+static void irq_remapping_free(struct irq_domain *domain, unsigned int virq,
+			       unsigned int nr_irqs)
+{
+	struct irq_2_irte *irte_info;
+	struct irq_data *irq_data;
+	struct amd_ir_data *data;
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_data = irq_domain_get_irq_data(domain, virq  + i);
+		if (irq_data && irq_data->chip_data) {
+			data = irq_data->chip_data;
+			irte_info = &data->irq_2_irte;
+			free_irte(irte_info->devid, irte_info->index);
+			kfree(data);
+		}
+	}
+	irq_domain_free_irqs_common(domain, virq, nr_irqs);
+}
+
+static void irq_remapping_activate(struct irq_domain *domain,
+				   struct irq_data *irq_data)
+{
+	struct amd_ir_data *data = irq_data->chip_data;
+	struct irq_2_irte *irte_info = &data->irq_2_irte;
+
+	modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+}
+
+static void irq_remapping_deactivate(struct irq_domain *domain,
+				     struct irq_data *irq_data)
+{
+	struct amd_ir_data *data = irq_data->chip_data;
+	struct irq_2_irte *irte_info = &data->irq_2_irte;
+	union irte entry;
+
+	entry.val = 0;
+	modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+}
+
+static struct irq_domain_ops amd_ir_domain_ops = {
+	.alloc = irq_remapping_alloc,
+	.free = irq_remapping_free,
+	.activate = irq_remapping_activate,
+	.deactivate = irq_remapping_deactivate,
 };
+
+static int amd_ir_set_affinity(struct irq_data *data,
+			       const struct cpumask *mask, bool force)
+{
+	struct amd_ir_data *ir_data = data->chip_data;
+	struct irq_2_irte *irte_info = &ir_data->irq_2_irte;
+	struct irq_cfg *cfg = irqd_cfg(data);
+	struct irq_data *parent = data->parent_data;
+	int ret;
+
+	ret = parent->chip->irq_set_affinity(parent, mask, force);
+	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
+		return ret;
+
+	/*
+	 * Atomically updates the IRTE with the new destination, vector
+	 * and flushes the interrupt entry cache.
+	 */
+	ir_data->irte_entry.fields.vector = cfg->vector;
+	ir_data->irte_entry.fields.destination = cfg->dest_apicid;
+	modify_irte(irte_info->devid, irte_info->index, ir_data->irte_entry);
+
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
+	return IRQ_SET_MASK_OK_DONE;
+}
+
+static void ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
+{
+	struct amd_ir_data *ir_data = irq_data->chip_data;
+
+	*msg = ir_data->msi_entry;
+}
+
+static struct irq_chip amd_ir_chip = {
+	.irq_ack = ir_ack_apic_edge,
+	.irq_set_affinity = amd_ir_set_affinity,
+	.irq_compose_msi_msg = ir_compose_msi_msg,
+};
+
+int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
+{
+	iommu->ir_domain = irq_domain_add_tree(NULL, &amd_ir_domain_ops, iommu);
+	if (!iommu->ir_domain)
+		return -ENOMEM;
+
+	iommu->ir_domain->parent = arch_get_ir_parent_domain();
+	iommu->msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
+
+	return 0;
+}
 #endif
drivers/iommu/amd_iommu_init.c +4 -0
index 450ef50..c17df04 100644
@@ -1124,6 +1124,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 	if (ret)
 		return ret;
 
+	ret = amd_iommu_create_irq_domain(iommu);
+	if (ret)
+		return ret;
+
 	/*
 	 * Make sure IOMMU is not considered to translate itself. The IVRS
 	 * table tells us so, but this is a lie!
drivers/iommu/amd_iommu_proto.h +9 -0
index 72b0fd4..0a21142 100644
@@ -62,6 +62,15 @@ extern u8 amd_iommu_pc_get_max_counters(u16 devid);
 extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
 				    u64 *value, bool is_write);
 
+#ifdef CONFIG_IRQ_REMAP
+extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu);
+#else
+static inline int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
+{
+	return 0;
+}
+#endif
+
 #define PPR_SUCCESS			0x0
 #define PPR_INVALID			0x1
 #define PPR_FAILURE			0xf
drivers/iommu/amd_iommu_types.h +5 -0
index 05030e5..6533e87 100644
@@ -398,6 +398,7 @@ struct amd_iommu_fault {
 
 
 struct iommu_domain;
+struct irq_domain;
 
 /*
  * This structure contains generic data for  IOMMU protection domains
@@ -579,6 +580,10 @@ struct amd_iommu {
 	/* The maximum PC banks and counters/bank (PCSup=1) */
 	u8 max_banks;
 	u8 max_counters;
+#ifdef CONFIG_IRQ_REMAP
+	struct irq_domain *ir_domain;
+	struct irq_domain *msi_domain;
+#endif
 };
 
 struct devid_map {
author
#21 lore raw

PATCH v8 12/37 x86/hpet: Enhance HPET IRQ to support hierarchy irqdomain

In reply to Jiang Liu

Enhance HPET code to support hierarchy irqdomain, it helps to make the architecture more clear.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Srivatsa S. Bhat <[email protected]>
Cc Andy Lutomirski <[email protected]>
---
 arch/x86/include/asm/hpet.h |    7 +-
 arch/x86/kernel/apic/msi.c  |  166 ++++++++++++++++++++++++++++++++++++++-----
 arch/x86/kernel/hpet.c      |   57 ++++-----------
 3 files changed, 167 insertions(+), 63 deletions(-)
arch/x86/include/asm/hpet.h +6 -1
index 36f7125945e3..e87e9faf87a9 100644
@@ -74,11 +74,16 @@ extern unsigned int hpet_readl(unsigned int a);
 extern void force_hpet_resume(void);
 
 struct irq_data;
+struct hpet_dev;
+struct irq_domain;
+
 extern void hpet_msi_unmask(struct irq_data *data);
 extern void hpet_msi_mask(struct irq_data *data);
-struct hpet_dev;
 extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
 extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
+extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
+extern int hpet_assign_irq(struct irq_domain *domain,
+			   struct hpet_dev *dev, int dev_num);
 
 #ifdef CONFIG_PCI_MSI
 extern int default_setup_hpet_msi(unsigned int irq, unsigned int id);
arch/x86/kernel/apic/msi.c +147 -19

201 lines not on this page · raw message

arch/x86/kernel/hpet.c +14 -43

114 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#22 lore raw

[tip:x86/apic] x86/hpet: Enhance HPET IRQ to support hierarchical irqdomains

x86/hpet: Enhance HPET IRQ to support hierarchical irqdomains
Commit-ID:  3cb96f0c97330834929abe9bd2ca3c252a83def0
Gitweb:     http://git.kernel.org/tip/3cb96f0c97330834929abe9bd2ca3c252a83def0
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:34 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

x86/hpet: Enhance HPET IRQ to support hierarchical irqdomains

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Srivatsa S. Bhat <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Andy Lutomirski <[email protected]>
---
 arch/x86/include/asm/hpet.h |   7 +-
 arch/x86/kernel/apic/msi.c  | 166 +++++++++++++++++++++++++++++++++++++++-----
 arch/x86/kernel/hpet.c      |  57 ++++-----------
 3 files changed, 167 insertions(+), 63 deletions(-)
arch/x86/include/asm/hpet.h +6 -1
index 36f7125..e87e9fa 100644
@@ -74,11 +74,16 @@ extern unsigned int hpet_readl(unsigned int a);
 extern void force_hpet_resume(void);
 
 struct irq_data;
+struct hpet_dev;
+struct irq_domain;
+
 extern void hpet_msi_unmask(struct irq_data *data);
 extern void hpet_msi_mask(struct irq_data *data);
-struct hpet_dev;
 extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
 extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
+extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
+extern int hpet_assign_irq(struct irq_domain *domain,
+			   struct hpet_dev *dev, int dev_num);
 
 #ifdef CONFIG_PCI_MSI
 extern int default_setup_hpet_msi(unsigned int irq, unsigned int id);
arch/x86/kernel/apic/msi.c +147 -19

201 lines not on this page · raw message

arch/x86/kernel/hpet.c +14 -43

114 lines not on this page · raw message

author
#23 lore raw

PATCH v8 13/37 x86/MSI: Use hierarchy irqdomain to manage MSI interrupts

In reply to Jiang Liu

Enhance MSI code to support hierarchy irqdomain, it helps to make the architecture more clear.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/x86/Kconfig                     |    1 +
 arch/x86/include/asm/hw_irq.h        |    9 ++-
 arch/x86/include/asm/irq_remapping.h |    6 +-
 arch/x86/include/asm/msi.h           |    7 ++
 arch/x86/kernel/apic/msi.c           |  141 ++++++++++++++++++----------------
 arch/x86/kernel/apic/vector.c        |    2 +
 drivers/iommu/irq_remapping.c        |    1 -
 7 files changed, 94 insertions(+), 73 deletions(-)
 create mode 100644 arch/x86/include/asm/msi.h
arch/x86/Kconfig +1 -0
index 2ca708961a3c..fecb8b7d74bd 100644
@@ -923,6 +923,7 @@ config X86_LOCAL_APIC
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
 	select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
 	select IRQ_DOMAIN_HIERARCHY
+	select PCI_MSI_IRQ_DOMAIN if PCI_MSI
 
 config X86_IO_APIC
 	def_bool X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
arch/x86/include/asm/hw_irq.h +8 -1
index bd7881c5a57a..270c432971f8 100644
@@ -110,9 +110,10 @@ struct irq_2_irte {
 };
 #endif	/* CONFIG_IRQ_REMAP */
 
+struct irq_domain;
+
 #ifdef	CONFIG_X86_LOCAL_APIC
 struct irq_data;
-struct irq_domain;
 struct pci_dev;
 struct msi_desc;
 
@@ -214,6 +215,12 @@ static inline void lock_vector_lock(void) {}
 static inline void unlock_vector_lock(void) {}
 #endif	/* CONFIG_X86_LOCAL_APIC */
 
+#ifdef	CONFIG_PCI_MSI
+extern void arch_init_msi_domain(struct irq_domain *domain);
+#else
+static inline void arch_init_msi_domain(struct irq_domain *domain) { }
+#endif
+
 /* Statistics */
 extern atomic_t irq_err_count;
 extern atomic_t irq_mis_count;
arch/x86/include/asm/irq_remapping.h +1 -5
index 0cd6195cc375..0d3bbd0e2c42 100644
@@ -66,11 +66,7 @@ irq_remapping_get_irq_domain(struct irq_alloc_info *info);
 extern void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p);
 
 /* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */
-static inline struct irq_domain *
-arch_create_msi_irq_domain(struct irq_domain *parent)
-{
-	return NULL;
-}
+extern struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent);
 
 /* Get parent irqdomain for interrupt remapping irqdomain */
 static inline struct irq_domain *arch_get_ir_parent_domain(void)
arch/x86/include/asm/msi.h new file +7 -0
new file mode 100644
index 000000000000..93724cc62177
@@ -0,0 +1,7 @@
+#ifndef _ASM_X86_MSI_H
+#define _ASM_X86_MSI_H
+#include <asm/hw_irq.h>
+
+typedef struct irq_alloc_info msi_alloc_info_t;
+
+#endif /* _ASM_X86_MSI_H */
arch/x86/kernel/apic/msi.c +75 -66

189 lines not on this page · raw message

arch/x86/kernel/apic/vector.c +2 -0
index f8340c72546f..e971c87f7858 100644
@@ -364,6 +364,8 @@ int __init arch_early_irq_init(void)
 	BUG_ON(x86_vector_domain == NULL);
 	irq_set_default_host(x86_vector_domain);
 
+	arch_init_msi_domain(x86_vector_domain);
+
 	return arch_early_ioapic_init();
 }
 
drivers/iommu/irq_remapping.c +0 -1
index c306421d86c1..d77e3711c2aa 100644
@@ -170,7 +170,6 @@ static void __init irq_remapping_modify_x86_ops(void)
 	x86_io_apic_ops.set_affinity	= set_remapped_irq_affinity;
 	x86_io_apic_ops.setup_entry	= setup_ioapic_remapped_entry;
 	x86_io_apic_ops.eoi_ioapic_pin	= eoi_ioapic_pin_remapped;
-	x86_msi.setup_msi_irqs		= irq_remapping_setup_msi_irqs;
 	x86_msi.setup_hpet_msi		= setup_hpet_msi_remapped;
 	x86_msi.compose_msi_msg		= compose_remapped_msi_msg;
 }
Signature · 1 line
1.7.10.4
#24 lore raw

[tip:x86/apic] x86/MSI: Use hierarchical irqdomains to manage MSI interrupts

x86/MSI: Use hierarchical irqdomains to manage MSI interrupts
Commit-ID:  52f518a3a7c2f80551a38d38be28bc9f335e713c
Gitweb:     http://git.kernel.org/tip/52f518a3a7c2f80551a38d38be28bc9f335e713c
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:35 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

x86/MSI: Use hierarchical irqdomains to manage MSI interrupts

Enhance MSI code to support hierarchical irqdomains, it helps to make the architecture more clear.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/x86/Kconfig                     |   1 +
 arch/x86/include/asm/hw_irq.h        |   9 ++-
 arch/x86/include/asm/irq_remapping.h |   6 +-
 arch/x86/include/asm/msi.h           |   7 ++
 arch/x86/kernel/apic/msi.c           | 141 +++++++++++++++++++----------------
 arch/x86/kernel/apic/vector.c        |   2 +
 drivers/iommu/irq_remapping.c        |   1 -
 7 files changed, 94 insertions(+), 73 deletions(-)
arch/x86/Kconfig +1 -0
index e75a96c..26e0665 100644
@@ -914,6 +914,7 @@ config X86_LOCAL_APIC
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
 	select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
 	select IRQ_DOMAIN_HIERARCHY
+	select PCI_MSI_IRQ_DOMAIN if PCI_MSI
 
 config X86_IO_APIC
 	def_bool y
arch/x86/include/asm/hw_irq.h +8 -1
index 75a97a5..05829e9 100644
@@ -110,9 +110,10 @@ struct irq_2_irte {
 };
 #endif	/* CONFIG_IRQ_REMAP */
 
+struct irq_domain;
+
 #ifdef	CONFIG_X86_LOCAL_APIC
 struct irq_data;
-struct irq_domain;
 struct pci_dev;
 struct msi_desc;
 
@@ -214,6 +215,12 @@ static inline void lock_vector_lock(void) {}
 static inline void unlock_vector_lock(void) {}
 #endif	/* CONFIG_X86_LOCAL_APIC */
 
+#ifdef	CONFIG_PCI_MSI
+extern void arch_init_msi_domain(struct irq_domain *domain);
+#else
+static inline void arch_init_msi_domain(struct irq_domain *domain) { }
+#endif
+
 /* Statistics */
 extern atomic_t irq_err_count;
 extern atomic_t irq_mis_count;
arch/x86/include/asm/irq_remapping.h +1 -5
index 0cd6195..0d3bbd0 100644
@@ -66,11 +66,7 @@ irq_remapping_get_irq_domain(struct irq_alloc_info *info);
 extern void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p);
 
 /* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */
-static inline struct irq_domain *
-arch_create_msi_irq_domain(struct irq_domain *parent)
-{
-	return NULL;
-}
+extern struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent);
 
 /* Get parent irqdomain for interrupt remapping irqdomain */
 static inline struct irq_domain *arch_get_ir_parent_domain(void)
arch/x86/include/asm/msi.h new file +7 -0
new file mode 100644
index 0000000..93724cc
@@ -0,0 +1,7 @@
+#ifndef _ASM_X86_MSI_H
+#define _ASM_X86_MSI_H
+#include <asm/hw_irq.h>
+
+typedef struct irq_alloc_info msi_alloc_info_t;
+
+#endif /* _ASM_X86_MSI_H */
arch/x86/kernel/apic/msi.c +75 -66

189 lines not on this page · raw message

arch/x86/kernel/apic/vector.c +2 -0
index 6358d8d..a8d8289 100644
@@ -364,6 +364,8 @@ int __init arch_early_irq_init(void)
 	BUG_ON(x86_vector_domain == NULL);
 	irq_set_default_host(x86_vector_domain);
 
+	arch_init_msi_domain(x86_vector_domain);
+
 	return arch_early_ioapic_init();
 }
 
drivers/iommu/irq_remapping.c +0 -1
index c306421..d77e371 100644
@@ -170,7 +170,6 @@ static void __init irq_remapping_modify_x86_ops(void)
 	x86_io_apic_ops.set_affinity	= set_remapped_irq_affinity;
 	x86_io_apic_ops.setup_entry	= setup_ioapic_remapped_entry;
 	x86_io_apic_ops.eoi_ioapic_pin	= eoi_ioapic_pin_remapped;
-	x86_msi.setup_msi_irqs		= irq_remapping_setup_msi_irqs;
 	x86_msi.setup_hpet_msi		= setup_hpet_msi_remapped;
 	x86_msi.compose_msi_msg		= compose_remapped_msi_msg;
 }
author
#25 lore raw

PATCH v8 14/37 x86/irq: Directly call native_compose_msi_msg() for DMAR IRQ

In reply to Jiang Liu

DMAR interrupt won't be remapped by interrupt remapping hardware, so directly call native_compose_msi_msg() for DMAR IRQ to compose MSI message data. This will help to simplify MSI code later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/msi.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
arch/x86/kernel/apic/msi.c +2 -4
index e82ab7973477..fa2dd6ebcaea 100644
@@ -259,12 +259,10 @@ static struct irq_chip dmar_msi_type = {
 
 int arch_setup_dmar_msi(unsigned int irq)
 {
-	int ret;
 	struct msi_msg msg;
+	struct irq_cfg *cfg = irq_cfg(irq);
 
-	ret = msi_compose_msg(NULL, irq, &msg, -1);
-	if (ret < 0)
-		return ret;
+	native_compose_msi_msg(NULL, irq, cfg->dest_apicid, &msg, -1);
 	dmar_msi_write(irq, &msg);
 	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
 				      "edge");
Signature · 1 line
1.7.10.4
#26 lore raw

[tip:x86/apic] x86/irq: Directly call native_compose_msi_msg() for DMAR IRQ

x86/irq: Directly call native_compose_msi_msg() for DMAR IRQ
Commit-ID:  80aa283364a17998dceb577bd185e3380b927544
Gitweb:     http://git.kernel.org/tip/80aa283364a17998dceb577bd185e3380b927544
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:36 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

x86/irq: Directly call native_compose_msi_msg() for DMAR IRQ

DMAR interrupt won't be remapped by interrupt remapping hardware, so directly call native_compose_msi_msg() for DMAR IRQ to compose MSI message data. This will help to simplify MSI code later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/kernel/apic/msi.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
arch/x86/kernel/apic/msi.c +2 -4
index c426cd5..9adb871 100644
@@ -259,12 +259,10 @@ static struct irq_chip dmar_msi_type = {
 
 int arch_setup_dmar_msi(unsigned int irq)
 {
-	int ret;
 	struct msi_msg msg;
+	struct irq_cfg *cfg = irq_cfg(irq);
 
-	ret = msi_compose_msg(NULL, irq, &msg, -1);
-	if (ret < 0)
-		return ret;
+	native_compose_msi_msg(NULL, irq, cfg->dest_apicid, &msg, -1);
 	dmar_msi_write(irq, &msg);
 	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
 				      "edge");
author
#27 lore raw

PATCH v8 15/37 irq_remapping/vt-d: Clean up unused MSI related code

In reply to Jiang Liu

Now MSI interrupt has been converted to new hierarchy irqdomain interfaces, so kill legacy MSI related code.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/intel_irq_remapping.c |  144 -----------------------------------
 1 file changed, 144 deletions(-)
drivers/iommu/intel_irq_remapping.c +0 -144
index f2dbb0d54d17..91c0fc65713d 100644
@@ -145,44 +145,6 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
 	return qi_submit_sync(&desc, iommu);
 }
 
-static int map_irq_to_irte_handle(int irq, u16 *sub_handle)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	unsigned long flags;
-	int index;
-
-	if (!irq_iommu)
-		return -1;
-
-	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
-	*sub_handle = irq_iommu->sub_handle;
-	index = irq_iommu->irte_index;
-	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-	return index;
-}
-
-static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	struct irq_cfg *cfg = irq_cfg(irq);
-	unsigned long flags;
-
-	if (!irq_iommu)
-		return -1;
-
-	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-	cfg->remapped = 1;
-	irq_iommu->iommu = iommu;
-	irq_iommu->irte_index = index;
-	irq_iommu->sub_handle = subhandle;
-	irq_iommu->irte_mask = 0;
-
-	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return 0;
-}
-
 static int modify_irte(struct irq_2_iommu *irq_iommu,
 		       struct irte *irte_modified)
 {
@@ -1127,108 +1089,6 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	return 0;
 }
 
-static void intel_compose_msi_msg(struct pci_dev *pdev,
-				  unsigned int irq, unsigned int dest,
-				  struct msi_msg *msg, u8 hpet_id)
-{
-	struct irq_cfg *cfg;
-	struct irte irte;
-	u16 sub_handle = 0;
-	int ir_index;
-
-	cfg = irq_cfg(irq);
-
-	ir_index = map_irq_to_irte_handle(irq, &sub_handle);
-	BUG_ON(ir_index == -1);
-
-	prepare_irte(&irte, cfg->vector, dest);
-
-	/* Set source-id of interrupt request */
-	if (pdev)
-		set_msi_sid(&irte, pdev);
-	else
-		set_hpet_sid(&irte, hpet_id);
-
-	modify_irte(irq_2_iommu(irq), &irte);
-
-	msg->address_hi = MSI_ADDR_BASE_HI;
-	msg->data = sub_handle;
-	msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
-			  MSI_ADDR_IR_SHV |
-			  MSI_ADDR_IR_INDEX1(ir_index) |
-			  MSI_ADDR_IR_INDEX2(ir_index);
-}
-
-/*
- * Map the PCI dev to the corresponding remapping hardware unit
- * and allocate 'nvec' consecutive interrupt-remapping table entries
- * in it.
- */
-static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec)
-{
-	struct intel_iommu *iommu;
-	int index;
-
-	down_read(&dmar_global_lock);
-	iommu = map_dev_to_ir(dev);
-	if (!iommu) {
-		printk(KERN_ERR
-		       "Unable to map PCI %s to iommu\n", pci_name(dev));
-		index = -ENOENT;
-	} else {
-		index = alloc_irte(iommu, irq, irq_2_iommu(irq), nvec);
-		if (index < 0) {
-			printk(KERN_ERR
-			       "Unable to allocate %d IRTE for PCI %s\n",
-			       nvec, pci_name(dev));
-			index = -ENOSPC;
-		}
-	}
-	up_read(&dmar_global_lock);
-
-	return index;
-}
-
-static int intel_msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
-			       int index, int sub_handle)
-{
-	struct intel_iommu *iommu;
-	int ret = -ENOENT;
-
-	down_read(&dmar_global_lock);
-	iommu = map_dev_to_ir(pdev);
-	if (iommu) {
-		/*
-		 * setup the mapping between the irq and the IRTE
-		 * base index, the sub_handle pointing to the
-		 * appropriate interrupt remap table entry.
-		 */
-		set_irte_irq(irq, iommu, index, sub_handle);
-		ret = 0;
-	}
-	up_read(&dmar_global_lock);
-
-	return ret;
-}
-
-static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id)
-{
-	int ret = -1;
-	struct intel_iommu *iommu;
-	int index;
-
-	down_read(&dmar_global_lock);
-	iommu = map_hpet_to_ir(id);
-	if (iommu) {
-		index = alloc_irte(iommu, irq, irq_2_iommu(irq), 1);
-		if (index >= 0)
-			ret = 0;
-	}
-	up_read(&dmar_global_lock);
-
-	return ret;
-}
-
 static struct irq_domain *intel_get_ir_irq_domain(struct irq_alloc_info *info)
 {
 	struct intel_iommu *iommu = NULL;
@@ -1285,10 +1145,6 @@ struct irq_remap_ops intel_irq_remap_ops = {
 	.setup_ioapic_entry	= intel_setup_ioapic_entry,
 	.set_affinity		= intel_ioapic_set_affinity,
 	.free_irq		= free_irte,
-	.compose_msi_msg	= intel_compose_msi_msg,
-	.msi_alloc_irq		= intel_msi_alloc_irq,
-	.msi_setup_irq		= intel_msi_setup_irq,
-	.alloc_hpet_msi		= intel_alloc_hpet_msi,
 	.get_ir_irq_domain	= intel_get_ir_irq_domain,
 	.get_irq_domain		= intel_get_irq_domain,
 };
Signature · 1 line
1.7.10.4
#28 lore raw

[tip:x86/apic] irq_remapping/vt-d: Clean up unused MSI related code

irq_remapping/vt-d: Clean up unused MSI related code
Commit-ID:  2b43817e481da9f5118adb56aef46b3f0298c685
Gitweb:     http://git.kernel.org/tip/2b43817e481da9f5118adb56aef46b3f0298c685
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:37 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

irq_remapping/vt-d: Clean up unused MSI related code

Now MSI interrupt has been converted to new hierarchical irqdomain interfaces, so remove legacy MSI related code.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/intel_irq_remapping.c | 144 ------------------------------------
 1 file changed, 144 deletions(-)
drivers/iommu/intel_irq_remapping.c +0 -144
index 97ea420..71a25ae 100644
@@ -145,44 +145,6 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
 	return qi_submit_sync(&desc, iommu);
 }
 
-static int map_irq_to_irte_handle(int irq, u16 *sub_handle)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	unsigned long flags;
-	int index;
-
-	if (!irq_iommu)
-		return -1;
-
-	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
-	*sub_handle = irq_iommu->sub_handle;
-	index = irq_iommu->irte_index;
-	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-	return index;
-}
-
-static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	struct irq_cfg *cfg = irq_cfg(irq);
-	unsigned long flags;
-
-	if (!irq_iommu)
-		return -1;
-
-	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-	cfg->remapped = 1;
-	irq_iommu->iommu = iommu;
-	irq_iommu->irte_index = index;
-	irq_iommu->sub_handle = subhandle;
-	irq_iommu->irte_mask = 0;
-
-	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return 0;
-}
-
 static int modify_irte(struct irq_2_iommu *irq_iommu,
 		       struct irte *irte_modified)
 {
@@ -1127,108 +1089,6 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	return 0;
 }
 
-static void intel_compose_msi_msg(struct pci_dev *pdev,
-				  unsigned int irq, unsigned int dest,
-				  struct msi_msg *msg, u8 hpet_id)
-{
-	struct irq_cfg *cfg;
-	struct irte irte;
-	u16 sub_handle = 0;
-	int ir_index;
-
-	cfg = irq_cfg(irq);
-
-	ir_index = map_irq_to_irte_handle(irq, &sub_handle);
-	BUG_ON(ir_index == -1);
-
-	prepare_irte(&irte, cfg->vector, dest);
-
-	/* Set source-id of interrupt request */
-	if (pdev)
-		set_msi_sid(&irte, pdev);
-	else
-		set_hpet_sid(&irte, hpet_id);
-
-	modify_irte(irq_2_iommu(irq), &irte);
-
-	msg->address_hi = MSI_ADDR_BASE_HI;
-	msg->data = sub_handle;
-	msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
-			  MSI_ADDR_IR_SHV |
-			  MSI_ADDR_IR_INDEX1(ir_index) |
-			  MSI_ADDR_IR_INDEX2(ir_index);
-}
-
-/*
- * Map the PCI dev to the corresponding remapping hardware unit
- * and allocate 'nvec' consecutive interrupt-remapping table entries
- * in it.
- */
-static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec)
-{
-	struct intel_iommu *iommu;
-	int index;
-
-	down_read(&dmar_global_lock);
-	iommu = map_dev_to_ir(dev);
-	if (!iommu) {
-		printk(KERN_ERR
-		       "Unable to map PCI %s to iommu\n", pci_name(dev));
-		index = -ENOENT;
-	} else {
-		index = alloc_irte(iommu, irq, irq_2_iommu(irq), nvec);
-		if (index < 0) {
-			printk(KERN_ERR
-			       "Unable to allocate %d IRTE for PCI %s\n",
-			       nvec, pci_name(dev));
-			index = -ENOSPC;
-		}
-	}
-	up_read(&dmar_global_lock);
-
-	return index;
-}
-
-static int intel_msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
-			       int index, int sub_handle)
-{
-	struct intel_iommu *iommu;
-	int ret = -ENOENT;
-
-	down_read(&dmar_global_lock);
-	iommu = map_dev_to_ir(pdev);
-	if (iommu) {
-		/*
-		 * setup the mapping between the irq and the IRTE
-		 * base index, the sub_handle pointing to the
-		 * appropriate interrupt remap table entry.
-		 */
-		set_irte_irq(irq, iommu, index, sub_handle);
-		ret = 0;
-	}
-	up_read(&dmar_global_lock);
-
-	return ret;
-}
-
-static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id)
-{
-	int ret = -1;
-	struct intel_iommu *iommu;
-	int index;
-
-	down_read(&dmar_global_lock);
-	iommu = map_hpet_to_ir(id);
-	if (iommu) {
-		index = alloc_irte(iommu, irq, irq_2_iommu(irq), 1);
-		if (index >= 0)
-			ret = 0;
-	}
-	up_read(&dmar_global_lock);
-
-	return ret;
-}
-
 static struct irq_domain *intel_get_ir_irq_domain(struct irq_alloc_info *info)
 {
 	struct intel_iommu *iommu = NULL;
@@ -1285,10 +1145,6 @@ struct irq_remap_ops intel_irq_remap_ops = {
 	.setup_ioapic_entry	= intel_setup_ioapic_entry,
 	.set_affinity		= intel_ioapic_set_affinity,
 	.free_irq		= free_irte,
-	.compose_msi_msg	= intel_compose_msi_msg,
-	.msi_alloc_irq		= intel_msi_alloc_irq,
-	.msi_setup_irq		= intel_msi_setup_irq,
-	.alloc_hpet_msi		= intel_alloc_hpet_msi,
 	.get_ir_irq_domain	= intel_get_ir_irq_domain,
 	.get_irq_domain		= intel_get_irq_domain,
 };
author
#29 lore raw

PATCH v8 16/37 irq_remapping/amd: Clean up unused MSI related code

In reply to Jiang Liu

Now MSI interrupt has been converted to new hierarchy irqdomain interfaces, so kill legacy MSI related code.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/amd_iommu.c |  115 +--------------------------------------------
 1 file changed, 2 insertions(+), 113 deletions(-)
drivers/iommu/amd_iommu.c +2 -113
index db974bd348a1..62fce11e1cfd 100644
@@ -3961,8 +3961,7 @@ out_unlock:
 	return table;
 }
 
-static int alloc_irq_index(struct irq_cfg *cfg, struct irq_2_irte *irte_info,
-			   u16 devid, int count)
+static int alloc_irq_index(u16 devid, int count)
 {
 	struct irq_remap_table *table;
 	unsigned long flags;
@@ -3988,11 +3987,6 @@ static int alloc_irq_index(struct irq_cfg *cfg, struct irq_2_irte *irte_info,
 				table->table[index - c + 1] = IRTE_ALLOCATED;
 
 			index -= count - 1;
-
-			cfg->remapped	      = 1;
-			irte_info->devid      = devid;
-			irte_info->index      = index;
-
 			goto out;
 		}
 	}
@@ -4192,106 +4186,6 @@ static int free_irq(int irq)
 	return 0;
 }
 
-static void compose_msi_msg(struct pci_dev *pdev,
-			    unsigned int irq, unsigned int dest,
-			    struct msi_msg *msg, u8 hpet_id)
-{
-	struct irq_2_irte *irte_info;
-	struct irq_cfg *cfg;
-	union irte irte;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return;
-
-	irte_info = &cfg->irq_2_irte;
-
-	irte.val		= 0;
-	irte.fields.vector	= cfg->vector;
-	irte.fields.int_type    = apic->irq_delivery_mode;
-	irte.fields.destination	= dest;
-	irte.fields.dm		= apic->irq_dest_mode;
-	irte.fields.valid	= 1;
-
-	modify_irte(irte_info->devid, irte_info->index, irte);
-
-	msg->address_hi = MSI_ADDR_BASE_HI;
-	msg->address_lo = MSI_ADDR_BASE_LO;
-	msg->data       = irte_info->index;
-}
-
-static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
-{
-	struct irq_cfg *cfg;
-	int index;
-	u16 devid;
-
-	if (!pdev)
-		return -EINVAL;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return -EINVAL;
-
-	devid = get_device_id(&pdev->dev);
-	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, nvec);
-
-	return index < 0 ? MAX_IRQS_PER_TABLE : index;
-}
-
-static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
-			 int index, int offset)
-{
-	struct irq_2_irte *irte_info;
-	struct irq_cfg *cfg;
-	u16 devid;
-
-	if (!pdev)
-		return -EINVAL;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return -EINVAL;
-
-	if (index >= MAX_IRQS_PER_TABLE)
-		return 0;
-
-	devid		= get_device_id(&pdev->dev);
-	irte_info	= &cfg->irq_2_irte;
-
-	cfg->remapped	      = 1;
-	irte_info->devid      = devid;
-	irte_info->index      = index + offset;
-
-	return 0;
-}
-
-static int alloc_hpet_msi(unsigned int irq, unsigned int id)
-{
-	struct irq_2_irte *irte_info;
-	struct irq_cfg *cfg;
-	int index, devid;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return -EINVAL;
-
-	irte_info = &cfg->irq_2_irte;
-	devid     = get_hpet_devid(id);
-	if (devid < 0)
-		return devid;
-
-	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, 1);
-	if (index < 0)
-		return index;
-
-	cfg->remapped	      = 1;
-	irte_info->devid      = devid;
-	irte_info->index      = index;
-
-	return 0;
-}
-
 static int get_devid(struct irq_alloc_info *info)
 {
 	int devid = -1;
@@ -4367,10 +4261,6 @@ struct irq_remap_ops amd_iommu_irq_ops = {
 	.setup_ioapic_entry	= setup_ioapic_entry,
 	.set_affinity		= set_affinity,
 	.free_irq		= free_irq,
-	.compose_msi_msg	= compose_msi_msg,
-	.msi_alloc_irq		= msi_alloc_irq,
-	.msi_setup_irq		= msi_setup_irq,
-	.alloc_hpet_msi		= alloc_hpet_msi,
 	.get_ir_irq_domain	= get_ir_irq_domain,
 	.get_irq_domain		= get_irq_domain,
 };
@@ -4468,8 +4358,7 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
 		else
 			ret = -ENOMEM;
 	} else {
-		cfg = irq_cfg(virq);
-		index = alloc_irq_index(cfg, &data->irq_2_irte, devid, nr_irqs);
+		index = alloc_irq_index(devid, nr_irqs);
 	}
 	if (index < 0) {
 		pr_warn("Failed to allocate IRTE\n");
Signature · 1 line
1.7.10.4
#30 lore raw

[tip:x86/apic] irq_remapping/amd: Clean up unused MSI related code

irq_remapping/amd: Clean up unused MSI related code
Commit-ID:  3c3d4f90f6f80cce357ef013baf1327a9b9d5732
Gitweb:     http://git.kernel.org/tip/3c3d4f90f6f80cce357ef013baf1327a9b9d5732
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:38 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

irq_remapping/amd: Clean up unused MSI related code

Now MSI interrupt has been converted to new hierarchical irqdomain interfaces, so remove legacy MSI related code.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/amd_iommu.c | 115 +---------------------------------------------
 1 file changed, 2 insertions(+), 113 deletions(-)
drivers/iommu/amd_iommu.c +2 -113
index a14ba26..8858cb6 100644
@@ -3955,8 +3955,7 @@ out_unlock:
 	return table;
 }
 
-static int alloc_irq_index(struct irq_cfg *cfg, struct irq_2_irte *irte_info,
-			   u16 devid, int count)
+static int alloc_irq_index(u16 devid, int count)
 {
 	struct irq_remap_table *table;
 	unsigned long flags;
@@ -3982,11 +3981,6 @@ static int alloc_irq_index(struct irq_cfg *cfg, struct irq_2_irte *irte_info,
 				table->table[index - c + 1] = IRTE_ALLOCATED;
 
 			index -= count - 1;
-
-			cfg->remapped	      = 1;
-			irte_info->devid      = devid;
-			irte_info->index      = index;
-
 			goto out;
 		}
 	}
@@ -4186,106 +4180,6 @@ static int free_irq(int irq)
 	return 0;
 }
 
-static void compose_msi_msg(struct pci_dev *pdev,
-			    unsigned int irq, unsigned int dest,
-			    struct msi_msg *msg, u8 hpet_id)
-{
-	struct irq_2_irte *irte_info;
-	struct irq_cfg *cfg;
-	union irte irte;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return;
-
-	irte_info = &cfg->irq_2_irte;
-
-	irte.val		= 0;
-	irte.fields.vector	= cfg->vector;
-	irte.fields.int_type    = apic->irq_delivery_mode;
-	irte.fields.destination	= dest;
-	irte.fields.dm		= apic->irq_dest_mode;
-	irte.fields.valid	= 1;
-
-	modify_irte(irte_info->devid, irte_info->index, irte);
-
-	msg->address_hi = MSI_ADDR_BASE_HI;
-	msg->address_lo = MSI_ADDR_BASE_LO;
-	msg->data       = irte_info->index;
-}
-
-static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
-{
-	struct irq_cfg *cfg;
-	int index;
-	u16 devid;
-
-	if (!pdev)
-		return -EINVAL;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return -EINVAL;
-
-	devid = get_device_id(&pdev->dev);
-	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, nvec);
-
-	return index < 0 ? MAX_IRQS_PER_TABLE : index;
-}
-
-static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
-			 int index, int offset)
-{
-	struct irq_2_irte *irte_info;
-	struct irq_cfg *cfg;
-	u16 devid;
-
-	if (!pdev)
-		return -EINVAL;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return -EINVAL;
-
-	if (index >= MAX_IRQS_PER_TABLE)
-		return 0;
-
-	devid		= get_device_id(&pdev->dev);
-	irte_info	= &cfg->irq_2_irte;
-
-	cfg->remapped	      = 1;
-	irte_info->devid      = devid;
-	irte_info->index      = index + offset;
-
-	return 0;
-}
-
-static int alloc_hpet_msi(unsigned int irq, unsigned int id)
-{
-	struct irq_2_irte *irte_info;
-	struct irq_cfg *cfg;
-	int index, devid;
-
-	cfg = irq_cfg(irq);
-	if (!cfg)
-		return -EINVAL;
-
-	irte_info = &cfg->irq_2_irte;
-	devid     = get_hpet_devid(id);
-	if (devid < 0)
-		return devid;
-
-	index = alloc_irq_index(cfg, &cfg->irq_2_irte, devid, 1);
-	if (index < 0)
-		return index;
-
-	cfg->remapped	      = 1;
-	irte_info->devid      = devid;
-	irte_info->index      = index;
-
-	return 0;
-}
-
 static int get_devid(struct irq_alloc_info *info)
 {
 	int devid = -1;
@@ -4361,10 +4255,6 @@ struct irq_remap_ops amd_iommu_irq_ops = {
 	.setup_ioapic_entry	= setup_ioapic_entry,
 	.set_affinity		= set_affinity,
 	.free_irq		= free_irq,
-	.compose_msi_msg	= compose_msi_msg,
-	.msi_alloc_irq		= msi_alloc_irq,
-	.msi_setup_irq		= msi_setup_irq,
-	.alloc_hpet_msi		= alloc_hpet_msi,
 	.get_ir_irq_domain	= get_ir_irq_domain,
 	.get_irq_domain		= get_irq_domain,
 };
@@ -4462,8 +4352,7 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
 		else
 			ret = -ENOMEM;
 	} else {
-		cfg = irq_cfg(virq);
-		index = alloc_irq_index(cfg, &data->irq_2_irte, devid, nr_irqs);
+		index = alloc_irq_index(devid, nr_irqs);
 	}
 	if (index < 0) {
 		pr_warn("Failed to allocate IRTE\n");
author
#31 lore raw

PATCH v8 17/37 irq_remapping: Clean up unused MSI related code

In reply to Jiang Liu

Now MSI interrupt has been converted to new hierarchy irqdomain interfaces, so kill legacy MSI related code and interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Yijing Wang <[email protected]>
---
 arch/x86/include/asm/irq_remapping.h |   13 ---
 arch/x86/include/asm/pci.h           |    5 --
 arch/x86/kernel/x86_init.c           |    2 -
 drivers/iommu/irq_remapping.c        |  151 ----------------------------------
 drivers/iommu/irq_remapping.h        |   14 ----
 5 files changed, 185 deletions(-)
arch/x86/include/asm/irq_remapping.h +0 -13
index 0d3bbd0e2c42..b978c68f5d29 100644
@@ -48,10 +48,6 @@ extern int setup_ioapic_remapped_entry(int irq,
 				       int vector,
 				       struct io_apic_irq_attr *attr);
 extern void free_remapped_irq(int irq);
-extern void compose_remapped_msi_msg(struct pci_dev *pdev,
-				     unsigned int irq, unsigned int dest,
-				     struct msi_msg *msg, u8 hpet_id);
-extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id);
 extern void panic_if_irq_remap(const char *msg);
 extern bool setup_remapped_irq(int irq,
 			       struct irq_cfg *cfg,
@@ -91,15 +87,6 @@ static inline int setup_ioapic_remapped_entry(int irq,
 	return -ENODEV;
 }
 static inline void free_remapped_irq(int irq) { }
-static inline void compose_remapped_msi_msg(struct pci_dev *pdev,
-					    unsigned int irq, unsigned int dest,
-					    struct msi_msg *msg, u8 hpet_id)
-{
-}
-static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
-{
-	return -ENODEV;
-}
 
 static inline void panic_if_irq_remap(const char *msg)
 {
arch/x86/include/asm/pci.h +0 -5
index 4e370a5d8117..d8c80ff32e8c 100644
@@ -96,15 +96,10 @@ extern void pci_iommu_alloc(void);
 #ifdef CONFIG_PCI_MSI
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
-void native_compose_msi_msg(struct pci_dev *pdev, unsigned int irq,
-			    unsigned int dest, struct msi_msg *msg, u8 hpet_id);
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev);
-int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-		  unsigned int irq_base, unsigned int irq_offset);
 #else
-#define native_compose_msi_msg		NULL
 #define native_setup_msi_irqs		NULL
 #define native_teardown_msi_irq		NULL
 #endif
arch/x86/kernel/x86_init.c +0 -2
index 234b0722de53..b094d691f2fe 100644
@@ -111,11 +111,9 @@ EXPORT_SYMBOL_GPL(x86_platform);
 #if defined(CONFIG_PCI_MSI)
 struct x86_msi_ops x86_msi = {
 	.setup_msi_irqs		= native_setup_msi_irqs,
-	.compose_msi_msg	= native_compose_msi_msg,
 	.teardown_msi_irq	= native_teardown_msi_irq,
 	.teardown_msi_irqs	= default_teardown_msi_irqs,
 	.restore_msi_irqs	= default_restore_msi_irqs,
-	.setup_hpet_msi		= default_setup_hpet_msi,
 };
 
 /* MSI arch specific hooks */
drivers/iommu/irq_remapping.c +0 -151

175 lines not on this page · raw message

drivers/iommu/irq_remapping.h +0 -14
index 3e109b1ea688..16b7d814e6fe 100644
@@ -66,20 +66,6 @@ struct irq_remap_ops {
 	/* Free an IRQ */
 	int (*free_irq)(int);
 
-	/* Create MSI msg to use for interrupt remapping */
-	void (*compose_msi_msg)(struct pci_dev *,
-				unsigned int, unsigned int,
-				struct msi_msg *, u8);
-
-	/* Allocate remapping resources for MSI */
-	int (*msi_alloc_irq)(struct pci_dev *, int, int);
-
-	/* Setup the remapped MSI irq */
-	int (*msi_setup_irq)(struct pci_dev *, unsigned int, int, int);
-
-	/* Setup interrupt remapping for an HPET MSI */
-	int (*alloc_hpet_msi)(unsigned int, unsigned int);
-
 	/* Get the irqdomain associated the IOMMU device */
 	struct irq_domain *(*get_ir_irq_domain)(struct irq_alloc_info *);
 
Signature · 1 line
1.7.10.4
#32 lore raw

[tip:x86/apic] irq_remapping: Clean up unused MSI related code

irq_remapping: Clean up unused MSI related code
Commit-ID:  7a53a12162cbe5feb66380b96cc794a031a8f39a
Gitweb:     http://git.kernel.org/tip/7a53a12162cbe5feb66380b96cc794a031a8f39a
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:39 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

irq_remapping: Clean up unused MSI related code

Now MSI interrupt has been converted to new hierarchical irqdomain interfaces, so remove legacy MSI related code and interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Yijing Wang <[email protected]>
---
 arch/x86/include/asm/irq_remapping.h |  13 ---
 arch/x86/include/asm/pci.h           |   5 --
 arch/x86/kernel/x86_init.c           |   2 -
 drivers/iommu/irq_remapping.c        | 151 -----------------------------------
 drivers/iommu/irq_remapping.h        |  14 ----
 5 files changed, 185 deletions(-)
arch/x86/include/asm/irq_remapping.h +0 -13
index 0d3bbd0..b978c68 100644
@@ -48,10 +48,6 @@ extern int setup_ioapic_remapped_entry(int irq,
 				       int vector,
 				       struct io_apic_irq_attr *attr);
 extern void free_remapped_irq(int irq);
-extern void compose_remapped_msi_msg(struct pci_dev *pdev,
-				     unsigned int irq, unsigned int dest,
-				     struct msi_msg *msg, u8 hpet_id);
-extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id);
 extern void panic_if_irq_remap(const char *msg);
 extern bool setup_remapped_irq(int irq,
 			       struct irq_cfg *cfg,
@@ -91,15 +87,6 @@ static inline int setup_ioapic_remapped_entry(int irq,
 	return -ENODEV;
 }
 static inline void free_remapped_irq(int irq) { }
-static inline void compose_remapped_msi_msg(struct pci_dev *pdev,
-					    unsigned int irq, unsigned int dest,
-					    struct msi_msg *msg, u8 hpet_id)
-{
-}
-static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
-{
-	return -ENODEV;
-}
 
 static inline void panic_if_irq_remap(const char *msg)
 {
arch/x86/include/asm/pci.h +0 -5
index 4e370a5..d8c80ff 100644
@@ -96,15 +96,10 @@ extern void pci_iommu_alloc(void);
 #ifdef CONFIG_PCI_MSI
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
-void native_compose_msi_msg(struct pci_dev *pdev, unsigned int irq,
-			    unsigned int dest, struct msi_msg *msg, u8 hpet_id);
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev);
-int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-		  unsigned int irq_base, unsigned int irq_offset);
 #else
-#define native_compose_msi_msg		NULL
 #define native_setup_msi_irqs		NULL
 #define native_teardown_msi_irq		NULL
 #endif
arch/x86/kernel/x86_init.c +0 -2
index 234b072..b094d69 100644
@@ -111,11 +111,9 @@ EXPORT_SYMBOL_GPL(x86_platform);
 #if defined(CONFIG_PCI_MSI)
 struct x86_msi_ops x86_msi = {
 	.setup_msi_irqs		= native_setup_msi_irqs,
-	.compose_msi_msg	= native_compose_msi_msg,
 	.teardown_msi_irq	= native_teardown_msi_irq,
 	.teardown_msi_irqs	= default_teardown_msi_irqs,
 	.restore_msi_irqs	= default_restore_msi_irqs,
-	.setup_hpet_msi		= default_setup_hpet_msi,
 };
 
 /* MSI arch specific hooks */
drivers/iommu/irq_remapping.c +0 -151

175 lines not on this page · raw message

drivers/iommu/irq_remapping.h +0 -14
index 3e109b1..16b7d81 100644
@@ -66,20 +66,6 @@ struct irq_remap_ops {
 	/* Free an IRQ */
 	int (*free_irq)(int);
 
-	/* Create MSI msg to use for interrupt remapping */
-	void (*compose_msi_msg)(struct pci_dev *,
-				unsigned int, unsigned int,
-				struct msi_msg *, u8);
-
-	/* Allocate remapping resources for MSI */
-	int (*msi_alloc_irq)(struct pci_dev *, int, int);
-
-	/* Setup the remapped MSI irq */
-	int (*msi_setup_irq)(struct pci_dev *, unsigned int, int, int);
-
-	/* Setup interrupt remapping for an HPET MSI */
-	int (*alloc_hpet_msi)(unsigned int, unsigned int);
-
 	/* Get the irqdomain associated the IOMMU device */
 	struct irq_domain *(*get_ir_irq_domain)(struct irq_alloc_info *);
 
author
#33 lore raw

PATCH v8 18/37 x86/MSI: Clean up unused MSI related code and interfaces

In reply to Jiang Liu

Now MSI interrupt has been converted to new hierarchy irqdomain interfaces, so kill legacy MSI related code and interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Yijing Wang <[email protected]>
---
 arch/x86/include/asm/hpet.h     |    9 -------
 arch/x86/include/asm/x86_init.h |    4 ---
 arch/x86/kernel/apic/msi.c      |   55 +++------------------------------------
 3 files changed, 4 insertions(+), 64 deletions(-)
arch/x86/include/asm/hpet.h +0 -9
index e87e9faf87a9..5fa9fb0f8809 100644
@@ -85,15 +85,6 @@ extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
 extern int hpet_assign_irq(struct irq_domain *domain,
 			   struct hpet_dev *dev, int dev_num);
 
-#ifdef CONFIG_PCI_MSI
-extern int default_setup_hpet_msi(unsigned int irq, unsigned int id);
-#else
-static inline int default_setup_hpet_msi(unsigned int irq, unsigned int id)
-{
-	return -EINVAL;
-}
-#endif
-
 #ifdef CONFIG_HPET_EMULATE_RTC
 
 #include <linux/interrupt.h>
arch/x86/include/asm/x86_init.h +0 -4
index f58a9c7a3c86..1649bb9ca27c 100644
@@ -175,13 +175,9 @@ struct msi_msg;
 
 struct x86_msi_ops {
 	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
-	void (*compose_msi_msg)(struct pci_dev *dev, unsigned int irq,
-				unsigned int dest, struct msi_msg *msg,
-			       u8 hpet_id);
 	void (*teardown_msi_irq)(unsigned int irq);
 	void (*teardown_msi_irqs)(struct pci_dev *dev);
 	void (*restore_msi_irqs)(struct pci_dev *dev);
-	int  (*setup_hpet_msi)(unsigned int irq, unsigned int id);
 };
 
 struct IO_APIC_route_entry;
arch/x86/kernel/apic/msi.c +4 -51

89 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#34 lore raw

[tip:x86/apic] x86/MSI: Clean up unused MSI related code and interfaces

x86/MSI: Clean up unused MSI related code and interfaces
Commit-ID:  b1855c752e67d1125d41fadb499014b49a245db8
Gitweb:     http://git.kernel.org/tip/b1855c752e67d1125d41fadb499014b49a245db8
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:40 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

x86/MSI: Clean up unused MSI related code and interfaces

Now MSI interrupt has been converted to new hierarchical irqdomain interfaces, so remove legacy MSI related code and interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Yijing Wang <[email protected]>
---
 arch/x86/include/asm/hpet.h     |  9 -------
 arch/x86/include/asm/x86_init.h |  4 ---
 arch/x86/kernel/apic/msi.c      | 55 +++--------------------------------------
 3 files changed, 4 insertions(+), 64 deletions(-)
arch/x86/include/asm/hpet.h +0 -9
index e87e9fa..5fa9fb0 100644
@@ -85,15 +85,6 @@ extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
 extern int hpet_assign_irq(struct irq_domain *domain,
 			   struct hpet_dev *dev, int dev_num);
 
-#ifdef CONFIG_PCI_MSI
-extern int default_setup_hpet_msi(unsigned int irq, unsigned int id);
-#else
-static inline int default_setup_hpet_msi(unsigned int irq, unsigned int id)
-{
-	return -EINVAL;
-}
-#endif
-
 #ifdef CONFIG_HPET_EMULATE_RTC
 
 #include <linux/interrupt.h>
arch/x86/include/asm/x86_init.h +0 -4
index f58a9c7..1649bb9 100644
@@ -175,13 +175,9 @@ struct msi_msg;
 
 struct x86_msi_ops {
 	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
-	void (*compose_msi_msg)(struct pci_dev *dev, unsigned int irq,
-				unsigned int dest, struct msi_msg *msg,
-			       u8 hpet_id);
 	void (*teardown_msi_irq)(unsigned int irq);
 	void (*teardown_msi_irqs)(struct pci_dev *dev);
 	void (*restore_msi_irqs)(struct pci_dev *dev);
-	int  (*setup_hpet_msi)(unsigned int irq, unsigned int id);
 };
 
 struct IO_APIC_route_entry;
arch/x86/kernel/apic/msi.c +4 -51

89 lines not on this page · raw message

author
#35 lore raw

PATCH v8 19/37 iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit

In reply to Jiang Liu

Refine the interfaces to create IRQ for DMAR unit. It's a preparation for converting DMAR IRQ to hierarchy irqdomain on x86.

It also moves dmar_alloc_hwirq()/dmar_free_hwirq() from irq_remapping.h to dmar.h. They are not irq_remapping specific.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Tony Luck <[email protected]>
Cc Fenghua Yu <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Vinod Koul <[email protected]>
---
 arch/ia64/include/asm/irq_remapping.h |    2 --
 arch/ia64/kernel/msi_ia64.c           |   30 +++++++++++++++++++-----------
 arch/x86/include/asm/irq_remapping.h  |    4 ----
 arch/x86/kernel/apic/msi.c            |   24 +++++++++++++-----------
 drivers/iommu/dmar.c                  |   19 +++++--------------
 include/linux/dmar.h                  |    3 ++-
 6 files changed, 39 insertions(+), 43 deletions(-)
arch/ia64/include/asm/irq_remapping.h +0 -2
index e3b3556e2e1b..a8687b1d8906 100644
@@ -1,6 +1,4 @@
 #ifndef __IA64_INTR_REMAPPING_H
 #define __IA64_INTR_REMAPPING_H
 #define irq_remapping_enabled 0
-#define dmar_alloc_hwirq	create_irq
-#define dmar_free_hwirq		destroy_irq
 #endif
arch/ia64/kernel/msi_ia64.c +19 -11
index 8ae36ea177d3..3f6b76135645 100644
@@ -166,7 +166,7 @@ static struct irq_chip dmar_msi_type = {
 	.irq_retrigger = ia64_msi_retrigger_irq,
 };
 
-static int
+static void
 msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 {
 	struct irq_cfg *cfg = irq_cfg + irq;
@@ -188,21 +188,29 @@ msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 		MSI_DATA_LEVEL_ASSERT |
 		MSI_DATA_DELIVERY_FIXED |
 		MSI_DATA_VECTOR(cfg->vector);
-	return 0;
 }
 
-int arch_setup_dmar_msi(unsigned int irq)
+int dmar_alloc_hwirq(int id, int node, void *arg)
 {
-	int ret;
+	int irq;
 	struct msi_msg msg;
 
-	ret = msi_compose_msg(NULL, irq, &msg);
-	if (ret < 0)
-		return ret;
-	dmar_msi_write(irq, &msg);
-	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-				      "edge");
-	return 0;
+	irq = create_irq();
+	if (irq > 0) {
+		irq_set_handler_data(irq, arg);
+		irq_set_chip_and_handler_name(irq, &dmar_msi_type,
+					      handle_edge_irq, "edge");
+		msi_compose_msg(NULL, irq, &msg);
+		dmar_msi_write(irq, &msg);
+	}
+
+	return irq;
+}
+
+void dmar_free_hwirq(int irq)
+{
+	irq_set_handler_data(irq, NULL);
+	destroy_irq(irq);
 }
 #endif /* CONFIG_INTEL_IOMMU */
 
arch/x86/include/asm/irq_remapping.h +0 -4
index b978c68f5d29..bacac1052262 100644
@@ -117,8 +117,4 @@ irq_remapping_get_irq_domain(struct irq_alloc_info *info)
 
 #define	irq_remapping_print_chip	NULL
 #endif /* CONFIG_IRQ_REMAP */
-
-extern int dmar_alloc_hwirq(void);
-extern void dmar_free_hwirq(int irq);
-
 #endif /* __X86_IRQ_REMAPPING_H */
arch/x86/kernel/apic/msi.c +13 -11
index afaaa1166a7d..695c82bbd682 100644
@@ -228,25 +228,27 @@ static struct irq_chip dmar_msi_type = {
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
-int arch_setup_dmar_msi(unsigned int irq)
+int dmar_alloc_hwirq(int id, int node, void *arg)
 {
+	int irq;
 	struct msi_msg msg;
-	struct irq_cfg *cfg = irq_cfg(irq);
 
-	native_compose_msi_msg(cfg, &msg);
-	dmar_msi_write(irq, &msg);
-	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-				      "edge");
-	return 0;
-}
+	irq = irq_domain_alloc_irqs(NULL, 1, node, NULL);
+	if (irq > 0) {
+		irq_set_handler_data(irq, arg);
+		irq_set_chip_and_handler_name(irq, &dmar_msi_type,
+					      handle_edge_irq, "edge");
+		native_compose_msi_msg(irq_cfg(irq), &msg);
+		dmar_msi_write(irq, &msg);
+	}
 
-int dmar_alloc_hwirq(void)
-{
-	return irq_domain_alloc_irqs(NULL, 1, NUMA_NO_NODE, NULL);
+	return irq;
 }
 
 void dmar_free_hwirq(int irq)
 {
+	irq_set_handler_data(irq, NULL);
+	irq_set_handler(irq, NULL);
 	irq_domain_free_irqs(irq, 1);
 }
 #endif
drivers/iommu/dmar.c +5 -14
index 9847613085e1..536f2d8ea41a 100644
@@ -1087,8 +1087,8 @@ static void free_iommu(struct intel_iommu *iommu)
 
 	if (iommu->irq) {
 		free_irq(iommu->irq, iommu);
-		irq_set_handler_data(iommu->irq, NULL);
 		dmar_free_hwirq(iommu->irq);
+		iommu->irq = 0;
 	}
 
 	if (iommu->qi) {
@@ -1642,23 +1642,14 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
 	if (iommu->irq)
 		return 0;
 
-	irq = dmar_alloc_hwirq();
-	if (irq <= 0) {
+	irq = dmar_alloc_hwirq(iommu->seq_id, iommu->node, iommu);
+	if (irq > 0) {
+		iommu->irq = irq;
+	} else {
 		pr_err("IOMMU: no free vectors\n");
 		return -EINVAL;
 	}
 
-	irq_set_handler_data(irq, iommu);
-	iommu->irq = irq;
-
-	ret = arch_setup_dmar_msi(irq);
-	if (ret) {
-		irq_set_handler_data(irq, NULL);
-		iommu->irq = 0;
-		dmar_free_hwirq(irq);
-		return ret;
-	}
-
 	ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
 	if (ret)
 		pr_err("IOMMU: can't request irq\n");
include/linux/dmar.h +2 -1
index 30624954dec5..84737565c1fd 100644
@@ -227,6 +227,7 @@ extern void dmar_msi_read(int irq, struct msi_msg *msg);
 extern void dmar_msi_write(int irq, struct msi_msg *msg);
 extern int dmar_set_interrupt(struct intel_iommu *iommu);
 extern irqreturn_t dmar_fault(int irq, void *dev_id);
-extern int arch_setup_dmar_msi(unsigned int irq);
+extern int dmar_alloc_hwirq(int id, int node, void *arg);
+extern void dmar_free_hwirq(int irq);
 
 #endif /* __DMAR_H__ */
Signature · 1 line
1.7.10.4
#36 lore raw

[tip:x86/apic] iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit

iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit
Commit-ID:  34742db8eaf9ff364034f214ee5827701e131d4b
Gitweb:     http://git.kernel.org/tip/34742db8eaf9ff364034f214ee5827701e131d4b
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:41 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit

Refine the interfaces to create IRQ for DMAR unit. It's a preparation for converting DMAR IRQ to hierarchical irqdomain on x86.

It also moves dmar_alloc_hwirq()/dmar_free_hwirq() from irq_remapping.h to dmar.h. They are not irq_remapping specific.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Vinod Koul <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Tony Luck <[email protected]>
Cc Fenghua Yu <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/ia64/include/asm/irq_remapping.h |  2 --
 arch/ia64/kernel/msi_ia64.c           | 30 +++++++++++++++++++-----------
 arch/x86/include/asm/irq_remapping.h  |  4 ----
 arch/x86/kernel/apic/msi.c            | 24 +++++++++++++-----------
 drivers/iommu/dmar.c                  | 19 +++++--------------
 include/linux/dmar.h                  |  3 ++-
 6 files changed, 39 insertions(+), 43 deletions(-)
arch/ia64/include/asm/irq_remapping.h +0 -2
index e3b3556..a8687b1 100644
@@ -1,6 +1,4 @@
 #ifndef __IA64_INTR_REMAPPING_H
 #define __IA64_INTR_REMAPPING_H
 #define irq_remapping_enabled 0
-#define dmar_alloc_hwirq	create_irq
-#define dmar_free_hwirq		destroy_irq
 #endif
arch/ia64/kernel/msi_ia64.c +19 -11
index 9dd7464..d70bf15 100644
@@ -165,7 +165,7 @@ static struct irq_chip dmar_msi_type = {
 	.irq_retrigger = ia64_msi_retrigger_irq,
 };
 
-static int
+static void
 msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 {
 	struct irq_cfg *cfg = irq_cfg + irq;
@@ -186,21 +186,29 @@ msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 		MSI_DATA_LEVEL_ASSERT |
 		MSI_DATA_DELIVERY_FIXED |
 		MSI_DATA_VECTOR(cfg->vector);
-	return 0;
 }
 
-int arch_setup_dmar_msi(unsigned int irq)
+int dmar_alloc_hwirq(int id, int node, void *arg)
 {
-	int ret;
+	int irq;
 	struct msi_msg msg;
 
-	ret = msi_compose_msg(NULL, irq, &msg);
-	if (ret < 0)
-		return ret;
-	dmar_msi_write(irq, &msg);
-	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-				      "edge");
-	return 0;
+	irq = create_irq();
+	if (irq > 0) {
+		irq_set_handler_data(irq, arg);
+		irq_set_chip_and_handler_name(irq, &dmar_msi_type,
+					      handle_edge_irq, "edge");
+		msi_compose_msg(NULL, irq, &msg);
+		dmar_msi_write(irq, &msg);
+	}
+
+	return irq;
+}
+
+void dmar_free_hwirq(int irq)
+{
+	irq_set_handler_data(irq, NULL);
+	destroy_irq(irq);
 }
 #endif /* CONFIG_INTEL_IOMMU */
 
arch/x86/include/asm/irq_remapping.h +0 -4
index b978c68..bacac10 100644
@@ -117,8 +117,4 @@ irq_remapping_get_irq_domain(struct irq_alloc_info *info)
 
 #define	irq_remapping_print_chip	NULL
 #endif /* CONFIG_IRQ_REMAP */
-
-extern int dmar_alloc_hwirq(void);
-extern void dmar_free_hwirq(int irq);
-
 #endif /* __X86_IRQ_REMAPPING_H */
arch/x86/kernel/apic/msi.c +13 -11
index 9fe7a08..ca62504 100644
@@ -228,25 +228,27 @@ static struct irq_chip dmar_msi_type = {
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
-int arch_setup_dmar_msi(unsigned int irq)
+int dmar_alloc_hwirq(int id, int node, void *arg)
 {
+	int irq;
 	struct msi_msg msg;
-	struct irq_cfg *cfg = irq_cfg(irq);
 
-	native_compose_msi_msg(cfg, &msg);
-	dmar_msi_write(irq, &msg);
-	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-				      "edge");
-	return 0;
-}
+	irq = irq_domain_alloc_irqs(NULL, 1, node, NULL);
+	if (irq > 0) {
+		irq_set_handler_data(irq, arg);
+		irq_set_chip_and_handler_name(irq, &dmar_msi_type,
+					      handle_edge_irq, "edge");
+		native_compose_msi_msg(irq_cfg(irq), &msg);
+		dmar_msi_write(irq, &msg);
+	}
 
-int dmar_alloc_hwirq(void)
-{
-	return irq_domain_alloc_irqs(NULL, 1, NUMA_NO_NODE, NULL);
+	return irq;
 }
 
 void dmar_free_hwirq(int irq)
 {
+	irq_set_handler_data(irq, NULL);
+	irq_set_handler(irq, NULL);
 	irq_domain_free_irqs(irq, 1);
 }
 #endif
drivers/iommu/dmar.c +5 -14
index 9847613..536f2d8 100644
@@ -1087,8 +1087,8 @@ static void free_iommu(struct intel_iommu *iommu)
 
 	if (iommu->irq) {
 		free_irq(iommu->irq, iommu);
-		irq_set_handler_data(iommu->irq, NULL);
 		dmar_free_hwirq(iommu->irq);
+		iommu->irq = 0;
 	}
 
 	if (iommu->qi) {
@@ -1642,23 +1642,14 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
 	if (iommu->irq)
 		return 0;
 
-	irq = dmar_alloc_hwirq();
-	if (irq <= 0) {
+	irq = dmar_alloc_hwirq(iommu->seq_id, iommu->node, iommu);
+	if (irq > 0) {
+		iommu->irq = irq;
+	} else {
 		pr_err("IOMMU: no free vectors\n");
 		return -EINVAL;
 	}
 
-	irq_set_handler_data(irq, iommu);
-	iommu->irq = irq;
-
-	ret = arch_setup_dmar_msi(irq);
-	if (ret) {
-		irq_set_handler_data(irq, NULL);
-		iommu->irq = 0;
-		dmar_free_hwirq(irq);
-		return ret;
-	}
-
 	ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
 	if (ret)
 		pr_err("IOMMU: can't request irq\n");
include/linux/dmar.h +2 -1
index 3062495..8473756 100644
@@ -227,6 +227,7 @@ extern void dmar_msi_read(int irq, struct msi_msg *msg);
 extern void dmar_msi_write(int irq, struct msi_msg *msg);
 extern int dmar_set_interrupt(struct intel_iommu *iommu);
 extern irqreturn_t dmar_fault(int irq, void *dev_id);
-extern int arch_setup_dmar_msi(unsigned int irq);
+extern int dmar_alloc_hwirq(int id, int node, void *arg);
+extern void dmar_free_hwirq(int irq);
 
 #endif /* __DMAR_H__ */
author
#37 lore raw

PATCH v8 20/37 x86/irq: Use hierarchy irqdomain to manage DMAR interrupts

In reply to Jiang Liu

Enhance DMAR code to support hierarchy irqdomain, it helps to make the architecture more clear.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/include/asm/hw_irq.h |    7 ++
 arch/x86/kernel/apic/msi.c    |  153 ++++++++++++++++++++++++++---------------
 2 files changed, 103 insertions(+), 57 deletions(-)
arch/x86/include/asm/hw_irq.h +7 -0
index 270c432971f8..29f1dc162a24 100644
@@ -122,6 +122,7 @@ enum irq_alloc_type {
 	X86_IRQ_ALLOC_TYPE_HPET,
 	X86_IRQ_ALLOC_TYPE_MSI,
 	X86_IRQ_ALLOC_TYPE_MSIX,
+	X86_IRQ_ALLOC_TYPE_DMAR,
 };
 
 struct irq_alloc_info {
@@ -154,6 +155,12 @@ struct irq_alloc_info {
 			struct IO_APIC_route_entry *ioapic_entry;
 		};
 #endif
+#ifdef	CONFIG_DMAR_TABLE
+		struct {
+			int		dmar_id;
+			void		*dmar_data;
+		};
+#endif
 	};
 };
 
arch/x86/kernel/apic/msi.c +96 -57

193 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#38 lore raw

[tip:x86/apic] x86/irq: Use hierarchical irqdomain to manage DMAR interrupts

x86/irq: Use hierarchical irqdomain to manage DMAR interrupts
Commit-ID:  0921f1da6425f05a1f56803069124b7ec13b79e2
Gitweb:     http://git.kernel.org/tip/0921f1da6425f05a1f56803069124b7ec13b79e2
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:42 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:49 +0200

x86/irq: Use hierarchical irqdomain to manage DMAR interrupts

Enhance DMAR code to support hierarchical irqdomain, it helps to make the architecture more clear.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/include/asm/hw_irq.h |   7 ++
 arch/x86/kernel/apic/msi.c    | 153 ++++++++++++++++++++++++++----------------
 2 files changed, 103 insertions(+), 57 deletions(-)
arch/x86/include/asm/hw_irq.h +7 -0
index 05829e9..bf17250 100644
@@ -122,6 +122,7 @@ enum irq_alloc_type {
 	X86_IRQ_ALLOC_TYPE_HPET,
 	X86_IRQ_ALLOC_TYPE_MSI,
 	X86_IRQ_ALLOC_TYPE_MSIX,
+	X86_IRQ_ALLOC_TYPE_DMAR,
 };
 
 struct irq_alloc_info {
@@ -154,6 +155,12 @@ struct irq_alloc_info {
 			struct IO_APIC_route_entry *ioapic_entry;
 		};
 #endif
+#ifdef	CONFIG_DMAR_TABLE
+		struct {
+			int		dmar_id;
+			void		*dmar_data;
+		};
+#endif
 	};
 };
 
arch/x86/kernel/apic/msi.c +96 -57

193 lines not on this page · raw message

author
#39 lore raw

PATCH v8 21/37 x86/htirq: Use hierarchy irqdomain to manage Hypertransport interrupts

In reply to Jiang Liu

Use hierarchy irqdomain to manage Hypertransport interrupts. We have slightly changed the architecture interfaces to support htirq PCI driver, it should be safe because currently Hypertransport interrupt is only enabled on x86 platforms.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/include/asm/hw_irq.h |   13 ++++
 arch/x86/kernel/apic/htirq.c  |  161 ++++++++++++++++++++++++++++++-----------
 arch/x86/kernel/apic/vector.c |    1 +
 drivers/pci/htirq.c           |   47 ++----------
 include/linux/htirq.h         |   24 ++++--
 5 files changed, 158 insertions(+), 88 deletions(-)
arch/x86/include/asm/hw_irq.h +13 -0
index 29f1dc162a24..46dec7e37829 100644
@@ -161,6 +161,14 @@ struct irq_alloc_info {
 			void		*dmar_data;
 		};
 #endif
+#ifdef	CONFIG_HT_IRQ
+		struct {
+			int		ht_pos;
+			int		ht_idx;
+			struct pci_dev	*ht_dev;
+			void		*ht_update;
+		};
+#endif
 	};
 };
 
@@ -227,6 +235,11 @@ extern void arch_init_msi_domain(struct irq_domain *domain);
 #else
 static inline void arch_init_msi_domain(struct irq_domain *domain) { }
 #endif
+#ifdef	CONFIG_HT_IRQ
+extern void arch_init_htirq_domain(struct irq_domain *domain);
+#else
+static inline void arch_init_htirq_domain(struct irq_domain *domain) { }
+#endif
 
 /* Statistics */
 extern atomic_t irq_err_count;
arch/x86/kernel/apic/htirq.c +120 -41

209 lines not on this page · raw message

arch/x86/kernel/apic/vector.c +1 -0
index e971c87f7858..609db1910fd3 100644
@@ -365,6 +365,7 @@ int __init arch_early_irq_init(void)
 	irq_set_default_host(x86_vector_domain);
 
 	arch_init_msi_domain(x86_vector_domain);
+	arch_init_htirq_domain(x86_vector_domain);
 
 	return arch_early_ioapic_init();
 }
drivers/pci/htirq.c +6 -41

80 lines not on this page · raw message

include/linux/htirq.h +18 -6
index 5caa51b7b95c..d4a527e58434 100644
@@ -1,26 +1,38 @@
 #ifndef LINUX_HTIRQ_H
 #define LINUX_HTIRQ_H
 
+struct pci_dev;
+struct irq_data;
+
 struct ht_irq_msg {
 	u32	address_lo;	/* low 32 bits of the ht irq message */
 	u32	address_hi;	/* high 32 bits of the it irq message */
 };
 
+typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
+			       struct ht_irq_msg *msg);
+
+struct ht_irq_cfg {
+	struct pci_dev *dev;
+	 /* Update callback used to cope with buggy hardware */
+	ht_irq_update_t *update;
+	unsigned pos;
+	unsigned idx;
+	struct ht_irq_msg msg;
+};
+
 /* Helper functions.. */
 void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
 void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
-struct irq_data;
 void mask_ht_irq(struct irq_data *data);
 void unmask_ht_irq(struct irq_data *data);
 
 /* The arch hook for getting things started */
-int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
-int arch_alloc_ht_irq(struct pci_dev *dev);
-void arch_free_ht_irq(int irq);
+int arch_setup_ht_irq(int idx, int pos, struct pci_dev *dev,
+		      ht_irq_update_t *update);
+void arch_teardown_ht_irq(unsigned int irq);
 
 /* For drivers of buggy hardware */
-typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
-			       struct ht_irq_msg *msg);
 int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update);
 
 #endif /* LINUX_HTIRQ_H */
Signature · 1 line
1.7.10.4
#40 lore raw

[tip:x86/apic] x86/htirq: Use hierarchical irqdomain to manage Hypertransport interrupts

x86/htirq: Use hierarchical irqdomain to manage Hypertransport interrupts
Commit-ID:  49e07d8f28c05347f237146a9ec66f6d958db83e
Gitweb:     http://git.kernel.org/tip/49e07d8f28c05347f237146a9ec66f6d958db83e
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:43 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

x86/htirq: Use hierarchical irqdomain to manage Hypertransport interrupts

We have slightly changed the architecture interfaces to support htirq PCI driver. It's safe because currently Hypertransport interrupt is only enabled on x86 platforms.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/include/asm/hw_irq.h |  13 ++++
 arch/x86/kernel/apic/htirq.c  | 161 +++++++++++++++++++++++++++++++-----------
 arch/x86/kernel/apic/vector.c |   1 +
 drivers/pci/htirq.c           |  47 ++----------
 include/linux/htirq.h         |  24 +++++--
 5 files changed, 158 insertions(+), 88 deletions(-)
arch/x86/include/asm/hw_irq.h +13 -0
index bf17250..5e0b031 100644
@@ -161,6 +161,14 @@ struct irq_alloc_info {
 			void		*dmar_data;
 		};
 #endif
+#ifdef	CONFIG_HT_IRQ
+		struct {
+			int		ht_pos;
+			int		ht_idx;
+			struct pci_dev	*ht_dev;
+			void		*ht_update;
+		};
+#endif
 	};
 };
 
@@ -227,6 +235,11 @@ extern void arch_init_msi_domain(struct irq_domain *domain);
 #else
 static inline void arch_init_msi_domain(struct irq_domain *domain) { }
 #endif
+#ifdef	CONFIG_HT_IRQ
+extern void arch_init_htirq_domain(struct irq_domain *domain);
+#else
+static inline void arch_init_htirq_domain(struct irq_domain *domain) { }
+#endif
 
 /* Statistics */
 extern atomic_t irq_err_count;
arch/x86/kernel/apic/htirq.c +120 -41

209 lines not on this page · raw message

arch/x86/kernel/apic/vector.c +1 -0
index a8d8289..b4b6b5a 100644
@@ -365,6 +365,7 @@ int __init arch_early_irq_init(void)
 	irq_set_default_host(x86_vector_domain);
 
 	arch_init_msi_domain(x86_vector_domain);
+	arch_init_htirq_domain(x86_vector_domain);
 
 	return arch_early_ioapic_init();
 }
drivers/pci/htirq.c +6 -41

80 lines not on this page · raw message

include/linux/htirq.h +18 -6
index 5caa51b..d4a527e 100644
@@ -1,26 +1,38 @@
 #ifndef LINUX_HTIRQ_H
 #define LINUX_HTIRQ_H
 
+struct pci_dev;
+struct irq_data;
+
 struct ht_irq_msg {
 	u32	address_lo;	/* low 32 bits of the ht irq message */
 	u32	address_hi;	/* high 32 bits of the it irq message */
 };
 
+typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
+			       struct ht_irq_msg *msg);
+
+struct ht_irq_cfg {
+	struct pci_dev *dev;
+	 /* Update callback used to cope with buggy hardware */
+	ht_irq_update_t *update;
+	unsigned pos;
+	unsigned idx;
+	struct ht_irq_msg msg;
+};
+
 /* Helper functions.. */
 void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
 void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
-struct irq_data;
 void mask_ht_irq(struct irq_data *data);
 void unmask_ht_irq(struct irq_data *data);
 
 /* The arch hook for getting things started */
-int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
-int arch_alloc_ht_irq(struct pci_dev *dev);
-void arch_free_ht_irq(int irq);
+int arch_setup_ht_irq(int idx, int pos, struct pci_dev *dev,
+		      ht_irq_update_t *update);
+void arch_teardown_ht_irq(unsigned int irq);
 
 /* For drivers of buggy hardware */
-typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
-			       struct ht_irq_msg *msg);
 int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update);
 
 #endif /* LINUX_HTIRQ_H */
author
#41 lore raw

PATCH v8 22/37 x86/uv: Use hierarchy irqdomain to manage UV interrupts

In reply to Jiang Liu

Enhance UV code to support hierarchy irqdomain, it helps to make the architecture more clear.

We should construct hwirq based on mmr_blade and mmr_offset, but mmr_offset is type of unsigned long, it may exceed the range of irq_hw_number_t. So help about the way to construct hwirq based on mmr_blade and mmr_offset is welcomed!

Folded a patch from Dimitri Sivanich <[email protected]> to fix a bug on UV platforms, please refer to:
http://lkml.org/lkml/2014/12/16/351

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Russ Anderson <[email protected]>
---
 arch/x86/include/asm/hw_irq.h |    9 ++
 arch/x86/platform/uv/uv_irq.c |  290 ++++++++++++++++-------------------------
 2 files changed, 119 insertions(+), 180 deletions(-)
arch/x86/include/asm/hw_irq.h +9 -0
index 46dec7e37829..bbf90fe2a224 100644
@@ -123,6 +123,7 @@ enum irq_alloc_type {
 	X86_IRQ_ALLOC_TYPE_MSI,
 	X86_IRQ_ALLOC_TYPE_MSIX,
 	X86_IRQ_ALLOC_TYPE_DMAR,
+	X86_IRQ_ALLOC_TYPE_UV,
 };
 
 struct irq_alloc_info {
@@ -169,6 +170,14 @@ struct irq_alloc_info {
 			void		*ht_update;
 		};
 #endif
+#ifdef	CONFIG_X86_UV
+		struct {
+			int		uv_limit;
+			int		uv_blade;
+			unsigned long	uv_offset;
+			char		*uv_name;
+		};
+#endif
 	};
 };
 
arch/x86/platform/uv/uv_irq.c +110 -180

361 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#42 lore raw

[tip:x86/apic] x86/uv: Use hierarchical irqdomain to manage UV interrupts

x86/uv: Use hierarchical irqdomain to manage UV interrupts
Commit-ID:  43fe1abc18a237581663a51da4c2f8e57684c223
Gitweb:     http://git.kernel.org/tip/43fe1abc18a237581663a51da4c2f8e57684c223
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:44 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

x86/uv: Use hierarchical irqdomain to manage UV interrupts

Enhance UV code to support hierarchical irqdomain, it helps to make the architecture more clear.

We construct hwirq based on mmr_blade and mmr_offset, but mmr_offset has type unsigned long, it may exceed the range of irq_hw_number_t. So help about the way to construct hwirq based on mmr_blade and mmr_offset is welcomed!

Folded a patch from Dimitri Sivanich <[email protected]> to fix a bug on UV platforms, please refer to:
http://lkml.org/lkml/2014/12/16/351

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Russ Anderson <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/include/asm/hw_irq.h |   9 ++
 arch/x86/platform/uv/uv_irq.c | 290 ++++++++++++++++--------------------------
 2 files changed, 119 insertions(+), 180 deletions(-)
arch/x86/include/asm/hw_irq.h +9 -0
index 5e0b031..75d0db1 100644
@@ -123,6 +123,7 @@ enum irq_alloc_type {
 	X86_IRQ_ALLOC_TYPE_MSI,
 	X86_IRQ_ALLOC_TYPE_MSIX,
 	X86_IRQ_ALLOC_TYPE_DMAR,
+	X86_IRQ_ALLOC_TYPE_UV,
 };
 
 struct irq_alloc_info {
@@ -169,6 +170,14 @@ struct irq_alloc_info {
 			void		*ht_update;
 		};
 #endif
+#ifdef	CONFIG_X86_UV
+		struct {
+			int		uv_limit;
+			int		uv_blade;
+			unsigned long	uv_offset;
+			char		*uv_name;
+		};
+#endif
 	};
 };
 
arch/x86/platform/uv/uv_irq.c +110 -180

361 lines not on this page · raw message

author
#43 lore raw

PATCH v8 23/37 x86/irq: Normalize x86 irq_chip name

In reply to Jiang Liu

Some irq_chip names use underscore, others use hyphen. So normalize them to use hythen as separator.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/msi.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/msi.c +2 -2
index a24b803b199a..2bf13484fbfd 100644
@@ -188,7 +188,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 }
 
 static struct irq_chip dmar_msi_controller = {
-	.name			= "DMAR_MSI",
+	.name			= "DMAR-MSI",
 	.irq_unmask		= dmar_msi_unmask,
 	.irq_mask		= dmar_msi_mask,
 	.irq_ack		= irq_chip_ack_parent,
@@ -319,7 +319,7 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 }
 
 static struct irq_chip hpet_msi_controller = {
-	.name = "HPET_MSI",
+	.name = "HPET-MSI",
 	.irq_unmask = hpet_msi_unmask,
 	.irq_mask = hpet_msi_mask,
 	.irq_ack = irq_chip_ack_parent,
Signature · 1 line
1.7.10.4
#44 lore raw

[tip:x86/apic] x86/irq: Normalize x86 irq_chip name

x86/irq: Normalize x86 irq_chip name
Commit-ID:  81dabe2e739d5e0ad8ca2369738fb84bd64f967d
Gitweb:     http://git.kernel.org/tip/81dabe2e739d5e0ad8ca2369738fb84bd64f967d
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:45 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

x86/irq: Normalize x86 irq_chip name

Some irq_chip names use underscore, others use hyphen. So normalize them to use hyphen as separator.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/kernel/apic/msi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/msi.c +2 -2
index f23d17d..d17eb6a 100644
@@ -188,7 +188,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 }
 
 static struct irq_chip dmar_msi_controller = {
-	.name			= "DMAR_MSI",
+	.name			= "DMAR-MSI",
 	.irq_unmask		= dmar_msi_unmask,
 	.irq_mask		= dmar_msi_mask,
 	.irq_ack		= irq_chip_ack_parent,
@@ -319,7 +319,7 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 }
 
 static struct irq_chip hpet_msi_controller = {
-	.name = "HPET_MSI",
+	.name = "HPET-MSI",
 	.irq_unmask = hpet_msi_unmask,
 	.irq_mask = hpet_msi_mask,
 	.irq_ack = irq_chip_ack_parent,
author
#45 lore raw

PATCH v8 24/37 x86/MSI: Simplify the way to deal with remapped MSI interrupts

In reply to Jiang Liu

Simplify the way to deal with remapped MSI interrupts, so we could kill irq_chip.irq_print_chip later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/msi.c |   28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)
arch/x86/kernel/apic/msi.c +24 -4
index 2bf13484fbfd..8e8f2435f25e 100644
@@ -77,7 +77,6 @@ static struct irq_chip pci_msi_controller = {
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
-	.irq_print_chip		= irq_remapping_print_chip,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
 	.irq_write_msi_msg	= pci_msi_domain_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
@@ -143,7 +142,7 @@ static struct msi_domain_ops pci_msi_domain_ops = {
 
 static struct msi_domain_info pci_msi_domain_info = {
 	.flags		= MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-			  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
+			  MSI_FLAG_PCI_MSIX,
 	.ops		= &pci_msi_domain_ops,
 	.chip		= &pci_msi_controller,
 	.handler	= handle_edge_irq,
@@ -162,9 +161,29 @@ void arch_init_msi_domain(struct irq_domain *parent)
 }
 
 #ifdef CONFIG_IRQ_REMAP
+static struct irq_chip pci_msi_ir_controller = {
+	.name			= "IR-PCI-MSI",
+	.irq_unmask		= pci_msi_unmask_irq,
+	.irq_mask		= pci_msi_mask_irq,
+	.irq_ack		= irq_chip_ack_parent,
+	.irq_set_affinity	= msi_domain_set_affinity,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_write_msi_msg	= pci_msi_domain_write_msg,
+	.flags			= IRQCHIP_SKIP_SET_WAKE,
+};
+
+static struct msi_domain_info pci_msi_ir_domain_info = {
+	.flags		= MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+			  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
+	.ops		= &pci_msi_domain_ops,
+	.chip		= &pci_msi_ir_controller,
+	.handler	= handle_edge_irq,
+	.handler_name	= "edge",
+};
+
 struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent)
 {
-	return msi_create_irq_domain(NULL, &pci_msi_domain_info, parent);
+	return pci_msi_create_irq_domain(NULL, &pci_msi_ir_domain_info, parent);
 }
 #endif
 
@@ -325,7 +344,6 @@ static struct irq_chip hpet_msi_controller = {
 	.irq_ack = irq_chip_ack_parent,
 	.irq_set_affinity = hpet_msi_set_affinity,
 	.irq_retrigger = irq_chip_retrigger_hierarchy,
-	.irq_print_chip = irq_remapping_print_chip,
 	.irq_compose_msi_msg = irq_msi_compose_msg,
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
@@ -402,6 +420,8 @@ struct irq_domain *hpet_create_irq_domain(int hpet_id)
 	parent = irq_remapping_get_ir_irq_domain(&info);
 	if (parent == NULL)
 		parent = x86_vector_domain;
+	else
+		hpet_msi_controller.name = "IR-HPET-MSI";
 
 	return irq_domain_add_hierarchy(parent, 0, 0, NULL, &hpet_domain_ops,
 					(void *)(long)hpet_id);
Signature · 1 line
1.7.10.4
#46 lore raw

[tip:x86/apic] x86/MSI: Simplify the way to deal with remapped MSI interrupts

x86/MSI: Simplify the way to deal with remapped MSI interrupts
Commit-ID:  68682a2687bf7dbe51309d297757a7ea6a96d312
Gitweb:     http://git.kernel.org/tip/68682a2687bf7dbe51309d297757a7ea6a96d312
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:46 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

x86/MSI: Simplify the way to deal with remapped MSI interrupts

Simplify the way to deal with remapped MSI interrupts, so we can remove irq_chip.irq_print_chip later. We simply change the name when the setup detects that the parent domain is remapping.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/kernel/apic/msi.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)
arch/x86/kernel/apic/msi.c +24 -4
index d17eb6a..87df03a 100644
@@ -77,7 +77,6 @@ static struct irq_chip pci_msi_controller = {
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
-	.irq_print_chip		= irq_remapping_print_chip,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
 	.irq_write_msi_msg	= pci_msi_domain_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
@@ -143,7 +142,7 @@ static struct msi_domain_ops pci_msi_domain_ops = {
 
 static struct msi_domain_info pci_msi_domain_info = {
 	.flags		= MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-			  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
+			  MSI_FLAG_PCI_MSIX,
 	.ops		= &pci_msi_domain_ops,
 	.chip		= &pci_msi_controller,
 	.handler	= handle_edge_irq,
@@ -162,9 +161,29 @@ void arch_init_msi_domain(struct irq_domain *parent)
 }
 
 #ifdef CONFIG_IRQ_REMAP
+static struct irq_chip pci_msi_ir_controller = {
+	.name			= "IR-PCI-MSI",
+	.irq_unmask		= pci_msi_unmask_irq,
+	.irq_mask		= pci_msi_mask_irq,
+	.irq_ack		= irq_chip_ack_parent,
+	.irq_set_affinity	= msi_domain_set_affinity,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_write_msi_msg	= pci_msi_domain_write_msg,
+	.flags			= IRQCHIP_SKIP_SET_WAKE,
+};
+
+static struct msi_domain_info pci_msi_ir_domain_info = {
+	.flags		= MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+			  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
+	.ops		= &pci_msi_domain_ops,
+	.chip		= &pci_msi_ir_controller,
+	.handler	= handle_edge_irq,
+	.handler_name	= "edge",
+};
+
 struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent)
 {
-	return msi_create_irq_domain(NULL, &pci_msi_domain_info, parent);
+	return pci_msi_create_irq_domain(NULL, &pci_msi_ir_domain_info, parent);
 }
 #endif
 
@@ -325,7 +344,6 @@ static struct irq_chip hpet_msi_controller = {
 	.irq_ack = irq_chip_ack_parent,
 	.irq_set_affinity = hpet_msi_set_affinity,
 	.irq_retrigger = irq_chip_retrigger_hierarchy,
-	.irq_print_chip = irq_remapping_print_chip,
 	.irq_compose_msi_msg = irq_msi_compose_msg,
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
@@ -402,6 +420,8 @@ struct irq_domain *hpet_create_irq_domain(int hpet_id)
 	parent = irq_remapping_get_ir_irq_domain(&info);
 	if (parent == NULL)
 		parent = x86_vector_domain;
+	else
+		hpet_msi_controller.name = "IR-HPET-MSI";
 
 	return irq_domain_add_hierarchy(parent, 0, 0, NULL, &hpet_domain_ops,
 					(void *)(long)hpet_id);
author
#47 lore raw

PATCH v8 25/37 x86/MSI: Replace msi_update_msg() with irq_chip_compose_msi_msg()

In reply to Jiang Liu

Function irq_chip_compose_msi_msg() can achieve the same goal as msi_update_msg(), so kill msi_update_msg().

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/msi.c |   19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)
arch/x86/kernel/apic/msi.c +2 -17
index 8e8f2435f25e..15429aa112fe 100644
@@ -53,19 +53,6 @@ static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 		MSI_DATA_VECTOR(cfg->vector);
 }
 
-static void msi_update_msg(struct msi_msg *msg, struct irq_data *irq_data)
-{
-	struct irq_cfg *cfg = irqd_cfg(irq_data);
-
-	msg->data &= ~MSI_DATA_VECTOR_MASK;
-	msg->data |= MSI_DATA_VECTOR(cfg->vector);
-	msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK;
-	msg->address_lo |= MSI_ADDR_DEST_ID(cfg->dest_apicid);
-	if (x2apic_enabled())
-		msg->address_hi = MSI_ADDR_BASE_HI |
-				  MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid);
-}
-
 /*
  * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
  * which implement the MSI or MSI-X Capability Structure.
@@ -198,8 +185,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 
 	ret = parent->chip->irq_set_affinity(parent, mask, force);
 	if (ret >= 0) {
-		dmar_msi_read(data->irq, &msg);
-		msi_update_msg(&msg, data);
+		irq_chip_compose_msi_msg(data, &msg);
 		dmar_msi_write(data->irq, &msg);
 	}
 
@@ -329,8 +315,7 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 
 	ret = parent->chip->irq_set_affinity(parent, mask, force);
 	if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
-		hpet_msi_read(data->handler_data, &msg);
-		msi_update_msg(&msg, data);
+		irq_chip_compose_msi_msg(data, &msg);
 		hpet_msi_write(data->handler_data, &msg);
 	}
 
Signature · 1 line
1.7.10.4
#48 lore raw

[tip:x86/apic] x86/MSI: Replace msi_update_msg() with irq_chip_compose_msi_msg()

x86/MSI: Replace msi_update_msg() with irq_chip_compose_msi_msg()
Commit-ID:  90d84fe95dd6b418383aa0e0e5cace8f1b1e7e30
Gitweb:     http://git.kernel.org/tip/90d84fe95dd6b418383aa0e0e5cace8f1b1e7e30
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:47 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

x86/MSI: Replace msi_update_msg() with irq_chip_compose_msi_msg()

Function irq_chip_compose_msi_msg() can achieve the same goal as msi_update_msg(), so remove msi_update_msg().

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/kernel/apic/msi.c | 19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)
arch/x86/kernel/apic/msi.c +2 -17
index 87df03a..5b5ef5b 100644
@@ -53,19 +53,6 @@ static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 		MSI_DATA_VECTOR(cfg->vector);
 }
 
-static void msi_update_msg(struct msi_msg *msg, struct irq_data *irq_data)
-{
-	struct irq_cfg *cfg = irqd_cfg(irq_data);
-
-	msg->data &= ~MSI_DATA_VECTOR_MASK;
-	msg->data |= MSI_DATA_VECTOR(cfg->vector);
-	msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK;
-	msg->address_lo |= MSI_ADDR_DEST_ID(cfg->dest_apicid);
-	if (x2apic_enabled())
-		msg->address_hi = MSI_ADDR_BASE_HI |
-				  MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid);
-}
-
 /*
  * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
  * which implement the MSI or MSI-X Capability Structure.
@@ -198,8 +185,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 
 	ret = parent->chip->irq_set_affinity(parent, mask, force);
 	if (ret >= 0) {
-		dmar_msi_read(data->irq, &msg);
-		msi_update_msg(&msg, data);
+		irq_chip_compose_msi_msg(data, &msg);
 		dmar_msi_write(data->irq, &msg);
 	}
 
@@ -329,8 +315,7 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 
 	ret = parent->chip->irq_set_affinity(parent, mask, force);
 	if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
-		hpet_msi_read(data->handler_data, &msg);
-		msi_update_msg(&msg, data);
+		irq_chip_compose_msi_msg(data, &msg);
 		hpet_msi_write(data->handler_data, &msg);
 	}
 
author
#49 lore raw

PATCH v8 26/37 x86/irq: Implement irq_chip.irq_write_msi_msg for MSI/DMAR/HPET irq_chips

In reply to Jiang Liu

Implement irq_chip.irq_write_msi_msg for MSI/DMAR/HPET irq_chips, they will be used to share common code later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/msi.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)
arch/x86/kernel/apic/msi.c +12 -0
index 15429aa112fe..f5b899514634 100644
@@ -192,6 +192,11 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	return ret;
 }
 
+static void dmar_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	dmar_msi_write(data->irq, msg);
+}
+
 static struct irq_chip dmar_msi_controller = {
 	.name			= "DMAR-MSI",
 	.irq_unmask		= dmar_msi_unmask,
@@ -200,6 +205,7 @@ static struct irq_chip dmar_msi_controller = {
 	.irq_set_affinity	= dmar_msi_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
+	.irq_write_msi_msg	= dmar_msi_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -322,6 +328,11 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 	return ret;
 }
 
+static void hpet_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	hpet_msi_write(data->handler_data, msg);
+}
+
 static struct irq_chip hpet_msi_controller = {
 	.name = "HPET-MSI",
 	.irq_unmask = hpet_msi_unmask,
@@ -330,6 +341,7 @@ static struct irq_chip hpet_msi_controller = {
 	.irq_set_affinity = hpet_msi_set_affinity,
 	.irq_retrigger = irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg = irq_msi_compose_msg,
+	.irq_write_msi_msg = hpet_msi_write_msg,
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
Signature · 1 line
1.7.10.4
#50 lore raw

[tip:x86/apic] x86/irq: Implement irq_chip.irq_write_msi_msg for MSI/DMAR/HPET irq_chips

x86/irq: Implement irq_chip.irq_write_msi_msg for MSI/DMAR/HPET irq_chips
Commit-ID:  62ac1780830ed64a9a46f80a03e91de71957d670
Gitweb:     http://git.kernel.org/tip/62ac1780830ed64a9a46f80a03e91de71957d670
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:48 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

x86/irq: Implement irq_chip.irq_write_msi_msg for MSI/DMAR/HPET irq_chips

Implement irq_chip.irq_write_msi_msg for MSI/DMAR/HPET irq_chips, they will be used to replace duplicated code.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/kernel/apic/msi.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
arch/x86/kernel/apic/msi.c +12 -0
index 5b5ef5b..3c82586 100644
@@ -192,6 +192,11 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	return ret;
 }
 
+static void dmar_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	dmar_msi_write(data->irq, msg);
+}
+
 static struct irq_chip dmar_msi_controller = {
 	.name			= "DMAR-MSI",
 	.irq_unmask		= dmar_msi_unmask,
@@ -200,6 +205,7 @@ static struct irq_chip dmar_msi_controller = {
 	.irq_set_affinity	= dmar_msi_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
+	.irq_write_msi_msg	= dmar_msi_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -322,6 +328,11 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 	return ret;
 }
 
+static void hpet_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	hpet_msi_write(data->handler_data, msg);
+}
+
 static struct irq_chip hpet_msi_controller = {
 	.name = "HPET-MSI",
 	.irq_unmask = hpet_msi_unmask,
@@ -330,6 +341,7 @@ static struct irq_chip hpet_msi_controller = {
 	.irq_set_affinity = hpet_msi_set_affinity,
 	.irq_retrigger = irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg = irq_msi_compose_msg,
+	.irq_write_msi_msg = hpet_msi_write_msg,
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
author
#51 lore raw

PATCH v8 27/37 x86/irq: Simplify MSI/DMAR/HPET implementation by using common code

In reply to Jiang Liu

Use common MSI interfaces to simplify DMAR/HPET driver implementation.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/kernel/apic/msi.c |  192 +++++++++++++-------------------------------
 1 file changed, 54 insertions(+), 138 deletions(-)
arch/x86/kernel/apic/msi.c +54 -138
index f5b899514634..da163da5fdee 100644
@@ -62,10 +62,8 @@ static struct irq_chip pci_msi_controller = {
 	.irq_unmask		= pci_msi_unmask_irq,
 	.irq_mask		= pci_msi_mask_irq,
 	.irq_ack		= irq_chip_ack_parent,
-	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
-	.irq_write_msi_msg	= pci_msi_domain_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -153,9 +151,7 @@ static struct irq_chip pci_msi_ir_controller = {
 	.irq_unmask		= pci_msi_unmask_irq,
 	.irq_mask		= pci_msi_mask_irq,
 	.irq_ack		= irq_chip_ack_parent,
-	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
-	.irq_write_msi_msg	= pci_msi_domain_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -175,23 +171,6 @@ struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent)
 #endif
 
 #ifdef CONFIG_DMAR_TABLE
-static int
-dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
-		      bool force)
-{
-	struct irq_data *parent = data->parent_data;
-	struct msi_msg msg;
-	int ret;
-
-	ret = parent->chip->irq_set_affinity(parent, mask, force);
-	if (ret >= 0) {
-		irq_chip_compose_msi_msg(data, &msg);
-		dmar_msi_write(data->irq, &msg);
-	}
-
-	return ret;
-}
-
 static void dmar_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
 {
 	dmar_msi_write(data->irq, msg);
@@ -202,67 +181,37 @@ static struct irq_chip dmar_msi_controller = {
 	.irq_unmask		= dmar_msi_unmask,
 	.irq_mask		= dmar_msi_mask,
 	.irq_ack		= irq_chip_ack_parent,
-	.irq_set_affinity	= dmar_msi_set_affinity,
+	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
 	.irq_write_msi_msg	= dmar_msi_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
-static int dmar_domain_alloc(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs, void *arg)
+static irq_hw_number_t dmar_msi_get_hwirq(struct msi_domain_info *info,
+					  msi_alloc_info_t *arg)
 {
-	struct irq_alloc_info *info = arg;
-	int ret;
-
-	if (nr_irqs > 1 || !info || info->type != X86_IRQ_ALLOC_TYPE_DMAR)
-		return -EINVAL;
-	if (irq_find_mapping(domain, info->dmar_id)) {
-		pr_warn("IRQ for DMAR%d already exists.\n", info->dmar_id);
-		return -EEXIST;
-	}
-
-	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
-	if (ret >= 0) {
-		irq_domain_set_hwirq_and_chip(domain, virq, info->dmar_id,
-					      &dmar_msi_controller, NULL);
-		irq_set_handler_data(virq, info->dmar_data);
-		__irq_set_handler(virq, handle_edge_irq, 0, "edge");
-	}
-
-	return ret;
+	return arg->dmar_id;
 }
 
-static void dmar_domain_free(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs)
+static int dmar_msi_init(struct irq_domain *domain,
+			 struct msi_domain_info *info, unsigned int virq,
+			 irq_hw_number_t hwirq, msi_alloc_info_t *arg)
 {
-	BUG_ON(nr_irqs > 1);
-	irq_domain_free_irqs_top(domain, virq, nr_irqs);
-}
+	irq_domain_set_info(domain, virq, arg->dmar_id, info->chip, NULL,
+			    handle_edge_irq, arg->dmar_data, "edge");
 
-static void dmar_domain_activate(struct irq_domain *domain,
-				 struct irq_data *irq_data)
-{
-	struct msi_msg msg;
-
-	BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
-	dmar_msi_write(irq_data->irq, &msg);
+	return 0;
 }
 
-static void dmar_domain_deactivate(struct irq_domain *domain,
-				   struct irq_data *irq_data)
-{
-	struct msi_msg msg;
-
-	memset(&msg, 0, sizeof(msg));
-	dmar_msi_write(irq_data->irq, &msg);
-}
+static struct msi_domain_ops dmar_msi_domain_ops = {
+	.get_hwirq	= dmar_msi_get_hwirq,
+	.msi_init	= dmar_msi_init,
+};
 
-static struct irq_domain_ops dmar_domain_ops = {
-	.alloc = dmar_domain_alloc,
-	.free = dmar_domain_free,
-	.activate = dmar_domain_activate,
-	.deactivate = dmar_domain_deactivate,
+static struct msi_domain_info dmar_msi_domain_info = {
+	.ops		= &dmar_msi_domain_ops,
+	.chip		= &dmar_msi_controller,
 };
 
 static struct irq_domain *dmar_get_irq_domain(void)
@@ -271,11 +220,9 @@ static struct irq_domain *dmar_get_irq_domain(void)
 	static DEFINE_MUTEX(dmar_lock);
 
 	mutex_lock(&dmar_lock);
-	if (dmar_domain == NULL) {
-		dmar_domain = irq_domain_add_tree(NULL, &dmar_domain_ops, NULL);
-		if (dmar_domain)
-			dmar_domain->parent = x86_vector_domain;
-	}
+	if (dmar_domain == NULL)
+		dmar_domain = msi_create_irq_domain(NULL, &dmar_msi_domain_info,
+						    x86_vector_domain);
 	mutex_unlock(&dmar_lock);
 
 	return dmar_domain;
@@ -309,23 +256,9 @@ void dmar_free_hwirq(int irq)
 #ifdef CONFIG_HPET_TIMER
 static inline int hpet_dev_id(struct irq_domain *domain)
 {
-	return (int)(long)domain->host_data;
-}
+	struct msi_domain_info *info = msi_get_domain_info(domain);
 
-static int hpet_msi_set_affinity(struct irq_data *data,
-				 const struct cpumask *mask, bool force)
-{
-	struct irq_data *parent = data->parent_data;
-	struct msi_msg msg;
-	int ret;
-
-	ret = parent->chip->irq_set_affinity(parent, mask, force);
-	if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
-		irq_chip_compose_msi_msg(data, &msg);
-		hpet_msi_write(data->handler_data, &msg);
-	}
-
-	return ret;
+	return (int)(long)info->data;
 }
 
 static void hpet_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
@@ -338,79 +271,63 @@ static struct irq_chip hpet_msi_controller = {
 	.irq_unmask = hpet_msi_unmask,
 	.irq_mask = hpet_msi_mask,
 	.irq_ack = irq_chip_ack_parent,
-	.irq_set_affinity = hpet_msi_set_affinity,
+	.irq_set_affinity = msi_domain_set_affinity,
 	.irq_retrigger = irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg = irq_msi_compose_msg,
 	.irq_write_msi_msg = hpet_msi_write_msg,
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
-static int hpet_domain_alloc(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs, void *arg)
-{
-	struct irq_alloc_info *info = arg;
-	int ret;
-
-	if (nr_irqs > 1 || !info || info->type != X86_IRQ_ALLOC_TYPE_HPET)
-		return -EINVAL;
-	if (irq_find_mapping(domain, info->hpet_index)) {
-		pr_warn("IRQ for HPET%d already exists.\n", info->hpet_index);
-		return -EEXIST;
-	}
-
-	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
-	if (ret >= 0) {
-		irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
-		irq_domain_set_hwirq_and_chip(domain, virq, info->hpet_index,
-					      &hpet_msi_controller, NULL);
-		irq_set_handler_data(virq, info->hpet_data);
-		__irq_set_handler(virq, handle_edge_irq, 0, "edge");
-	}
-
-	return ret;
-}
-
-static void hpet_domain_free(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs)
+static irq_hw_number_t hpet_msi_get_hwirq(struct msi_domain_info *info,
+					  msi_alloc_info_t *arg)
 {
-	BUG_ON(nr_irqs > 1);
-	irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
-	irq_domain_free_irqs_top(domain, virq, nr_irqs);
+	return arg->hpet_index;
 }
 
-static void hpet_domain_activate(struct irq_domain *domain,
-				struct irq_data *irq_data)
+static int hpet_msi_init(struct irq_domain *domain,
+			 struct msi_domain_info *info, unsigned int virq,
+			 irq_hw_number_t hwirq, msi_alloc_info_t *arg)
 {
-	struct msi_msg msg;
+	irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
+	irq_domain_set_info(domain, virq, arg->hpet_index, info->chip, NULL,
+			    handle_edge_irq, arg->hpet_data, "edge");
 
-	BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
-	hpet_msi_write(irq_get_handler_data(irq_data->irq), &msg);
+	return 0;
 }
 
-static void hpet_domain_deactivate(struct irq_domain *domain,
-				  struct irq_data *irq_data)
+static void hpet_msi_free(struct irq_domain *domain,
+			  struct msi_domain_info *info, unsigned int virq)
 {
-	struct msi_msg msg;
-
-	memset(&msg, 0, sizeof(msg));
-	hpet_msi_write(irq_get_handler_data(irq_data->irq), &msg);
+	irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
 }
 
-static struct irq_domain_ops hpet_domain_ops = {
-	.alloc = hpet_domain_alloc,
-	.free = hpet_domain_free,
-	.activate = hpet_domain_activate,
-	.deactivate = hpet_domain_deactivate,
+static struct msi_domain_ops hpet_msi_domain_ops = {
+	.get_hwirq	= hpet_msi_get_hwirq,
+	.msi_init	= hpet_msi_init,
+	.msi_free	= hpet_msi_free,
+};
+
+static struct msi_domain_info hpet_msi_domain_info = {
+	.ops		= &hpet_msi_domain_ops,
+	.chip		= &hpet_msi_controller,
 };
 
 struct irq_domain *hpet_create_irq_domain(int hpet_id)
 {
 	struct irq_domain *parent;
 	struct irq_alloc_info info;
+	struct msi_domain_info *domain_info;
 
 	if (x86_vector_domain == NULL)
 		return NULL;
 
+	domain_info = kzalloc(sizeof(*domain_info), GFP_KERNEL);
+	if (!domain_info)
+		return NULL;
+
+	*domain_info = hpet_msi_domain_info;
+	domain_info->data = (void *)(long)hpet_id;
+
 	init_irq_alloc_info(&info, NULL);
 	info.type = X86_IRQ_ALLOC_TYPE_HPET;
 	info.hpet_id = hpet_id;
@@ -420,8 +337,7 @@ struct irq_domain *hpet_create_irq_domain(int hpet_id)
 	else
 		hpet_msi_controller.name = "IR-HPET-MSI";
 
-	return irq_domain_add_hierarchy(parent, 0, 0, NULL, &hpet_domain_ops,
-					(void *)(long)hpet_id);
+	return msi_create_irq_domain(NULL, domain_info, parent);
 }
 
 int hpet_assign_irq(struct irq_domain *domain, struct hpet_dev *dev,
Signature · 1 line
1.7.10.4
#52 lore raw

[tip:x86/apic] x86/irq: Simplify MSI/DMAR/ HPET implementation by using common code

x86/irq: Simplify MSI/DMAR/HPET implementation by using common code
Commit-ID:  e390d895ae14ad655c6b830e62a22a81b69290ef
Gitweb:     http://git.kernel.org/tip/e390d895ae14ad655c6b830e62a22a81b69290ef
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:49 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

x86/irq: Simplify MSI/DMAR/HPET implementation by using common code

Use common MSI interfaces instead of private implementations of the same functionality to simplify DMAR/HPET driver implementation.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
---
 arch/x86/kernel/apic/msi.c | 192 +++++++++++++--------------------------------
 1 file changed, 54 insertions(+), 138 deletions(-)
arch/x86/kernel/apic/msi.c +54 -138
index 3c82586..1095842 100644
@@ -62,10 +62,8 @@ static struct irq_chip pci_msi_controller = {
 	.irq_unmask		= pci_msi_unmask_irq,
 	.irq_mask		= pci_msi_mask_irq,
 	.irq_ack		= irq_chip_ack_parent,
-	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
-	.irq_write_msi_msg	= pci_msi_domain_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -153,9 +151,7 @@ static struct irq_chip pci_msi_ir_controller = {
 	.irq_unmask		= pci_msi_unmask_irq,
 	.irq_mask		= pci_msi_mask_irq,
 	.irq_ack		= irq_chip_ack_parent,
-	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
-	.irq_write_msi_msg	= pci_msi_domain_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -175,23 +171,6 @@ struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent)
 #endif
 
 #ifdef CONFIG_DMAR_TABLE
-static int
-dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
-		      bool force)
-{
-	struct irq_data *parent = data->parent_data;
-	struct msi_msg msg;
-	int ret;
-
-	ret = parent->chip->irq_set_affinity(parent, mask, force);
-	if (ret >= 0) {
-		irq_chip_compose_msi_msg(data, &msg);
-		dmar_msi_write(data->irq, &msg);
-	}
-
-	return ret;
-}
-
 static void dmar_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
 {
 	dmar_msi_write(data->irq, msg);
@@ -202,67 +181,37 @@ static struct irq_chip dmar_msi_controller = {
 	.irq_unmask		= dmar_msi_unmask,
 	.irq_mask		= dmar_msi_mask,
 	.irq_ack		= irq_chip_ack_parent,
-	.irq_set_affinity	= dmar_msi_set_affinity,
+	.irq_set_affinity	= msi_domain_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
 	.irq_write_msi_msg	= dmar_msi_write_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
-static int dmar_domain_alloc(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs, void *arg)
+static irq_hw_number_t dmar_msi_get_hwirq(struct msi_domain_info *info,
+					  msi_alloc_info_t *arg)
 {
-	struct irq_alloc_info *info = arg;
-	int ret;
-
-	if (nr_irqs > 1 || !info || info->type != X86_IRQ_ALLOC_TYPE_DMAR)
-		return -EINVAL;
-	if (irq_find_mapping(domain, info->dmar_id)) {
-		pr_warn("IRQ for DMAR%d already exists.\n", info->dmar_id);
-		return -EEXIST;
-	}
-
-	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
-	if (ret >= 0) {
-		irq_domain_set_hwirq_and_chip(domain, virq, info->dmar_id,
-					      &dmar_msi_controller, NULL);
-		irq_set_handler_data(virq, info->dmar_data);
-		__irq_set_handler(virq, handle_edge_irq, 0, "edge");
-	}
-
-	return ret;
+	return arg->dmar_id;
 }
 
-static void dmar_domain_free(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs)
+static int dmar_msi_init(struct irq_domain *domain,
+			 struct msi_domain_info *info, unsigned int virq,
+			 irq_hw_number_t hwirq, msi_alloc_info_t *arg)
 {
-	BUG_ON(nr_irqs > 1);
-	irq_domain_free_irqs_top(domain, virq, nr_irqs);
-}
+	irq_domain_set_info(domain, virq, arg->dmar_id, info->chip, NULL,
+			    handle_edge_irq, arg->dmar_data, "edge");
 
-static void dmar_domain_activate(struct irq_domain *domain,
-				 struct irq_data *irq_data)
-{
-	struct msi_msg msg;
-
-	BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
-	dmar_msi_write(irq_data->irq, &msg);
+	return 0;
 }
 
-static void dmar_domain_deactivate(struct irq_domain *domain,
-				   struct irq_data *irq_data)
-{
-	struct msi_msg msg;
-
-	memset(&msg, 0, sizeof(msg));
-	dmar_msi_write(irq_data->irq, &msg);
-}
+static struct msi_domain_ops dmar_msi_domain_ops = {
+	.get_hwirq	= dmar_msi_get_hwirq,
+	.msi_init	= dmar_msi_init,
+};
 
-static struct irq_domain_ops dmar_domain_ops = {
-	.alloc = dmar_domain_alloc,
-	.free = dmar_domain_free,
-	.activate = dmar_domain_activate,
-	.deactivate = dmar_domain_deactivate,
+static struct msi_domain_info dmar_msi_domain_info = {
+	.ops		= &dmar_msi_domain_ops,
+	.chip		= &dmar_msi_controller,
 };
 
 static struct irq_domain *dmar_get_irq_domain(void)
@@ -271,11 +220,9 @@ static struct irq_domain *dmar_get_irq_domain(void)
 	static DEFINE_MUTEX(dmar_lock);
 
 	mutex_lock(&dmar_lock);
-	if (dmar_domain == NULL) {
-		dmar_domain = irq_domain_add_tree(NULL, &dmar_domain_ops, NULL);
-		if (dmar_domain)
-			dmar_domain->parent = x86_vector_domain;
-	}
+	if (dmar_domain == NULL)
+		dmar_domain = msi_create_irq_domain(NULL, &dmar_msi_domain_info,
+						    x86_vector_domain);
 	mutex_unlock(&dmar_lock);
 
 	return dmar_domain;
@@ -309,23 +256,9 @@ void dmar_free_hwirq(int irq)
 #ifdef CONFIG_HPET_TIMER
 static inline int hpet_dev_id(struct irq_domain *domain)
 {
-	return (int)(long)domain->host_data;
-}
+	struct msi_domain_info *info = msi_get_domain_info(domain);
 
-static int hpet_msi_set_affinity(struct irq_data *data,
-				 const struct cpumask *mask, bool force)
-{
-	struct irq_data *parent = data->parent_data;
-	struct msi_msg msg;
-	int ret;
-
-	ret = parent->chip->irq_set_affinity(parent, mask, force);
-	if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
-		irq_chip_compose_msi_msg(data, &msg);
-		hpet_msi_write(data->handler_data, &msg);
-	}
-
-	return ret;
+	return (int)(long)info->data;
 }
 
 static void hpet_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
@@ -338,79 +271,63 @@ static struct irq_chip hpet_msi_controller = {
 	.irq_unmask = hpet_msi_unmask,
 	.irq_mask = hpet_msi_mask,
 	.irq_ack = irq_chip_ack_parent,
-	.irq_set_affinity = hpet_msi_set_affinity,
+	.irq_set_affinity = msi_domain_set_affinity,
 	.irq_retrigger = irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg = irq_msi_compose_msg,
 	.irq_write_msi_msg = hpet_msi_write_msg,
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
-static int hpet_domain_alloc(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs, void *arg)
-{
-	struct irq_alloc_info *info = arg;
-	int ret;
-
-	if (nr_irqs > 1 || !info || info->type != X86_IRQ_ALLOC_TYPE_HPET)
-		return -EINVAL;
-	if (irq_find_mapping(domain, info->hpet_index)) {
-		pr_warn("IRQ for HPET%d already exists.\n", info->hpet_index);
-		return -EEXIST;
-	}
-
-	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
-	if (ret >= 0) {
-		irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
-		irq_domain_set_hwirq_and_chip(domain, virq, info->hpet_index,
-					      &hpet_msi_controller, NULL);
-		irq_set_handler_data(virq, info->hpet_data);
-		__irq_set_handler(virq, handle_edge_irq, 0, "edge");
-	}
-
-	return ret;
-}
-
-static void hpet_domain_free(struct irq_domain *domain, unsigned int virq,
-			     unsigned int nr_irqs)
+static irq_hw_number_t hpet_msi_get_hwirq(struct msi_domain_info *info,
+					  msi_alloc_info_t *arg)
 {
-	BUG_ON(nr_irqs > 1);
-	irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
-	irq_domain_free_irqs_top(domain, virq, nr_irqs);
+	return arg->hpet_index;
 }
 
-static void hpet_domain_activate(struct irq_domain *domain,
-				struct irq_data *irq_data)
+static int hpet_msi_init(struct irq_domain *domain,
+			 struct msi_domain_info *info, unsigned int virq,
+			 irq_hw_number_t hwirq, msi_alloc_info_t *arg)
 {
-	struct msi_msg msg;
+	irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
+	irq_domain_set_info(domain, virq, arg->hpet_index, info->chip, NULL,
+			    handle_edge_irq, arg->hpet_data, "edge");
 
-	BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
-	hpet_msi_write(irq_get_handler_data(irq_data->irq), &msg);
+	return 0;
 }
 
-static void hpet_domain_deactivate(struct irq_domain *domain,
-				  struct irq_data *irq_data)
+static void hpet_msi_free(struct irq_domain *domain,
+			  struct msi_domain_info *info, unsigned int virq)
 {
-	struct msi_msg msg;
-
-	memset(&msg, 0, sizeof(msg));
-	hpet_msi_write(irq_get_handler_data(irq_data->irq), &msg);
+	irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
 }
 
-static struct irq_domain_ops hpet_domain_ops = {
-	.alloc = hpet_domain_alloc,
-	.free = hpet_domain_free,
-	.activate = hpet_domain_activate,
-	.deactivate = hpet_domain_deactivate,
+static struct msi_domain_ops hpet_msi_domain_ops = {
+	.get_hwirq	= hpet_msi_get_hwirq,
+	.msi_init	= hpet_msi_init,
+	.msi_free	= hpet_msi_free,
+};
+
+static struct msi_domain_info hpet_msi_domain_info = {
+	.ops		= &hpet_msi_domain_ops,
+	.chip		= &hpet_msi_controller,
 };
 
 struct irq_domain *hpet_create_irq_domain(int hpet_id)
 {
 	struct irq_domain *parent;
 	struct irq_alloc_info info;
+	struct msi_domain_info *domain_info;
 
 	if (x86_vector_domain == NULL)
 		return NULL;
 
+	domain_info = kzalloc(sizeof(*domain_info), GFP_KERNEL);
+	if (!domain_info)
+		return NULL;
+
+	*domain_info = hpet_msi_domain_info;
+	domain_info->data = (void *)(long)hpet_id;
+
 	init_irq_alloc_info(&info, NULL);
 	info.type = X86_IRQ_ALLOC_TYPE_HPET;
 	info.hpet_id = hpet_id;
@@ -420,8 +337,7 @@ struct irq_domain *hpet_create_irq_domain(int hpet_id)
 	else
 		hpet_msi_controller.name = "IR-HPET-MSI";
 
-	return irq_domain_add_hierarchy(parent, 0, 0, NULL, &hpet_domain_ops,
-					(void *)(long)hpet_id);
+	return msi_create_irq_domain(NULL, domain_info, parent);
 }
 
 int hpet_assign_irq(struct irq_domain *domain, struct hpet_dev *dev,
author
#53 lore raw

PATCH v8 28/37 irq_remapping: Kill unused function irq_remapping_print_chip()

In reply to Jiang Liu

Now there's no user of irq_remapping_print_chip(), so kill it.

---
 arch/x86/include/asm/irq_remapping.h |    2 --
 drivers/iommu/irq_remapping.c        |   13 -------------
 2 files changed, 15 deletions(-)
arch/x86/include/asm/irq_remapping.h +0 -2
index bacac1052262..52e1a1f337b2 100644
@@ -59,7 +59,6 @@ extern struct irq_domain *
 irq_remapping_get_ir_irq_domain(struct irq_alloc_info *info);
 extern struct irq_domain *
 irq_remapping_get_irq_domain(struct irq_alloc_info *info);
-extern void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p);
 
 /* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */
 extern struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent);
@@ -115,6 +114,5 @@ irq_remapping_get_irq_domain(struct irq_alloc_info *info)
 	return NULL;
 }
 
-#define	irq_remapping_print_chip	NULL
 #endif /* CONFIG_IRQ_REMAP */
 #endif /* __X86_IRQ_REMAPPING_H */
drivers/iommu/irq_remapping.c +0 -13
index 3eaa822c30a9..558c804dbe11 100644
@@ -204,19 +204,6 @@ static void ir_ack_apic_level(struct irq_data *data)
 	eoi_ioapic_irq(data->irq, irqd_cfg(data));
 }
 
-void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p)
-{
-	/*
-	 * Assume interrupt is remapped if the parent irqdomain isn't the
-	 * vector domain, which is true for MSI, HPET and IOAPIC on x86
-	 * platforms.
-	 */
-	if (data->domain && data->domain->parent != arch_get_ir_parent_domain())
-		seq_printf(p, " IR-%s", data->chip->name);
-	else
-		seq_printf(p, " %s", data->chip->name);
-}
-
 static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
 {
 	seq_printf(p, " IR-%s", data->chip->name);
Signature · 1 line
1.7.10.4
#54 lore raw

[tip:x86/apic] irq_remapping: Remove unused function irq_remapping_print_chip()

irq_remapping: Remove unused function irq_remapping_print_chip()
Commit-ID:  0cddfc79462423bf86cbe34560bad07f4a25ded6
Gitweb:     http://git.kernel.org/tip/0cddfc79462423bf86cbe34560bad07f4a25ded6
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:50 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:50 +0200

irq_remapping: Remove unused function irq_remapping_print_chip()

Now there's no user of irq_remapping_print_chip() anymore, so remove it.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 arch/x86/include/asm/irq_remapping.h |  2 --
 drivers/iommu/irq_remapping.c        | 13 -------------
 2 files changed, 15 deletions(-)
arch/x86/include/asm/irq_remapping.h +0 -2
index bacac10..52e1a1f 100644
@@ -59,7 +59,6 @@ extern struct irq_domain *
 irq_remapping_get_ir_irq_domain(struct irq_alloc_info *info);
 extern struct irq_domain *
 irq_remapping_get_irq_domain(struct irq_alloc_info *info);
-extern void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p);
 
 /* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */
 extern struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent);
@@ -115,6 +114,5 @@ irq_remapping_get_irq_domain(struct irq_alloc_info *info)
 	return NULL;
 }
 
-#define	irq_remapping_print_chip	NULL
 #endif /* CONFIG_IRQ_REMAP */
 #endif /* __X86_IRQ_REMAPPING_H */
drivers/iommu/irq_remapping.c +0 -13
index 3eaa822..558c804 100644
@@ -204,19 +204,6 @@ static void ir_ack_apic_level(struct irq_data *data)
 	eoi_ioapic_irq(data->irq, irqd_cfg(data));
 }
 
-void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p)
-{
-	/*
-	 * Assume interrupt is remapped if the parent irqdomain isn't the
-	 * vector domain, which is true for MSI, HPET and IOAPIC on x86
-	 * platforms.
-	 */
-	if (data->domain && data->domain->parent != arch_get_ir_parent_domain())
-		seq_printf(p, " IR-%s", data->chip->name);
-	else
-		seq_printf(p, " %s", data->chip->name);
-}
-
 static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
 {
 	seq_printf(p, " IR-%s", data->chip->name);
author
#55 lore raw

PATCH v8 29/37 x86/intel-mid: Delay initialization of APB timer

In reply to Jiang Liu

From: Thomas Gleixner <[email protected]>

MID has no PIC, but depending on the platform it requires the abt_timer, which is connected to irq0. The timer is set up at late_time_init().

But, looking at the MID code it seems, that there is no reason to do so. The only code which might need the timer working is the TSC calibration code, but thats a non issue on MID as that is using its own empty calibration function. And check_timer() is not invoked either because MID has no PIC and therefor no legacy irqs.

So if you look at intel_mid_time_init() then you'll see that in the ARAT case the timer setup is skipped already. So until the point where x86_init.timers.setup_percpu_clockev() is called for the boot cpu nothing really needs a timer on MID.

According to the MID code the apbt horror is only used for moorestown. Medfield and later use the local apic timer without the apbt nonsense.

The best thing we can do is to drop moorestown support and get rid of that apbt nonsense alltogether.

I don't think anyone deeply cares about it not being supported from 3.18 on. The number of devices which sport a moorestown should be pretty limited and the only relevant use case of those is to act as a pocket heater with short battery life time. Its pretty pointless to update kernels on pocket heaters except for bragging reasons.

If someone at Intel really thinks that we need to keep moorestown alive for other than documentary and sentimental reasons, then we can move the apbt setup to x86_init.timers.setup_percpu_clockev(). At that point the IOAPIC is setup already, so it should just work.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Cohen <[email protected]>
Cc Kuppuswamy Sathyanarayanan <[email protected]>
---
 arch/x86/kernel/apb_timer.c             |    4 ----
 arch/x86/platform/intel-mid/intel-mid.c |   18 +++++++++++++-----
 arch/x86/platform/intel-mid/sfi.c       |    2 --
 3 files changed, 13 insertions(+), 11 deletions(-)
arch/x86/kernel/apb_timer.c +0 -4
index 6a7c23ff21d3..ede92c3364d3 100644
@@ -171,10 +171,6 @@ static int __init apbt_clockevent_register(void)
 
 static void apbt_setup_irq(struct apbt_dev *adev)
 {
-	/* timer0 irq has been setup early */
-	if (adev->irq == 0)
-		return;
-
 	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
 	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
 }
arch/x86/platform/intel-mid/intel-mid.c +13 -5
index 3005f0c89f2e..01d54ea766c1 100644
@@ -81,26 +81,34 @@ static unsigned long __init intel_mid_calibrate_tsc(void)
 	return 0;
 }
 
+static void __init intel_mid_setup_bp_timer(void)
+{
+	apbt_time_init();
+	setup_boot_APIC_clock();
+}
+
 static void __init intel_mid_time_init(void)
 {
 	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
+
 	switch (intel_mid_timer_options) {
 	case INTEL_MID_TIMER_APBT_ONLY:
 		break;
 	case INTEL_MID_TIMER_LAPIC_APBT:
-		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
+		/* Use apbt and local apic */
+		x86_init.timers.setup_percpu_clockev = intel_mid_setup_bp_timer;
 		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
-		break;
+		return;
 	default:
 		if (!boot_cpu_has(X86_FEATURE_ARAT))
 			break;
+		/* Lapic only, no apbt */
 		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
 		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
 		return;
 	}
-	/* we need at least one APB timer */
-	pre_init_apic_IRQ0();
-	apbt_time_init();
+
+	x86_init.timers.setup_percpu_clockev = apbt_time_init;
 }
 
 static void intel_mid_arch_setup(void)
arch/x86/platform/intel-mid/sfi.c +0 -2
index c14ad34776c4..aa59f88868f8 100644
@@ -95,8 +95,6 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 		pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n",
 			totallen, (u32)pentry->phys_addr,
 			pentry->freq_hz, pentry->irq);
-			if (!pentry->irq)
-				continue;
 			mp_irq.type = MP_INTSRC;
 			mp_irq.irqtype = mp_INT;
 /* triggering mode edge bit 2-3, active high polarity bit 0-1 */
Signature · 1 line
1.7.10.4
#56 lore raw

[tip:x86/apic] x86/intel-mid: Delay initialization of APB timer

x86/intel-mid: Delay initialization of APB timer
Commit-ID:  6648d1b42c349d748839d7bad91cc8a65c73e262
Gitweb:     http://git.kernel.org/tip/6648d1b42c349d748839d7bad91cc8a65c73e262
Author:     Thomas Gleixner <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:51 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/intel-mid: Delay initialization of APB timer

MID has no PIC, but depending on the platform it requires the abt_timer, which is connected to irq0. The timer is set up at late_time_init().

But, looking at the MID code it seems, that there is no reason to do so. The only code which might need the timer working is the TSC calibration code, but thats a non issue on MID as that is using its own empty calibration function. And check_timer() is not invoked either because MID has no PIC and therefor no legacy irqs.

So if you look at intel_mid_time_init() then you'll see that in the ARAT case the timer setup is skipped already. So until the point where x86_init.timers.setup_percpu_clockev() is called for the boot cpu nothing really needs a timer on MID.

According to the MID code the apbt horror is only used for moorestown. Medfield and later use the local apic timer without the apbt nonsense.

The best thing we can do is to drop moorestown support and get rid of that apbt nonsense alltogether.

I don't think anyone deeply cares about it not being supported from 3.18 on. The number of devices which sport a moorestown should be pretty limited and the only relevant use case of those is to act as a pocket heater with short battery life time. Its pretty pointless to update kernels on pocket heaters except for bragging reasons.

If someone at Intel really thinks that we need to keep moorestown alive for other than documentary and sentimental reasons, then we can move the apbt setup to x86_init.timers.setup_percpu_clockev(). At that point the IOAPIC is setup already, so it should just work.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Kuppuswamy Sathyanarayanan <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Rickard Strandqvist <[email protected]>
---
 arch/x86/kernel/apb_timer.c             |  4 ----
 arch/x86/platform/intel-mid/intel-mid.c | 18 +++++++++++++-----
 arch/x86/platform/intel-mid/sfi.c       |  2 --
 3 files changed, 13 insertions(+), 11 deletions(-)
arch/x86/kernel/apb_timer.c +0 -4
index 6a7c23f..ede92c3 100644
@@ -171,10 +171,6 @@ static int __init apbt_clockevent_register(void)
 
 static void apbt_setup_irq(struct apbt_dev *adev)
 {
-	/* timer0 irq has been setup early */
-	if (adev->irq == 0)
-		return;
-
 	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
 	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
 }
arch/x86/platform/intel-mid/intel-mid.c +13 -5
index 3005f0c..01d54ea 100644
@@ -81,26 +81,34 @@ static unsigned long __init intel_mid_calibrate_tsc(void)
 	return 0;
 }
 
+static void __init intel_mid_setup_bp_timer(void)
+{
+	apbt_time_init();
+	setup_boot_APIC_clock();
+}
+
 static void __init intel_mid_time_init(void)
 {
 	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
+
 	switch (intel_mid_timer_options) {
 	case INTEL_MID_TIMER_APBT_ONLY:
 		break;
 	case INTEL_MID_TIMER_LAPIC_APBT:
-		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
+		/* Use apbt and local apic */
+		x86_init.timers.setup_percpu_clockev = intel_mid_setup_bp_timer;
 		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
-		break;
+		return;
 	default:
 		if (!boot_cpu_has(X86_FEATURE_ARAT))
 			break;
+		/* Lapic only, no apbt */
 		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
 		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
 		return;
 	}
-	/* we need at least one APB timer */
-	pre_init_apic_IRQ0();
-	apbt_time_init();
+
+	x86_init.timers.setup_percpu_clockev = apbt_time_init;
 }
 
 static void intel_mid_arch_setup(void)
arch/x86/platform/intel-mid/sfi.c +0 -2
index c14ad34..aa59f88 100644
@@ -95,8 +95,6 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 		pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n",
 			totallen, (u32)pentry->phys_addr,
 			pentry->freq_hz, pentry->irq);
-			if (!pentry->irq)
-				continue;
 			mp_irq.type = MP_INTSRC;
 			mp_irq.irqtype = mp_INT;
 /* triggering mode edge bit 2-3, active high polarity bit 0-1 */
author
#57 lore raw

PATCH v8 30/37 x86/intel-mid, trivial: Refine code syntax for sfi_parse_mtmr()

In reply to Jiang Liu

Correctly indent code in function sfi_parse_mtmr().

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Jiri Kosina <[email protected]>
Cc David Cohen <[email protected]>
---
 arch/x86/platform/intel-mid/sfi.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
arch/x86/platform/intel-mid/sfi.c +10 -10
index aa59f88868f8..9a16749935d4 100644
@@ -95,16 +95,16 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 		pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n",
 			totallen, (u32)pentry->phys_addr,
 			pentry->freq_hz, pentry->irq);
-			mp_irq.type = MP_INTSRC;
-			mp_irq.irqtype = mp_INT;
-/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
-			mp_irq.irqflag = 5;
-			mp_irq.srcbus = MP_BUS_ISA;
-			mp_irq.srcbusirq = pentry->irq;	/* IRQ */
-			mp_irq.dstapic = MP_APIC_ALL;
-			mp_irq.dstirq = pentry->irq;
-			mp_save_irq(&mp_irq);
-			mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
+		mp_irq.type = MP_INTSRC;
+		mp_irq.irqtype = mp_INT;
+		/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
+		mp_irq.irqflag = 5;
+		mp_irq.srcbus = MP_BUS_ISA;
+		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
+		mp_irq.dstapic = MP_APIC_ALL;
+		mp_irq.dstirq = pentry->irq;
+		mp_save_irq(&mp_irq);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 
 	return 0;
Signature · 1 line
1.7.10.4
#58 lore raw

[tip:x86/apic] x86/intel-mid, trivial: Refine code syntax for sfi_parse_mtmr()

x86/intel-mid, trivial: Refine code syntax for sfi_parse_mtmr()
Commit-ID:  b0415817cb7960f408da51e6fedecc6a19e2b895
Gitweb:     http://git.kernel.org/tip/b0415817cb7960f408da51e6fedecc6a19e2b895
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:52 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/intel-mid, trivial: Refine code syntax for sfi_parse_mtmr()

Correctly indent code in function sfi_parse_mtmr().

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Jiri Kosina <[email protected]>
---
 arch/x86/platform/intel-mid/sfi.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
arch/x86/platform/intel-mid/sfi.c +10 -10
index aa59f88..9a16749 100644
@@ -95,16 +95,16 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 		pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n",
 			totallen, (u32)pentry->phys_addr,
 			pentry->freq_hz, pentry->irq);
-			mp_irq.type = MP_INTSRC;
-			mp_irq.irqtype = mp_INT;
-/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
-			mp_irq.irqflag = 5;
-			mp_irq.srcbus = MP_BUS_ISA;
-			mp_irq.srcbusirq = pentry->irq;	/* IRQ */
-			mp_irq.dstapic = MP_APIC_ALL;
-			mp_irq.dstirq = pentry->irq;
-			mp_save_irq(&mp_irq);
-			mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
+		mp_irq.type = MP_INTSRC;
+		mp_irq.irqtype = mp_INT;
+		/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
+		mp_irq.irqflag = 5;
+		mp_irq.srcbus = MP_BUS_ISA;
+		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
+		mp_irq.dstapic = MP_APIC_ALL;
+		mp_irq.dstirq = pentry->irq;
+		mp_save_irq(&mp_irq);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 
 	return 0;
author
#59 lore raw

PATCH v8 31/37 x86/irq: Kill unused pre_init_apic_IRQ0()

In reply to Jiang Liu

Now there's no user of pre_init_apic_IRQ0(), so kill it.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/include/asm/io_apic.h |    1 -
 arch/x86/kernel/apic/io_apic.c |   17 -----------------
 2 files changed, 18 deletions(-)
arch/x86/include/asm/io_apic.h +0 -1
index 2f91685fe1cd..c976de126a91 100644
@@ -204,7 +204,6 @@ extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
 extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
-extern void __init pre_init_apic_IRQ0(void);
 
 extern void mp_save_irq(struct mpc_intsrc *m);
 
arch/x86/kernel/apic/io_apic.c +0 -17
index 56d532106ef3..540598c77e55 100644
@@ -3091,20 +3091,3 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
 
 	return ret;
 }
-
-/* Enable IOAPIC early just for system timer */
-void __init pre_init_apic_IRQ0(void)
-{
-	struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
-
-	printk(KERN_INFO "Early APIC setup for system timer0\n");
-#ifndef CONFIG_SMP
-	physid_set_mask_of_physid(boot_cpu_physical_apicid,
-					 &phys_cpu_present_map);
-#endif
-	setup_local_APIC();
-
-	io_apic_setup_irq_pin(0, 0, &attr);
-	irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq,
-				      "edge");
-}
Signature · 1 line
1.7.10.4
#60 lore raw

[tip:x86/apic] x86/irq: Remove unused pre_init_apic_IRQ0()

x86/irq: Remove unused pre_init_apic_IRQ0()
Commit-ID:  4e69d7eab4c24aa88fb0ec99fad7feac254d9ece
Gitweb:     http://git.kernel.org/tip/4e69d7eab4c24aa88fb0ec99fad7feac254d9ece
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:53 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/irq: Remove unused pre_init_apic_IRQ0()

Now there's no user of pre_init_apic_IRQ0(), so remove it.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Jan Beulich <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  1 -
 arch/x86/kernel/apic/io_apic.c | 17 -----------------
 2 files changed, 18 deletions(-)
arch/x86/include/asm/io_apic.h +0 -1
index 2f91685..c976de1 100644
@@ -204,7 +204,6 @@ extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
 extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
-extern void __init pre_init_apic_IRQ0(void);
 
 extern void mp_save_irq(struct mpc_intsrc *m);
 
arch/x86/kernel/apic/io_apic.c +0 -17
index 56d5321..540598c 100644
@@ -3091,20 +3091,3 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
 
 	return ret;
 }
-
-/* Enable IOAPIC early just for system timer */
-void __init pre_init_apic_IRQ0(void)
-{
-	struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
-
-	printk(KERN_INFO "Early APIC setup for system timer0\n");
-#ifndef CONFIG_SMP
-	physid_set_mask_of_physid(boot_cpu_physical_apicid,
-					 &phys_cpu_present_map);
-#endif
-	setup_local_APIC();
-
-	io_apic_setup_irq_pin(0, 0, &attr);
-	irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq,
-				      "edge");
-}
author
#61 lore raw

PATCH v8 32/37 x86/irq: Prepare IOAPIC interfaces to support hierarchy irqdomain

In reply to Jiang Liu

Introduce helper functions to manipulate struct irq_alloc_info for IOAPIC. Also add extra parameter to IOAPIC interfaces to prepare for hierarchy irqdomain. Function mp_set_gsi_attr() will be killed once we have switched to hierarchy irqdomain.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Grant Likely <[email protected]>
Cc David Cohen <[email protected]>
---
 arch/x86/include/asm/io_apic.h                     |   14 ++++++-
 arch/x86/kernel/acpi/boot.c                        |    6 ++-
 arch/x86/kernel/apic/io_apic.c                     |   39 +++++++++++++-------
 arch/x86/pci/intel_mid_pci.c                       |    4 +-
 .../platform/intel-mid/device_libs/platform_wdt.c  |    4 +-
 arch/x86/platform/intel-mid/sfi.c                  |    9 +++--
 6 files changed, 54 insertions(+), 22 deletions(-)
arch/x86/include/asm/io_apic.h +12 -2
index c976de126a91..1fbeda50a77d 100644
@@ -95,6 +95,8 @@ struct IR_IO_APIC_route_entry {
 		index		: 15;
 } __attribute__ ((packed));
 
+struct irq_alloc_info;
+
 #define IOAPIC_AUTO     -1
 #define IOAPIC_EDGE     0
 #define IOAPIC_LEVEL    1
@@ -194,7 +196,8 @@ extern u32 gsi_top;
 extern int mp_find_ioapic(u32 gsi);
 extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
-extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
+extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
+			     struct irq_alloc_info *info);
 extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
@@ -203,6 +206,8 @@ extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
+extern void ioapic_set_alloc_attr(struct irq_alloc_info *info,
+				  int node, int trigger, int polarity);
 extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
 
 extern void mp_save_irq(struct mpc_intsrc *m);
@@ -253,7 +258,12 @@ static inline void print_IO_APICs(void) {}
 #define gsi_top (NR_IRQS_LEGACY)
 static inline int mp_find_ioapic(u32 gsi) { return 0; }
 static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
-static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
+static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
+				    struct irq_alloc_info *info)
+{
+	return gsi;
+}
+
 static inline void mp_unmap_irq(int irq) { }
 
 static inline int save_ioapic_entries(void)
arch/x86/kernel/acpi/boot.c +4 -2
index 803b684676ff..a43a4d3c60e1 100644
@@ -404,6 +404,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 			   int polarity)
 {
 	int irq, node;
+	struct irq_alloc_info info;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -416,7 +417,8 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 		return -1;
 	}
 
-	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
+	ioapic_set_alloc_attr(&info, node, trigger, polarity);
+	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info);
 	if (irq < 0)
 		return irq;
 
@@ -434,7 +436,7 @@ static void mp_unregister_gsi(u32 gsi)
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return;
 
-	irq = mp_map_gsi_to_irq(gsi, 0);
+	irq = mp_map_gsi_to_irq(gsi, 0, NULL);
 	if (irq > 0)
 		mp_unmap_irq(irq);
 }
arch/x86/kernel/apic/io_apic.c +26 -13
index 540598c77e55..5c953bb96ecf 100644
@@ -938,7 +938,19 @@ static int irq_trigger(int idx)
 	return trigger;
 }
 
-static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
+void ioapic_set_alloc_attr(struct irq_alloc_info *info, int node,
+			   int trigger, int polarity)
+{
+	init_irq_alloc_info(info, NULL);
+	info->type = X86_IRQ_ALLOC_TYPE_IOAPIC;
+	info->ioapic_node = node;
+	info->ioapic_trigger = trigger;
+	info->ioapic_polarity = polarity;
+	info->ioapic_valid = 1;
+}
+
+static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin,
+				 struct irq_alloc_info *info)
 {
 	int irq = -1;
 	int ioapic = (int)(long)domain->host_data;
@@ -971,11 +983,11 @@ static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
 }
 
 static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
-			     unsigned int flags)
+			     unsigned int flags, struct irq_alloc_info *info)
 {
 	int irq;
 	struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
-	struct mp_pin_info *info = mp_pin_info(ioapic, pin);
+	struct mp_pin_info *pinfo = mp_pin_info(ioapic, pin);
 
 	if (!domain)
 		return -1;
@@ -997,30 +1009,30 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
 	if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 		if (flags & IOAPIC_MAP_ALLOC) {
-			if (info->count == 0 &&
+			if (pinfo->count == 0 &&
 			    mp_irqdomain_map(domain, irq, pin) != 0)
 				irq = -1;
 
 			/* special handling for timer IRQ0 */
 			if (irq == 0)
-				info->count++;
+				pinfo->count++;
 		}
 	} else {
 		irq = irq_find_mapping(domain, pin);
 		if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC))
-			irq = alloc_irq_from_domain(domain, gsi, pin);
+			irq = alloc_irq_from_domain(domain, gsi, pin, info);
 	}
 
 	if (flags & IOAPIC_MAP_ALLOC) {
 		/* special handling for legacy IRQs */
-		if (irq < nr_legacy_irqs() && info->count == 1 &&
+		if (irq < nr_legacy_irqs() && pinfo->count == 1 &&
 		    mp_irqdomain_map(domain, irq, pin) != 0)
 			irq = -1;
 
 		if (irq > 0)
-			info->count++;
-		else if (info->count == 0)
-			info->set = 0;
+			pinfo->count++;
+		else if (pinfo->count == 0)
+			pinfo->set = 0;
 	}
 
 	mutex_unlock(&ioapic_mutex);
@@ -1058,10 +1070,11 @@ static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
 	}
 #endif
 
-	return  mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+	return  mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags, NULL);
 }
 
-int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
+int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
+		      struct irq_alloc_info *info)
 {
 	int ioapic, pin, idx;
 
@@ -1074,7 +1087,7 @@ int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
 	if ((flags & IOAPIC_MAP_CHECK) && idx < 0)
 		return -1;
 
-	return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+	return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags, info);
 }
 
 void mp_unmap_irq(int irq)
arch/x86/pci/intel_mid_pci.c +3 -1
index 852aa4c92da0..57b5719b617b 100644
@@ -208,6 +208,7 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 
 static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 {
+	struct irq_alloc_info info;
 	int polarity;
 
 	if (dev->irq_managed && dev->irq > 0)
@@ -217,6 +218,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 		polarity = 0; /* active high */
 	else
 		polarity = 1; /* active low */
+	ioapic_set_alloc_attr(&info, dev_to_node(&dev->dev), 1, polarity);
 
 	/*
 	 * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
@@ -224,7 +226,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 	 */
 	if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
 		return -EBUSY;
-	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
+	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC, &info) < 0)
 		return -EBUSY;
 
 	dev->irq_managed = 1;
arch/x86/platform/intel-mid/device_libs/platform_wdt.c +3 -1
index 0b283d4d0ad7..de0009f6d555 100644
@@ -27,6 +27,7 @@ static struct platform_device wdt_dev = {
 static int tangier_probe(struct platform_device *pdev)
 {
 	int gsi;
+	struct irq_alloc_info info;
 	struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
 
 	if (!pdata)
@@ -34,8 +35,9 @@ static int tangier_probe(struct platform_device *pdev)
 
 	/* IOAPIC builds identity mapping between GSI and IRQ on MID */
 	gsi = pdata->irq;
+	ioapic_set_alloc_attr(&info, cpu_to_node(0), 1, 0);
 	if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
-	    mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
+	    mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info) <= 0) {
 		dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
 			 gsi);
 		return -EINVAL;
arch/x86/platform/intel-mid/sfi.c +6 -3
index 9a16749935d4..7d17355d820e 100644
@@ -104,7 +104,7 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
 		mp_save_irq(&mp_irq);
-		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC, NULL);
 	}
 
 	return 0;
@@ -175,7 +175,7 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
 		mp_save_irq(&mp_irq);
-		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC, NULL);
 	}
 	return 0;
 }
@@ -434,6 +434,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 	struct devs_id *dev = NULL;
 	int num, i, ret;
 	int polarity;
+	struct irq_alloc_info info;
 
 	sb = (struct sfi_table_simple *)table;
 	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
@@ -467,9 +468,11 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 				polarity = 1;
 			}
 
+			ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, polarity);
 			ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
 			if (ret == 0)
-				ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC);
+				ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC,
+							&info);
 			WARN_ON(ret < 0);
 		}
 
Signature · 1 line
1.7.10.4
#62 lore raw

[tip:x86/apic] x86/irq: Prepare IOAPIC interfaces to support hierarchical irqdomains

x86/irq: Prepare IOAPIC interfaces to support hierarchical irqdomains
Commit-ID:  c4d05a2c354b15965c9b2a5f46016a5d9f43e224
Gitweb:     http://git.kernel.org/tip/c4d05a2c354b15965c9b2a5f46016a5d9f43e224
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:54 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/irq: Prepare IOAPIC interfaces to support hierarchical irqdomains

Introduce helper functions to manipulate struct irq_alloc_info for IOAPIC. Also add an extra parameter to IOAPIC interfaces to prepare for hierarchical irqdomain. Function mp_set_gsi_attr() will be removed once we have switched to hierarchical irqdomains.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Jan Beulich <[email protected]>
Cc Grant Likely <[email protected]>
Cc David Cohen <[email protected]>
---
 arch/x86/include/asm/io_apic.h                     | 14 ++++++--
 arch/x86/kernel/acpi/boot.c                        |  6 ++--
 arch/x86/kernel/apic/io_apic.c                     | 39 ++++++++++++++--------
 arch/x86/pci/intel_mid_pci.c                       |  4 ++-
 .../platform/intel-mid/device_libs/platform_wdt.c  |  4 ++-
 arch/x86/platform/intel-mid/sfi.c                  |  9 +++--
 6 files changed, 54 insertions(+), 22 deletions(-)
arch/x86/include/asm/io_apic.h +12 -2
index c976de1..1fbeda5 100644
@@ -95,6 +95,8 @@ struct IR_IO_APIC_route_entry {
 		index		: 15;
 } __attribute__ ((packed));
 
+struct irq_alloc_info;
+
 #define IOAPIC_AUTO     -1
 #define IOAPIC_EDGE     0
 #define IOAPIC_LEVEL    1
@@ -194,7 +196,8 @@ extern u32 gsi_top;
 extern int mp_find_ioapic(u32 gsi);
 extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
-extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
+extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
+			     struct irq_alloc_info *info);
 extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
@@ -203,6 +206,8 @@ extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
+extern void ioapic_set_alloc_attr(struct irq_alloc_info *info,
+				  int node, int trigger, int polarity);
 extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
 
 extern void mp_save_irq(struct mpc_intsrc *m);
@@ -253,7 +258,12 @@ static inline void print_IO_APICs(void) {}
 #define gsi_top (NR_IRQS_LEGACY)
 static inline int mp_find_ioapic(u32 gsi) { return 0; }
 static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
-static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
+static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
+				    struct irq_alloc_info *info)
+{
+	return gsi;
+}
+
 static inline void mp_unmap_irq(int irq) { }
 
 static inline int save_ioapic_entries(void)
arch/x86/kernel/acpi/boot.c +4 -2
index 803b684..a43a4d3 100644
@@ -404,6 +404,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 			   int polarity)
 {
 	int irq, node;
+	struct irq_alloc_info info;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -416,7 +417,8 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 		return -1;
 	}
 
-	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
+	ioapic_set_alloc_attr(&info, node, trigger, polarity);
+	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info);
 	if (irq < 0)
 		return irq;
 
@@ -434,7 +436,7 @@ static void mp_unregister_gsi(u32 gsi)
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return;
 
-	irq = mp_map_gsi_to_irq(gsi, 0);
+	irq = mp_map_gsi_to_irq(gsi, 0, NULL);
 	if (irq > 0)
 		mp_unmap_irq(irq);
 }
arch/x86/kernel/apic/io_apic.c +26 -13
index 540598c..5c953bb 100644
@@ -938,7 +938,19 @@ static int irq_trigger(int idx)
 	return trigger;
 }
 
-static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
+void ioapic_set_alloc_attr(struct irq_alloc_info *info, int node,
+			   int trigger, int polarity)
+{
+	init_irq_alloc_info(info, NULL);
+	info->type = X86_IRQ_ALLOC_TYPE_IOAPIC;
+	info->ioapic_node = node;
+	info->ioapic_trigger = trigger;
+	info->ioapic_polarity = polarity;
+	info->ioapic_valid = 1;
+}
+
+static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin,
+				 struct irq_alloc_info *info)
 {
 	int irq = -1;
 	int ioapic = (int)(long)domain->host_data;
@@ -971,11 +983,11 @@ static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
 }
 
 static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
-			     unsigned int flags)
+			     unsigned int flags, struct irq_alloc_info *info)
 {
 	int irq;
 	struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
-	struct mp_pin_info *info = mp_pin_info(ioapic, pin);
+	struct mp_pin_info *pinfo = mp_pin_info(ioapic, pin);
 
 	if (!domain)
 		return -1;
@@ -997,30 +1009,30 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
 	if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 		if (flags & IOAPIC_MAP_ALLOC) {
-			if (info->count == 0 &&
+			if (pinfo->count == 0 &&
 			    mp_irqdomain_map(domain, irq, pin) != 0)
 				irq = -1;
 
 			/* special handling for timer IRQ0 */
 			if (irq == 0)
-				info->count++;
+				pinfo->count++;
 		}
 	} else {
 		irq = irq_find_mapping(domain, pin);
 		if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC))
-			irq = alloc_irq_from_domain(domain, gsi, pin);
+			irq = alloc_irq_from_domain(domain, gsi, pin, info);
 	}
 
 	if (flags & IOAPIC_MAP_ALLOC) {
 		/* special handling for legacy IRQs */
-		if (irq < nr_legacy_irqs() && info->count == 1 &&
+		if (irq < nr_legacy_irqs() && pinfo->count == 1 &&
 		    mp_irqdomain_map(domain, irq, pin) != 0)
 			irq = -1;
 
 		if (irq > 0)
-			info->count++;
-		else if (info->count == 0)
-			info->set = 0;
+			pinfo->count++;
+		else if (pinfo->count == 0)
+			pinfo->set = 0;
 	}
 
 	mutex_unlock(&ioapic_mutex);
@@ -1058,10 +1070,11 @@ static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
 	}
 #endif
 
-	return  mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+	return  mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags, NULL);
 }
 
-int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
+int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
+		      struct irq_alloc_info *info)
 {
 	int ioapic, pin, idx;
 
@@ -1074,7 +1087,7 @@ int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
 	if ((flags & IOAPIC_MAP_CHECK) && idx < 0)
 		return -1;
 
-	return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+	return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags, info);
 }
 
 void mp_unmap_irq(int irq)
arch/x86/pci/intel_mid_pci.c +3 -1
index 852aa4c..57b5719 100644
@@ -208,6 +208,7 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 
 static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 {
+	struct irq_alloc_info info;
 	int polarity;
 
 	if (dev->irq_managed && dev->irq > 0)
@@ -217,6 +218,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 		polarity = 0; /* active high */
 	else
 		polarity = 1; /* active low */
+	ioapic_set_alloc_attr(&info, dev_to_node(&dev->dev), 1, polarity);
 
 	/*
 	 * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
@@ -224,7 +226,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 	 */
 	if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
 		return -EBUSY;
-	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
+	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC, &info) < 0)
 		return -EBUSY;
 
 	dev->irq_managed = 1;
arch/x86/platform/intel-mid/device_libs/platform_wdt.c +3 -1
index 0b283d4..de0009f 100644
@@ -27,6 +27,7 @@ static struct platform_device wdt_dev = {
 static int tangier_probe(struct platform_device *pdev)
 {
 	int gsi;
+	struct irq_alloc_info info;
 	struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
 
 	if (!pdata)
@@ -34,8 +35,9 @@ static int tangier_probe(struct platform_device *pdev)
 
 	/* IOAPIC builds identity mapping between GSI and IRQ on MID */
 	gsi = pdata->irq;
+	ioapic_set_alloc_attr(&info, cpu_to_node(0), 1, 0);
 	if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
-	    mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
+	    mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info) <= 0) {
 		dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
 			 gsi);
 		return -EINVAL;
arch/x86/platform/intel-mid/sfi.c +6 -3
index 9a16749..7d17355 100644
@@ -104,7 +104,7 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
 		mp_save_irq(&mp_irq);
-		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC, NULL);
 	}
 
 	return 0;
@@ -175,7 +175,7 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
 		mp_save_irq(&mp_irq);
-		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC, NULL);
 	}
 	return 0;
 }
@@ -434,6 +434,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 	struct devs_id *dev = NULL;
 	int num, i, ret;
 	int polarity;
+	struct irq_alloc_info info;
 
 	sb = (struct sfi_table_simple *)table;
 	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
@@ -467,9 +468,11 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 				polarity = 1;
 			}
 
+			ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, polarity);
 			ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
 			if (ret == 0)
-				ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC);
+				ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC,
+							&info);
 			WARN_ON(ret < 0);
 		}
 
author
#63 lore raw

PATCH v8 33/37 x86/irq: Implement callbacks to enable hierarchy irqdomain on IOAPICs

In reply to Jiang Liu

Implement required callbacks to prepare for enabling hierarchy irqdomain on IOAPICs. Later we will clean up IOAPIC code a lot by using hierarchy irqdomain framework.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/include/asm/io_apic.h |   10 +++
 arch/x86/kernel/apic/io_apic.c |  159 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 166 insertions(+), 3 deletions(-)
arch/x86/include/asm/io_apic.h +10 -0
index 1fbeda50a77d..ecc192624eaf 100644
@@ -96,6 +96,7 @@ struct IR_IO_APIC_route_entry {
 } __attribute__ ((packed));
 
 struct irq_alloc_info;
+struct irq_data;
 
 #define IOAPIC_AUTO     -1
 #define IOAPIC_EDGE     0
@@ -206,6 +207,15 @@ extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
+extern int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
+			      unsigned int nr_irqs, void *arg);
+extern void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq,
+			      unsigned int nr_irqs);
+extern void mp_irqdomain_activate(struct irq_domain *domain,
+				  struct irq_data *irq_data);
+extern void mp_irqdomain_deactivate(struct irq_domain *domain,
+				    struct irq_data *irq_data);
+extern int mp_irqdomain_ioapic_idx(struct irq_domain *domain);
 extern void ioapic_set_alloc_attr(struct irq_alloc_info *info,
 				  int node, int trigger, int polarity);
 extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
arch/x86/kernel/apic/io_apic.c +156 -3

196 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#64 lore raw

[tip:x86/apic] x86/irq: Implement callbacks to enable hierarchical irqdomains on IOAPICs

x86/irq: Implement callbacks to enable hierarchical irqdomains on IOAPICs
Commit-ID:  49c7e60022912d10da88ba67e8eb2927f1143f6a
Gitweb:     http://git.kernel.org/tip/49c7e60022912d10da88ba67e8eb2927f1143f6a
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:55 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/irq: Implement callbacks to enable hierarchical irqdomains on IOAPICs

Implement required callbacks to prepare for enabling hierarchical irqdomains on IOAPICs. After the conversion we can remove quite some code from the old implementation.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Jan Beulich <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  10 +++
 arch/x86/kernel/apic/io_apic.c | 159 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 166 insertions(+), 3 deletions(-)
arch/x86/include/asm/io_apic.h +10 -0
index 1fbeda5..ecc1926 100644
@@ -96,6 +96,7 @@ struct IR_IO_APIC_route_entry {
 } __attribute__ ((packed));
 
 struct irq_alloc_info;
+struct irq_data;
 
 #define IOAPIC_AUTO     -1
 #define IOAPIC_EDGE     0
@@ -206,6 +207,15 @@ extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
+extern int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
+			      unsigned int nr_irqs, void *arg);
+extern void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq,
+			      unsigned int nr_irqs);
+extern void mp_irqdomain_activate(struct irq_domain *domain,
+				  struct irq_data *irq_data);
+extern void mp_irqdomain_deactivate(struct irq_domain *domain,
+				    struct irq_data *irq_data);
+extern int mp_irqdomain_ioapic_idx(struct irq_domain *domain);
 extern void ioapic_set_alloc_attr(struct irq_alloc_info *info,
 				  int node, int trigger, int polarity);
 extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
arch/x86/kernel/apic/io_apic.c +156 -3

196 lines not on this page · raw message

author
#65 lore raw

PATCH v8 34/37 x86/irq: Refine the way to allocate irq_cfg for legacy IRQs

In reply to Jiang Liu

To support legacy ISA IRQs, we need to preallocate irq_cfg structures for legacy ISA IRQs. Refine the way to allocate irq_cfg for legacy ISA IRQs, so it's more friend to hierarchy irqdomain implementation.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c |   13 +------------
 arch/x86/kernel/apic/vector.c  |   42 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 13 deletions(-)
arch/x86/kernel/apic/io_apic.c +1 -12
index 3406dbec1570..16d4ba3ac844 100644
@@ -254,8 +254,7 @@ static void free_ioapic_saved_registers(int idx)
 
 int __init arch_early_ioapic_init(void)
 {
-	struct irq_cfg *cfg;
-	int i, node = cpu_to_node(0);
+	int i;
 
 	if (!nr_legacy_irqs())
 		io_apic_irqs = ~0UL;
@@ -263,16 +262,6 @@ int __init arch_early_ioapic_init(void)
 	for_each_ioapic(i)
 		alloc_ioapic_saved_registers(i);
 
-	/*
-	 * For legacy IRQ's, start with assigning irq0 to irq15 to
-	 * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
-	 */
-	for (i = 0; i < nr_legacy_irqs(); i++) {
-		cfg = alloc_irq_and_cfg_at(i, node);
-		cfg->vector = IRQ0_VECTOR + i;
-		cpumask_setall(cfg->domain);
-	}
-
 	return 0;
 }
 
arch/x86/kernel/apic/vector.c +41 -1

68 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#66 lore raw

[tip:x86/apic] x86/irq: Refine the way to allocate irq_cfg for legacy IRQs

x86/irq: Refine the way to allocate irq_cfg for legacy IRQs
Commit-ID:  133153205b263ea9ce4e771876ede544f896e034
Gitweb:     http://git.kernel.org/tip/133153205b263ea9ce4e771876ede544f896e034
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:56 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/irq: Refine the way to allocate irq_cfg for legacy IRQs

To support legacy ISA IRQs, we need to preallocate irq_cfg structures for legacy ISA IRQs. Refine the way to allocate irq_cfg for legacy ISA IRQs, so it's more friendly for the hierarchical irqdomain implementation.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c | 13 +------------
 arch/x86/kernel/apic/vector.c  | 42 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 13 deletions(-)
arch/x86/kernel/apic/io_apic.c +1 -12
index 3406dbe..16d4ba3 100644
@@ -254,8 +254,7 @@ static void free_ioapic_saved_registers(int idx)
 
 int __init arch_early_ioapic_init(void)
 {
-	struct irq_cfg *cfg;
-	int i, node = cpu_to_node(0);
+	int i;
 
 	if (!nr_legacy_irqs())
 		io_apic_irqs = ~0UL;
@@ -263,16 +262,6 @@ int __init arch_early_ioapic_init(void)
 	for_each_ioapic(i)
 		alloc_ioapic_saved_registers(i);
 
-	/*
-	 * For legacy IRQ's, start with assigning irq0 to irq15 to
-	 * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
-	 */
-	for (i = 0; i < nr_legacy_irqs(); i++) {
-		cfg = alloc_irq_and_cfg_at(i, node);
-		cfg->vector = IRQ0_VECTOR + i;
-		cpumask_setall(cfg->domain);
-	}
-
 	return 0;
 }
 
arch/x86/kernel/apic/vector.c +41 -1

68 lines not on this page · raw message

author
#67 lore raw

PATCH v8 35/37 x86/irq: Simplify the way to print IOAPIC entry

In reply to Jiang Liu

Simplify the way to print IOAPIC entry content, so we could kill native_io_apic_print_entries(), intel_ir_io_apic_print_entries() and x86_io_apic_ops.print_entries() later.

Folded a patch from Thomas to fix errors in printed pin attributes,
http://www.spinics.net/lists/linux-tip-commits/msg26108.html

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c |   30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/io_apic.c +28 -2
index 16d4ba3ac844..3c6609617306 100644
@@ -1424,6 +1424,33 @@ void ioapic_zap_locks(void)
 	raw_spin_lock_init(&ioapic_lock);
 }
 
+static void io_apic_print_entries(unsigned int apic, unsigned int nr_entries)
+{
+	int i;
+	char buf[256];
+	struct IO_APIC_route_entry entry;
+	struct IR_IO_APIC_route_entry *ir_entry = (void *)&entry;
+
+	printk(KERN_DEBUG "IOAPIC %d:\n", apic);
+	for (i = 0; i <= nr_entries; i++) {
+		entry = ioapic_read_entry(apic, i);
+		snprintf(buf, sizeof(buf),
+			 " pin%02x, %s, %s, %s, V(%02X), IRR(%1d), S(%1d)",
+			 i, entry.mask ? "disabled" : "enabled ",
+			 entry.trigger ? "level" : "edge ",
+			 entry.polarity ? "low " : "high",
+			 entry.vector, entry.irr, entry.delivery_status);
+		if (ir_entry->format)
+			printk(KERN_DEBUG "%s, remapped, I(%04X),  Z(%X)\n",
+			       buf, (ir_entry->index << 15) | ir_entry->index,
+			       ir_entry->zero);
+		else
+			printk(KERN_DEBUG "%s, %s, D(%02X), M(%1d)\n",
+			       buf, entry.dest_mode ? "logical " : "physical",
+			       entry.dest, entry.delivery_mode);
+	}
+}
+
 static void __init print_IO_APIC(int ioapic_idx)
 {
 	union IO_APIC_reg_00 reg_00;
@@ -1477,8 +1504,7 @@ static void __init print_IO_APIC(int ioapic_idx)
 	}
 
 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
-
-	x86_io_apic_ops.print_entries(ioapic_idx, reg_01.bits.entries);
+	io_apic_print_entries(ioapic_idx, reg_01.bits.entries);
 }
 
 void __init print_IO_APICs(void)
Signature · 1 line
1.7.10.4
#68 lore raw

[tip:x86/apic] x86/irq: Simplify the way to print IOAPIC entry

x86/irq: Simplify the way to print IOAPIC entry
Commit-ID:  a44174ee7b380012cdb63d563617f67bb7757649
Gitweb:     http://git.kernel.org/tip/a44174ee7b380012cdb63d563617f67bb7757649
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:57 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/irq: Simplify the way to print IOAPIC entry

Simplify the way to print IOAPIC entry content, so we can remove native_io_apic_print_entries(), intel_ir_io_apic_print_entries() and x86_io_apic_ops.print_entries() later.

Folded a patch from Thomas to fix errors in printed pin attributes,
http://www.spinics.net/lists/linux-tip-commits/msg26108.html

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/io_apic.c +28 -2
index 16d4ba3..3c66096 100644
@@ -1424,6 +1424,33 @@ void ioapic_zap_locks(void)
 	raw_spin_lock_init(&ioapic_lock);
 }
 
+static void io_apic_print_entries(unsigned int apic, unsigned int nr_entries)
+{
+	int i;
+	char buf[256];
+	struct IO_APIC_route_entry entry;
+	struct IR_IO_APIC_route_entry *ir_entry = (void *)&entry;
+
+	printk(KERN_DEBUG "IOAPIC %d:\n", apic);
+	for (i = 0; i <= nr_entries; i++) {
+		entry = ioapic_read_entry(apic, i);
+		snprintf(buf, sizeof(buf),
+			 " pin%02x, %s, %s, %s, V(%02X), IRR(%1d), S(%1d)",
+			 i, entry.mask ? "disabled" : "enabled ",
+			 entry.trigger ? "level" : "edge ",
+			 entry.polarity ? "low " : "high",
+			 entry.vector, entry.irr, entry.delivery_status);
+		if (ir_entry->format)
+			printk(KERN_DEBUG "%s, remapped, I(%04X),  Z(%X)\n",
+			       buf, (ir_entry->index << 15) | ir_entry->index,
+			       ir_entry->zero);
+		else
+			printk(KERN_DEBUG "%s, %s, D(%02X), M(%1d)\n",
+			       buf, entry.dest_mode ? "logical " : "physical",
+			       entry.dest, entry.delivery_mode);
+	}
+}
+
 static void __init print_IO_APIC(int ioapic_idx)
 {
 	union IO_APIC_reg_00 reg_00;
@@ -1477,8 +1504,7 @@ static void __init print_IO_APIC(int ioapic_idx)
 	}
 
 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
-
-	x86_io_apic_ops.print_entries(ioapic_idx, reg_01.bits.entries);
+	io_apic_print_entries(ioapic_idx, reg_01.bits.entries);
 }
 
 void __init print_IO_APICs(void)
author
#69 lore raw

PATCH v8 36/37 x86/irq: Introduce helper functions to support hierarchy irqdomain for IOAPIC

In reply to Jiang Liu

Introduce several helper functions, which will be used to enable hierarchy irqdomain for IOAPIC.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c |   61 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)
arch/x86/kernel/apic/io_apic.c +61 -0
index 3c6609617306..c8f786b5b91c 100644
@@ -82,6 +82,7 @@ struct mp_chip_data {
 	struct IO_APIC_route_entry entry;
 	int trigger;
 	int polarity;
+	u32 count;
 	bool isa_irq;
 };
 
@@ -945,6 +946,46 @@ void ioapic_set_alloc_attr(struct irq_alloc_info *info, int node,
 	info->ioapic_valid = 1;
 }
 
+#ifndef CONFIG_ACPI
+int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
+#endif
+
+static void ioapic_copy_alloc_attr(struct irq_alloc_info *dst,
+				   struct irq_alloc_info *src,
+				   u32 gsi, int ioapic_idx, int pin)
+{
+	int trigger, polarity;
+
+	copy_irq_alloc_info(dst, src);
+	dst->type = X86_IRQ_ALLOC_TYPE_IOAPIC;
+	dst->ioapic_id = mpc_ioapic_id(ioapic_idx);
+	dst->ioapic_pin = pin;
+	dst->ioapic_valid = 1;
+	if (src && src->ioapic_valid) {
+		dst->ioapic_node = src->ioapic_node;
+		dst->ioapic_trigger = src->ioapic_trigger;
+		dst->ioapic_polarity = src->ioapic_polarity;
+	} else {
+		dst->ioapic_node = NUMA_NO_NODE;
+		if (acpi_get_override_irq(gsi, &trigger, &polarity) >= 0) {
+			dst->ioapic_trigger = trigger;
+			dst->ioapic_polarity = polarity;
+		} else {
+			/*
+			 * PCI interrupts are always polarity one level
+			 * triggered.
+			 */
+			dst->ioapic_trigger = 1;
+			dst->ioapic_polarity = 1;
+		}
+	}
+}
+
+static int ioapic_alloc_attr_node(struct irq_alloc_info *info)
+{
+	return (info && info->ioapic_valid) ? info->ioapic_node : NUMA_NO_NODE;
+}
+
 static void mp_register_handler(unsigned int irq, unsigned long trigger)
 {
 	irq_flow_handler_t hdl;
@@ -962,6 +1003,26 @@ static void mp_register_handler(unsigned int irq, unsigned long trigger)
 	__irq_set_handler(irq, hdl, 0, fasteoi ? "fasteoi" : "edge");
 }
 
+static bool mp_check_pin_attr(int irq, struct irq_alloc_info *info)
+{
+	struct mp_chip_data *data = irq_get_chip_data(irq);
+
+	/*
+	 * setup_IO_APIC_irqs() programs all legacy IRQs with default trigger
+	 * and polarity attirbutes. So allow the first user to reprogram the
+	 * pin with real trigger and polarity attributes.
+	 */
+	if (irq < nr_legacy_irqs() && data->count == 1) {
+		if (info->ioapic_trigger != data->trigger)
+			mp_register_handler(irq, data->trigger);
+		data->entry.trigger = data->trigger = info->ioapic_trigger;
+		data->entry.polarity = data->polarity = info->ioapic_polarity;
+	}
+
+	return data->trigger == info->ioapic_trigger &&
+	       data->polarity == info->ioapic_polarity;
+}
+
 static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin,
 				 struct irq_alloc_info *info)
 {
Signature · 1 line
1.7.10.4
#70 lore raw

[tip:x86/apic] x86/irq: Introduce helper functions to support hierarchical irqdomains for IOAPIC

x86/irq: Introduce helper functions to support hierarchical irqdomains for IOAPIC
Commit-ID:  96ed44b2d5e0e9d6e5b135e84ea5c8cd763ce861
Gitweb:     http://git.kernel.org/tip/96ed44b2d5e0e9d6e5b135e84ea5c8cd763ce861
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:58 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/irq: Introduce helper functions to support hierarchical irqdomains for IOAPIC

Introduce several helper functions, which will be used to enable hierarchical irqdomain for IOAPIC.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc David Cohen <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Grant Likely <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c | 61 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)
arch/x86/kernel/apic/io_apic.c +61 -0
index 3c66096..c8f786b 100644
@@ -82,6 +82,7 @@ struct mp_chip_data {
 	struct IO_APIC_route_entry entry;
 	int trigger;
 	int polarity;
+	u32 count;
 	bool isa_irq;
 };
 
@@ -945,6 +946,46 @@ void ioapic_set_alloc_attr(struct irq_alloc_info *info, int node,
 	info->ioapic_valid = 1;
 }
 
+#ifndef CONFIG_ACPI
+int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
+#endif
+
+static void ioapic_copy_alloc_attr(struct irq_alloc_info *dst,
+				   struct irq_alloc_info *src,
+				   u32 gsi, int ioapic_idx, int pin)
+{
+	int trigger, polarity;
+
+	copy_irq_alloc_info(dst, src);
+	dst->type = X86_IRQ_ALLOC_TYPE_IOAPIC;
+	dst->ioapic_id = mpc_ioapic_id(ioapic_idx);
+	dst->ioapic_pin = pin;
+	dst->ioapic_valid = 1;
+	if (src && src->ioapic_valid) {
+		dst->ioapic_node = src->ioapic_node;
+		dst->ioapic_trigger = src->ioapic_trigger;
+		dst->ioapic_polarity = src->ioapic_polarity;
+	} else {
+		dst->ioapic_node = NUMA_NO_NODE;
+		if (acpi_get_override_irq(gsi, &trigger, &polarity) >= 0) {
+			dst->ioapic_trigger = trigger;
+			dst->ioapic_polarity = polarity;
+		} else {
+			/*
+			 * PCI interrupts are always polarity one level
+			 * triggered.
+			 */
+			dst->ioapic_trigger = 1;
+			dst->ioapic_polarity = 1;
+		}
+	}
+}
+
+static int ioapic_alloc_attr_node(struct irq_alloc_info *info)
+{
+	return (info && info->ioapic_valid) ? info->ioapic_node : NUMA_NO_NODE;
+}
+
 static void mp_register_handler(unsigned int irq, unsigned long trigger)
 {
 	irq_flow_handler_t hdl;
@@ -962,6 +1003,26 @@ static void mp_register_handler(unsigned int irq, unsigned long trigger)
 	__irq_set_handler(irq, hdl, 0, fasteoi ? "fasteoi" : "edge");
 }
 
+static bool mp_check_pin_attr(int irq, struct irq_alloc_info *info)
+{
+	struct mp_chip_data *data = irq_get_chip_data(irq);
+
+	/*
+	 * setup_IO_APIC_irqs() programs all legacy IRQs with default trigger
+	 * and polarity attirbutes. So allow the first user to reprogram the
+	 * pin with real trigger and polarity attributes.
+	 */
+	if (irq < nr_legacy_irqs() && data->count == 1) {
+		if (info->ioapic_trigger != data->trigger)
+			mp_register_handler(irq, data->trigger);
+		data->entry.trigger = data->trigger = info->ioapic_trigger;
+		data->entry.polarity = data->polarity = info->ioapic_polarity;
+	}
+
+	return data->trigger == info->ioapic_trigger &&
+	       data->polarity == info->ioapic_polarity;
+}
+
 static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin,
 				 struct irq_alloc_info *info)
 {
author
#71 lore raw

PATCH v8 37/37 x86/irq: Convert IOAPIC to use hierarchy irqdomain interfaces

In reply to Jiang Liu

Convert IOAPIC driver to support and use hierarchy irqdomain interfaces. It's a little big, but it always break bisectings if we split it into multiple patches.

Fold in a patch from Andy Shevchenko <[email protected]> to make it bisectable.
http://lkml.org/lkml/2014/12/10/622

Cc Andy Shevchenko <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Grant Likely <[email protected]>
Cc Rob Herring <[email protected]>
Cc David Rientjes <[email protected]>
Cc David Cohen <[email protected]>
---
 arch/x86/kernel/acpi/boot.c                        |   11 +-
 arch/x86/kernel/apic/io_apic.c                     |  308 ++++++++++++++------
 arch/x86/kernel/devicetree.c                       |   37 +--
 arch/x86/kernel/mpparse.c                          |    6 +-
 arch/x86/pci/intel_mid_pci.c                       |    2 -
 .../platform/intel-mid/device_libs/platform_wdt.c  |    3 +-
 arch/x86/platform/intel-mid/sfi.c                  |    5 +-
 arch/x86/platform/sfi/sfi.c                        |    5 +-
 8 files changed, 240 insertions(+), 137 deletions(-)
arch/x86/kernel/acpi/boot.c +4 -7
index a43a4d3c60e1..21e460b3b360 100644
@@ -412,11 +412,6 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 	trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
 	polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
 	node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
-	if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
-		pr_warn("Failed to set pin attr for GSI%d\n", gsi);
-		return -1;
-	}
-
 	ioapic_set_alloc_attr(&info, node, trigger, polarity);
 	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info);
 	if (irq < 0)
@@ -442,8 +437,10 @@ static void mp_unregister_gsi(u32 gsi)
 }
 
 static struct irq_domain_ops acpi_irqdomain_ops = {
-	.map = mp_irqdomain_map,
-	.unmap = mp_irqdomain_unmap,
+	.alloc = mp_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static int __init
arch/x86/kernel/apic/io_apic.c +211 -97

496 lines not on this page · raw message

arch/x86/kernel/devicetree.c +15 -22
index 3d3503351242..9ca73a700912 100644
@@ -196,38 +196,31 @@ static struct of_ioapic_type of_ioapic_type[] =
 	},
 };
 
-static int ioapic_xlate(struct irq_domain *domain,
-			struct device_node *controller,
-			const u32 *intspec, u32 intsize,
-			irq_hw_number_t *out_hwirq, u32 *out_type)
+static int dt_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
+			      unsigned int nr_irqs, void *arg)
 {
+	struct of_phandle_args *irq_data = (void *)arg;
 	struct of_ioapic_type *it;
-	u32 line, idx, gsi;
+	struct irq_alloc_info tmp;
 
-	if (WARN_ON(intsize < 2))
+	if (WARN_ON(irq_data->args_count < 2))
 		return -EINVAL;
-
-	line = intspec[0];
-
-	if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
+	if (irq_data->args[1] >= ARRAY_SIZE(of_ioapic_type))
 		return -EINVAL;
 
-	it = &of_ioapic_type[intspec[1]];
+	it = &of_ioapic_type[irq_data->args[1]];
+	ioapic_set_alloc_attr(&tmp, NUMA_NO_NODE, it->trigger, it->polarity);
+	tmp.ioapic_id = mpc_ioapic_id(mp_irqdomain_ioapic_idx(domain));
+	tmp.ioapic_pin = irq_data->args[0];
 
-	idx = (u32)(long)domain->host_data;
-	gsi = mp_pin_to_gsi(idx, line);
-	if (mp_set_gsi_attr(gsi, it->trigger, it->polarity, cpu_to_node(0)))
-		return -EBUSY;
-
-	*out_hwirq = line;
-	*out_type = it->out_type;
-	return 0;
+	return mp_irqdomain_alloc(domain, virq, nr_irqs, &tmp);
 }
 
 const struct irq_domain_ops ioapic_irq_domain_ops = {
-	.map = mp_irqdomain_map,
-	.unmap = mp_irqdomain_unmap,
-	.xlate = ioapic_xlate,
+	.alloc = dt_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static void __init dtb_add_ioapic(struct device_node *dn)
arch/x86/kernel/mpparse.c +4 -2
index 2d2a237f2c73..aa4feee74dbe 100644
@@ -114,8 +114,10 @@ static void __init MP_bus_info(struct mpc_bus *m)
 }
 
 static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
-	.map = mp_irqdomain_map,
-	.unmap = mp_irqdomain_unmap,
+	.alloc = mp_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static void __init MP_ioapic_info(struct mpc_ioapic *m)
arch/x86/pci/intel_mid_pci.c +0 -2
index 57b5719b617b..27062303c881 100644
@@ -224,8 +224,6 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 	 * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
 	 * IOAPIC RTE entries, so we just enable RTE for the device.
 	 */
-	if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
-		return -EBUSY;
 	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC, &info) < 0)
 		return -EBUSY;
 
arch/x86/platform/intel-mid/device_libs/platform_wdt.c +1 -2
index de0009f6d555..de734134bc8d 100644
@@ -36,8 +36,7 @@ static int tangier_probe(struct platform_device *pdev)
 	/* IOAPIC builds identity mapping between GSI and IRQ on MID */
 	gsi = pdata->irq;
 	ioapic_set_alloc_attr(&info, cpu_to_node(0), 1, 0);
-	if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
-	    mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info) <= 0) {
+	if (mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info) <= 0) {
 		dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
 			 gsi);
 		return -EINVAL;
arch/x86/platform/intel-mid/sfi.c +1 -4
index 7d17355d820e..ce992e8cc065 100644
@@ -469,10 +469,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 			}
 
 			ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, polarity);
-			ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
-			if (ret == 0)
-				ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC,
-							&info);
+			ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC, &info);
 			WARN_ON(ret < 0);
 		}
 
arch/x86/platform/sfi/sfi.c +4 -1
index 2a8a74f3bd76..b66b194f9900 100644
@@ -72,7 +72,10 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
 
 #ifdef CONFIG_X86_IO_APIC
 static struct irq_domain_ops sfi_ioapic_irqdomain_ops = {
-	.map = mp_irqdomain_map,
+	.alloc = mp_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static int __init sfi_parse_ioapic(struct sfi_table_header *table)
Signature · 1 line
1.7.10.4
#72 lore raw

[tip:x86/apic] x86/irq: Convert IOAPIC to use hierarchical irqdomain interfaces

x86/irq: Convert IOAPIC to use hierarchical irqdomain interfaces
Commit-ID:  d32932d02e1869be838cea3ace42467c360db377
Gitweb:     http://git.kernel.org/tip/d32932d02e1869be838cea3ace42467c360db377
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 13 Apr 2015 14:11:59 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Fri, 24 Apr 2015 15:36:51 +0200

x86/irq: Convert IOAPIC to use hierarchical irqdomain interfaces

Convert IOAPIC driver to support and use hierarchical irqdomain interfaces. It's a little big, but would break bisecting if we split it into multiple patches.

Fold in a patch from Andy Shevchenko <[email protected]> to make it bisectable.
http://lkml.org/lkml/2014/12/10/622

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Sander Eikelenboom <[email protected]>
Cc David Vrabel <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Andy Shevchenko <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dimitri Sivanich <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Grant Likely <[email protected]>
Cc Rob Herring <[email protected]>
Cc David Rientjes <[email protected]>
Cc David Cohen <[email protected]>
---
 arch/x86/kernel/acpi/boot.c                        |  11 +-
 arch/x86/kernel/apic/io_apic.c                     | 308 ++++++++++++++-------
 arch/x86/kernel/devicetree.c                       |  37 +--
 arch/x86/kernel/mpparse.c                          |   6 +-
 arch/x86/pci/intel_mid_pci.c                       |   2 -
 .../platform/intel-mid/device_libs/platform_wdt.c  |   3 +-
 arch/x86/platform/intel-mid/sfi.c                  |   5 +-
 arch/x86/platform/sfi/sfi.c                        |   5 +-
 8 files changed, 240 insertions(+), 137 deletions(-)
arch/x86/kernel/acpi/boot.c +4 -7
index a43a4d3..21e460b 100644
@@ -412,11 +412,6 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 	trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
 	polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
 	node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
-	if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
-		pr_warn("Failed to set pin attr for GSI%d\n", gsi);
-		return -1;
-	}
-
 	ioapic_set_alloc_attr(&info, node, trigger, polarity);
 	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info);
 	if (irq < 0)
@@ -442,8 +437,10 @@ static void mp_unregister_gsi(u32 gsi)
 }
 
 static struct irq_domain_ops acpi_irqdomain_ops = {
-	.map = mp_irqdomain_map,
-	.unmap = mp_irqdomain_unmap,
+	.alloc = mp_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static int __init
arch/x86/kernel/apic/io_apic.c +211 -97

496 lines not on this page · raw message

arch/x86/kernel/devicetree.c +15 -22
index 6367a78..05103d3 100644
@@ -196,38 +196,31 @@ static struct of_ioapic_type of_ioapic_type[] =
 	},
 };
 
-static int ioapic_xlate(struct irq_domain *domain,
-			struct device_node *controller,
-			const u32 *intspec, u32 intsize,
-			irq_hw_number_t *out_hwirq, u32 *out_type)
+static int dt_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
+			      unsigned int nr_irqs, void *arg)
 {
+	struct of_phandle_args *irq_data = (void *)arg;
 	struct of_ioapic_type *it;
-	u32 line, idx, gsi;
+	struct irq_alloc_info tmp;
 
-	if (WARN_ON(intsize < 2))
+	if (WARN_ON(irq_data->args_count < 2))
 		return -EINVAL;
-
-	line = intspec[0];
-
-	if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
+	if (irq_data->args[1] >= ARRAY_SIZE(of_ioapic_type))
 		return -EINVAL;
 
-	it = &of_ioapic_type[intspec[1]];
+	it = &of_ioapic_type[irq_data->args[1]];
+	ioapic_set_alloc_attr(&tmp, NUMA_NO_NODE, it->trigger, it->polarity);
+	tmp.ioapic_id = mpc_ioapic_id(mp_irqdomain_ioapic_idx(domain));
+	tmp.ioapic_pin = irq_data->args[0];
 
-	idx = (u32)(long)domain->host_data;
-	gsi = mp_pin_to_gsi(idx, line);
-	if (mp_set_gsi_attr(gsi, it->trigger, it->polarity, cpu_to_node(0)))
-		return -EBUSY;
-
-	*out_hwirq = line;
-	*out_type = it->out_type;
-	return 0;
+	return mp_irqdomain_alloc(domain, virq, nr_irqs, &tmp);
 }
 
 const struct irq_domain_ops ioapic_irq_domain_ops = {
-	.map = mp_irqdomain_map,
-	.unmap = mp_irqdomain_unmap,
-	.xlate = ioapic_xlate,
+	.alloc = dt_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static void __init dtb_add_ioapic(struct device_node *dn)
arch/x86/kernel/mpparse.c +4 -2
index 2d2a237..aa4feee 100644
@@ -114,8 +114,10 @@ static void __init MP_bus_info(struct mpc_bus *m)
 }
 
 static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
-	.map = mp_irqdomain_map,
-	.unmap = mp_irqdomain_unmap,
+	.alloc = mp_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static void __init MP_ioapic_info(struct mpc_ioapic *m)
arch/x86/pci/intel_mid_pci.c +0 -2
index 57b5719..2706230 100644
@@ -224,8 +224,6 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 	 * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
 	 * IOAPIC RTE entries, so we just enable RTE for the device.
 	 */
-	if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
-		return -EBUSY;
 	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC, &info) < 0)
 		return -EBUSY;
 
arch/x86/platform/intel-mid/device_libs/platform_wdt.c +1 -2
index de0009f..de73413 100644
@@ -36,8 +36,7 @@ static int tangier_probe(struct platform_device *pdev)
 	/* IOAPIC builds identity mapping between GSI and IRQ on MID */
 	gsi = pdata->irq;
 	ioapic_set_alloc_attr(&info, cpu_to_node(0), 1, 0);
-	if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
-	    mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info) <= 0) {
+	if (mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info) <= 0) {
 		dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
 			 gsi);
 		return -EINVAL;
arch/x86/platform/intel-mid/sfi.c +1 -4
index 7d17355..ce992e8 100644
@@ -469,10 +469,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 			}
 
 			ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, polarity);
-			ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
-			if (ret == 0)
-				ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC,
-							&info);
+			ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC, &info);
 			WARN_ON(ret < 0);
 		}
 
arch/x86/platform/sfi/sfi.c +4 -1
index 2a8a74f..b66b194 100644
@@ -72,7 +72,10 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
 
 #ifdef CONFIG_X86_IO_APIC
 static struct irq_domain_ops sfi_ioapic_irqdomain_ops = {
-	.map = mp_irqdomain_map,
+	.alloc = mp_irqdomain_alloc,
+	.free = mp_irqdomain_free,
+	.activate = mp_irqdomain_activate,
+	.deactivate = mp_irqdomain_deactivate,
 };
 
 static int __init sfi_parse_ioapic(struct sfi_table_header *table)
#73 lore raw
In reply to Jiang Liu
Quoted 13 lines · Jiang Liu

Hi all,
The generic hierarchy irqdomain and stacked irqchip implementation
has been merged into v3.19, so this patch set converts x86 interupt management to hierarchy irqdomain and stacked irqchip. You may access it at:
https://github.com/jiangliu/linux.git irqdomain/x86_p1_v8

This patch set has been reviewed several times and it missed v3.19
merging because several bugs got fixed just before the merging window. The main changes since last review are:
1) Rebased the patch set onto v4.0-rc6.
2) Merged bugfixes into the patch introducing the bug so they don't break bisecting.

Quoted 2 lines

I will send out another following-on patch set to clean up code and interfaces obseleted by this patch set.

So JFYI, the v4.1 merge window has just opened and I probably won't have time to look at this for a week or two.

Thanks,

Ingo

author
#74 lore raw
Quoted 16 lines · Ingo Molnar
Quoted 13 lines · Jiang Liu

Hi all,
The generic hierarchy irqdomain and stacked irqchip implementation
has been merged into v3.19, so this patch set converts x86 interupt management to hierarchy irqdomain and stacked irqchip. You may access it at:
https://github.com/jiangliu/linux.git irqdomain/x86_p1_v8

This patch set has been reviewed several times and it missed v3.19
merging because several bugs got fixed just before the merging window. The main changes since last review are:
1) Rebased the patch set onto v4.0-rc6.
2) Merged bugfixes into the patch introducing the bug so they don't break bisecting.

Quoted 5 lines
Quoted 2 lines

I will send out another following-on patch set to clean up code and interfaces obseleted by this patch set.

So JFYI, the v4.1 merge window has just opened and I probably won't have time to look at this for a week or two.

Hi Ingo,
Thanks for reminder:) Thomas pinged me on this patch set,
so I send it out right now. Originally I planned to send it out after v4.1 merge window.
Regards!
Gerry

Quoted 10 lines

Thanks,

Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#75 lore raw
Quoted 20 lines · Jiang Liu
Quoted 19 lines · Ingo Molnar
Quoted 15 lines · Jiang Liu

Hi all,
The generic hierarchy irqdomain and stacked irqchip implementation
has been merged into v3.19, so this patch set converts x86 interupt management to hierarchy irqdomain and stacked irqchip. You may access it at:
https://github.com/jiangliu/linux.git irqdomain/x86_p1_v8

This patch set has been reviewed several times and it missed v3.19
merging because several bugs got fixed just before the merging window. The main changes since last review are:
1) Rebased the patch set onto v4.0-rc6.
2) Merged bugfixes into the patch introducing the bug so they don't break bisecting.

I will send out another following-on patch set to clean up code and interfaces obseleted by this patch set.

Quoted 6 lines
Quoted 2 lines

So JFYI, the v4.1 merge window has just opened and I probably won't have time to look at this for a week or two.

Hi Ingo,
Thanks for reminder:) Thomas pinged me on this patch set,
so I send it out right now. Originally I planned to send it out after v4.1 merge window.

Right. I'm taking a look in the next days.

#76 lore raw
In reply to Ingo Molnar
Quoted 16 lines · Ingo Molnar
Quoted 13 lines · Jiang Liu

Hi all,
The generic hierarchy irqdomain and stacked irqchip implementation
has been merged into v3.19, so this patch set converts x86 interupt management to hierarchy irqdomain and stacked irqchip. You may access it at:
https://github.com/jiangliu/linux.git irqdomain/x86_p1_v8

This patch set has been reviewed several times and it missed v3.19
merging because several bugs got fixed just before the merging window. The main changes since last review are:
1) Rebased the patch set onto v4.0-rc6.
2) Merged bugfixes into the patch introducing the bug so they don't break bisecting.

Quoted 5 lines
Quoted 2 lines

I will send out another following-on patch set to clean up code and interfaces obseleted by this patch set.

So JFYI, the v4.1 merge window has just opened and I probably won't have time to look at this for a week or two.

Same for me. I rather won't be able to look at this in the next 2 weeks.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.