All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-06 17:36 ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

[This patch series used to be called "Making the generic ACPI GSI
layer irqdomain aware", but as I've radically changed my approach to
this problem, I've decided to reset the counters...]

The irqdomain code is not entierely ACPI friendly, as it has some
built-in knowledge of the device-tree. Nothing too harmful, but enough
to scare the ARM ACPI developpers which end up with their own version
of the square wheel. And some of the ramifications actually run deeper
than initially expected.

This series adapts the irqdomain code to use 'struct fwnode_handle'
instead of 'struct device_node' as the identifier for a domain
(compatibility interfaces are of course added). It also introduces a
generic IRQ specifier that firmware interfaces (DT or ACPI) can
directly use to configure interrupts, and allow the ACPI GSI code to
be plugged into this.

As examples, we convert the ARM GIC ACPI support to use irqdomains as
originally intended, and rework the MSI code to also move away from
using device nodes when using irqdomains.

Overall, this gives us a way to use irqdomains on both DT and ACPI
enabled platforms, having very little changes made to the actual
drivers (other than the probing infrastructure). Because we keep the
flow of information between the various layers identical between ACPI
and DT, we immediately benefit from the existing infrastructure.

This has been test-booted on Juno, is based on 4.3-rc4, and available at:

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1

Marc Zyngier (16):
  irqdomain: Use an accessor for the of_node field
  irqdomain: Convert irqdomain->of_node to fwnode
  irqdomain: Allow irq domain lookup by fwnode
  irqdomain: Introduce a firmware-specific IRQ specifier structure
  irqchip: Convert all alloc/xlate users from of_node to fwnode
  irqdomain: Introduce irq_create_fwspec_mapping
  irqdomain: Introduce irq_domain_create_{linear,tree}
  irqdomain: Add a fwnode_handle allocator
  acpi/gsi: Always perform an irq domain lookup
  acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
  irqchip/gic: Get rid of gic_init_bases()
  irqchip/gic: Switch ACPI support to stacked domains
  irqchip/gic: Kill the xlate method
  acpi/gsi: Cleanup acpi_register_gsi
  irqdomain: Introduce irq_domain_create_hierarchy
  irqdomain/msi: Use fwnode instead of of_node

 arch/arm/mach-exynos/suspend.c                |  55 ++++----
 arch/arm/mach-imx/gpc.c                       |  55 ++++----
 arch/arm/mach-omap2/omap-wakeupgen.c          |  55 ++++----
 arch/c6x/platforms/megamod-pic.c              |   2 +-
 arch/mips/cavium-octeon/octeon-irq.c          |   4 +-
 arch/powerpc/platforms/cell/axon_msi.c        |   2 +-
 arch/powerpc/platforms/cell/spider-pic.c      |   9 +-
 arch/powerpc/platforms/pasemi/msi.c           |   6 +-
 arch/powerpc/platforms/powernv/opal-irqchip.c |   2 +-
 arch/powerpc/sysdev/ehv_pic.c                 |   3 +-
 arch/powerpc/sysdev/fsl_msi.c                 |   2 +-
 arch/powerpc/sysdev/i8259.c                   |   3 +-
 arch/powerpc/sysdev/ipic.c                    |   3 +-
 arch/powerpc/sysdev/mpic.c                    |   3 +-
 arch/powerpc/sysdev/mpic_msi.c                |   2 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c            |   3 +-
 drivers/acpi/gsi.c                            |  54 ++++----
 drivers/base/platform-msi.c                   |   6 +-
 drivers/gpio/gpio-sodaville.c                 |   2 +-
 drivers/irqchip/exynos-combiner.c             |   2 +-
 drivers/irqchip/irq-atmel-aic-common.c        |   2 +-
 drivers/irqchip/irq-crossbar.c                |  62 ++++-----
 drivers/irqchip/irq-gic-v2m.c                 |  23 ++--
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
 drivers/irqchip/irq-gic-v3-its.c              |  20 +--
 drivers/irqchip/irq-gic-v3.c                  |  49 ++++----
 drivers/irqchip/irq-gic.c                     |  94 ++++++++------
 drivers/irqchip/irq-hip04.c                   |   2 +-
 drivers/irqchip/irq-imx-gpcv2.c               |  64 +++++-----
 drivers/irqchip/irq-mtk-sysirq.c              |  49 ++++----
 drivers/irqchip/irq-nvic.c                    |  18 ++-
 drivers/irqchip/irq-s3c24xx.c                 |   4 +-
 drivers/irqchip/irq-tegra.c                   |  55 ++++----
 drivers/irqchip/irq-vf610-mscm-ir.c           |  45 ++++---
 drivers/pci/host/pci-xgene-msi.c              |   2 +-
 drivers/pci/msi.c                             |  14 +--
 drivers/spmi/spmi-pmic-arb.c                  |   2 +-
 include/linux/acpi.h                          |   3 +
 include/linux/fwnode.h                        |   1 +
 include/linux/irqchip/arm-gic.h               |   9 +-
 include/linux/irqdomain.h                     |  86 +++++++++++--
 include/linux/msi.h                           |   9 +-
 kernel/irq/irqdomain.c                        | 173 ++++++++++++++++++++------
 kernel/irq/msi.c                              |   8 +-
 45 files changed, 665 insertions(+), 408 deletions(-)

-- 
2.1.4

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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-06 17:36 ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

[This patch series used to be called "Making the generic ACPI GSI
layer irqdomain aware", but as I've radically changed my approach to
this problem, I've decided to reset the counters...]

The irqdomain code is not entierely ACPI friendly, as it has some
built-in knowledge of the device-tree. Nothing too harmful, but enough
to scare the ARM ACPI developpers which end up with their own version
of the square wheel. And some of the ramifications actually run deeper
than initially expected.

This series adapts the irqdomain code to use 'struct fwnode_handle'
instead of 'struct device_node' as the identifier for a domain
(compatibility interfaces are of course added). It also introduces a
generic IRQ specifier that firmware interfaces (DT or ACPI) can
directly use to configure interrupts, and allow the ACPI GSI code to
be plugged into this.

As examples, we convert the ARM GIC ACPI support to use irqdomains as
originally intended, and rework the MSI code to also move away from
using device nodes when using irqdomains.

Overall, this gives us a way to use irqdomains on both DT and ACPI
enabled platforms, having very little changes made to the actual
drivers (other than the probing infrastructure). Because we keep the
flow of information between the various layers identical between ACPI
and DT, we immediately benefit from the existing infrastructure.

This has been test-booted on Juno, is based on 4.3-rc4, and available at:

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1

Marc Zyngier (16):
  irqdomain: Use an accessor for the of_node field
  irqdomain: Convert irqdomain->of_node to fwnode
  irqdomain: Allow irq domain lookup by fwnode
  irqdomain: Introduce a firmware-specific IRQ specifier structure
  irqchip: Convert all alloc/xlate users from of_node to fwnode
  irqdomain: Introduce irq_create_fwspec_mapping
  irqdomain: Introduce irq_domain_create_{linear,tree}
  irqdomain: Add a fwnode_handle allocator
  acpi/gsi: Always perform an irq domain lookup
  acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
  irqchip/gic: Get rid of gic_init_bases()
  irqchip/gic: Switch ACPI support to stacked domains
  irqchip/gic: Kill the xlate method
  acpi/gsi: Cleanup acpi_register_gsi
  irqdomain: Introduce irq_domain_create_hierarchy
  irqdomain/msi: Use fwnode instead of of_node

 arch/arm/mach-exynos/suspend.c                |  55 ++++----
 arch/arm/mach-imx/gpc.c                       |  55 ++++----
 arch/arm/mach-omap2/omap-wakeupgen.c          |  55 ++++----
 arch/c6x/platforms/megamod-pic.c              |   2 +-
 arch/mips/cavium-octeon/octeon-irq.c          |   4 +-
 arch/powerpc/platforms/cell/axon_msi.c        |   2 +-
 arch/powerpc/platforms/cell/spider-pic.c      |   9 +-
 arch/powerpc/platforms/pasemi/msi.c           |   6 +-
 arch/powerpc/platforms/powernv/opal-irqchip.c |   2 +-
 arch/powerpc/sysdev/ehv_pic.c                 |   3 +-
 arch/powerpc/sysdev/fsl_msi.c                 |   2 +-
 arch/powerpc/sysdev/i8259.c                   |   3 +-
 arch/powerpc/sysdev/ipic.c                    |   3 +-
 arch/powerpc/sysdev/mpic.c                    |   3 +-
 arch/powerpc/sysdev/mpic_msi.c                |   2 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c            |   3 +-
 drivers/acpi/gsi.c                            |  54 ++++----
 drivers/base/platform-msi.c                   |   6 +-
 drivers/gpio/gpio-sodaville.c                 |   2 +-
 drivers/irqchip/exynos-combiner.c             |   2 +-
 drivers/irqchip/irq-atmel-aic-common.c        |   2 +-
 drivers/irqchip/irq-crossbar.c                |  62 ++++-----
 drivers/irqchip/irq-gic-v2m.c                 |  23 ++--
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
 drivers/irqchip/irq-gic-v3-its.c              |  20 +--
 drivers/irqchip/irq-gic-v3.c                  |  49 ++++----
 drivers/irqchip/irq-gic.c                     |  94 ++++++++------
 drivers/irqchip/irq-hip04.c                   |   2 +-
 drivers/irqchip/irq-imx-gpcv2.c               |  64 +++++-----
 drivers/irqchip/irq-mtk-sysirq.c              |  49 ++++----
 drivers/irqchip/irq-nvic.c                    |  18 ++-
 drivers/irqchip/irq-s3c24xx.c                 |   4 +-
 drivers/irqchip/irq-tegra.c                   |  55 ++++----
 drivers/irqchip/irq-vf610-mscm-ir.c           |  45 ++++---
 drivers/pci/host/pci-xgene-msi.c              |   2 +-
 drivers/pci/msi.c                             |  14 +--
 drivers/spmi/spmi-pmic-arb.c                  |   2 +-
 include/linux/acpi.h                          |   3 +
 include/linux/fwnode.h                        |   1 +
 include/linux/irqchip/arm-gic.h               |   9 +-
 include/linux/irqdomain.h                     |  86 +++++++++++--
 include/linux/msi.h                           |   9 +-
 kernel/irq/irqdomain.c                        | 173 ++++++++++++++++++++------
 kernel/irq/msi.c                              |   8 +-
 45 files changed, 665 insertions(+), 408 deletions(-)

-- 
2.1.4


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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-06 17:36 ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

[This patch series used to be called "Making the generic ACPI GSI
layer irqdomain aware", but as I've radically changed my approach to
this problem, I've decided to reset the counters...]

The irqdomain code is not entierely ACPI friendly, as it has some
built-in knowledge of the device-tree. Nothing too harmful, but enough
to scare the ARM ACPI developpers which end up with their own version
of the square wheel. And some of the ramifications actually run deeper
than initially expected.

This series adapts the irqdomain code to use 'struct fwnode_handle'
instead of 'struct device_node' as the identifier for a domain
(compatibility interfaces are of course added). It also introduces a
generic IRQ specifier that firmware interfaces (DT or ACPI) can
directly use to configure interrupts, and allow the ACPI GSI code to
be plugged into this.

As examples, we convert the ARM GIC ACPI support to use irqdomains as
originally intended, and rework the MSI code to also move away from
using device nodes when using irqdomains.

Overall, this gives us a way to use irqdomains on both DT and ACPI
enabled platforms, having very little changes made to the actual
drivers (other than the probing infrastructure). Because we keep the
flow of information between the various layers identical between ACPI
and DT, we immediately benefit from the existing infrastructure.

This has been test-booted on Juno, is based on 4.3-rc4, and available at:

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1

Marc Zyngier (16):
  irqdomain: Use an accessor for the of_node field
  irqdomain: Convert irqdomain->of_node to fwnode
  irqdomain: Allow irq domain lookup by fwnode
  irqdomain: Introduce a firmware-specific IRQ specifier structure
  irqchip: Convert all alloc/xlate users from of_node to fwnode
  irqdomain: Introduce irq_create_fwspec_mapping
  irqdomain: Introduce irq_domain_create_{linear,tree}
  irqdomain: Add a fwnode_handle allocator
  acpi/gsi: Always perform an irq domain lookup
  acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
  irqchip/gic: Get rid of gic_init_bases()
  irqchip/gic: Switch ACPI support to stacked domains
  irqchip/gic: Kill the xlate method
  acpi/gsi: Cleanup acpi_register_gsi
  irqdomain: Introduce irq_domain_create_hierarchy
  irqdomain/msi: Use fwnode instead of of_node

 arch/arm/mach-exynos/suspend.c                |  55 ++++----
 arch/arm/mach-imx/gpc.c                       |  55 ++++----
 arch/arm/mach-omap2/omap-wakeupgen.c          |  55 ++++----
 arch/c6x/platforms/megamod-pic.c              |   2 +-
 arch/mips/cavium-octeon/octeon-irq.c          |   4 +-
 arch/powerpc/platforms/cell/axon_msi.c        |   2 +-
 arch/powerpc/platforms/cell/spider-pic.c      |   9 +-
 arch/powerpc/platforms/pasemi/msi.c           |   6 +-
 arch/powerpc/platforms/powernv/opal-irqchip.c |   2 +-
 arch/powerpc/sysdev/ehv_pic.c                 |   3 +-
 arch/powerpc/sysdev/fsl_msi.c                 |   2 +-
 arch/powerpc/sysdev/i8259.c                   |   3 +-
 arch/powerpc/sysdev/ipic.c                    |   3 +-
 arch/powerpc/sysdev/mpic.c                    |   3 +-
 arch/powerpc/sysdev/mpic_msi.c                |   2 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c            |   3 +-
 drivers/acpi/gsi.c                            |  54 ++++----
 drivers/base/platform-msi.c                   |   6 +-
 drivers/gpio/gpio-sodaville.c                 |   2 +-
 drivers/irqchip/exynos-combiner.c             |   2 +-
 drivers/irqchip/irq-atmel-aic-common.c        |   2 +-
 drivers/irqchip/irq-crossbar.c                |  62 ++++-----
 drivers/irqchip/irq-gic-v2m.c                 |  23 ++--
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
 drivers/irqchip/irq-gic-v3-its.c              |  20 +--
 drivers/irqchip/irq-gic-v3.c                  |  49 ++++----
 drivers/irqchip/irq-gic.c                     |  94 ++++++++------
 drivers/irqchip/irq-hip04.c                   |   2 +-
 drivers/irqchip/irq-imx-gpcv2.c               |  64 +++++-----
 drivers/irqchip/irq-mtk-sysirq.c              |  49 ++++----
 drivers/irqchip/irq-nvic.c                    |  18 ++-
 drivers/irqchip/irq-s3c24xx.c                 |   4 +-
 drivers/irqchip/irq-tegra.c                   |  55 ++++----
 drivers/irqchip/irq-vf610-mscm-ir.c           |  45 ++++---
 drivers/pci/host/pci-xgene-msi.c              |   2 +-
 drivers/pci/msi.c                             |  14 +--
 drivers/spmi/spmi-pmic-arb.c                  |   2 +-
 include/linux/acpi.h                          |   3 +
 include/linux/fwnode.h                        |   1 +
 include/linux/irqchip/arm-gic.h               |   9 +-
 include/linux/irqdomain.h                     |  86 +++++++++++--
 include/linux/msi.h                           |   9 +-
 kernel/irq/irqdomain.c                        | 173 ++++++++++++++++++++------
 kernel/irq/msi.c                              |   8 +-
 45 files changed, 665 insertions(+), 408 deletions(-)

-- 
2.1.4

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

* [PATCH 01/16] irqdomain: Use an accessor for the of_node field
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Suravee Suthikulpanit, Jake Oshins, Graeme Gregory,
	linux-arm-kernel

The struct irq_domain contains a "struct device_node *" field
(of_node) that is almost the only link between the irqdomain
and the device tree infrastructure.

In order to prepare for the removal of that field, convert all
users to use an accessor.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-omap2/omap-wakeupgen.c          |  2 +-
 arch/c6x/platforms/megamod-pic.c              |  2 +-
 arch/mips/cavium-octeon/octeon-irq.c          |  4 ++--
 arch/powerpc/platforms/cell/axon_msi.c        |  2 +-
 arch/powerpc/platforms/cell/spider-pic.c      |  9 +++++---
 arch/powerpc/platforms/pasemi/msi.c           |  6 ++++--
 arch/powerpc/platforms/powernv/opal-irqchip.c |  2 +-
 arch/powerpc/sysdev/ehv_pic.c                 |  3 ++-
 arch/powerpc/sysdev/fsl_msi.c                 |  2 +-
 arch/powerpc/sysdev/i8259.c                   |  3 ++-
 arch/powerpc/sysdev/ipic.c                    |  3 ++-
 arch/powerpc/sysdev/mpic.c                    |  3 ++-
 arch/powerpc/sysdev/mpic_msi.c                |  2 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c            |  3 ++-
 drivers/gpio/gpio-sodaville.c                 |  2 +-
 drivers/irqchip/exynos-combiner.c             |  2 +-
 drivers/irqchip/irq-atmel-aic-common.c        |  2 +-
 drivers/irqchip/irq-crossbar.c                |  4 ++--
 drivers/irqchip/irq-gic-v2m.c                 |  2 +-
 drivers/irqchip/irq-gic-v3-its.c              |  2 +-
 drivers/irqchip/irq-gic-v3.c                  |  2 +-
 drivers/irqchip/irq-gic.c                     |  2 +-
 drivers/irqchip/irq-hip04.c                   |  2 +-
 drivers/irqchip/irq-imx-gpcv2.c               |  2 +-
 drivers/irqchip/irq-mtk-sysirq.c              |  2 +-
 drivers/irqchip/irq-s3c24xx.c                 |  4 ++--
 drivers/irqchip/irq-tegra.c                   |  4 ++--
 drivers/irqchip/irq-vf610-mscm-ir.c           |  5 +++--
 drivers/spmi/spmi-pmic-arb.c                  |  2 +-
 include/linux/irqdomain.h                     |  5 +++++
 kernel/irq/irqdomain.c                        | 30 +++++++++++++++++++--------
 31 files changed, 74 insertions(+), 46 deletions(-)

diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index e1d2e99..a52fe5b 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -441,7 +441,7 @@ static int wakeupgen_domain_alloc(struct irq_domain *domain,
 					      &wakeupgen_chip, NULL);
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
 }
 
diff --git a/arch/c6x/platforms/megamod-pic.c b/arch/c6x/platforms/megamod-pic.c
index ddcb45d..43afc03 100644
--- a/arch/c6x/platforms/megamod-pic.c
+++ b/arch/c6x/platforms/megamod-pic.c
@@ -178,7 +178,7 @@ static void __init set_megamod_mux(struct megamod_pic *pic, int src, int output)
 static void __init parse_priority_map(struct megamod_pic *pic,
 				      int *mapping, int size)
 {
-	struct device_node *np = pic->irqhost->of_node;
+	struct device_node *np = irq_domain_get_of_node(pic->irqhost);
 	const __be32 *map;
 	int i, maplen;
 	u32 val;
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 0352bc8..4f9eb05 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -1094,7 +1094,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
 	unsigned int pin;
 	unsigned int trigger;
 
-	if (d->of_node != node)
+	if (irq_domain_get_of_node(d) != node)
 		return -EINVAL;
 
 	if (intsize < 2)
@@ -2163,7 +2163,7 @@ static int octeon_irq_cib_map(struct irq_domain *d,
 
 	if (hw >= host_data->max_bits) {
 		pr_err("ERROR: %s mapping %u is to big!\n",
-		       d->of_node->name, (unsigned)hw);
+		       irq_domain_get_of_node(d)->name, (unsigned)hw);
 		return -EINVAL;
 	}
 
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index e0e68a1..aed7714 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -327,7 +327,7 @@ static void axon_msi_shutdown(struct platform_device *device)
 	u32 tmp;
 
 	pr_devel("axon_msi: disabling %s\n",
-		  msic->irq_domain->of_node->full_name);
+		 irq_domain_get_of_node(msic->irq_domain)->full_name);
 	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 9d27de6..54ee574 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -231,20 +231,23 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
 	const u32 *imap, *tmp;
 	int imaplen, intsize, unit;
 	struct device_node *iic;
+	struct device_node *of_node;
+
+	of_node = irq_domain_get_of_node(pic->host);
 
 	/* First, we check whether we have a real "interrupts" in the device
 	 * tree in case the device-tree is ever fixed
 	 */
-	virq = irq_of_parse_and_map(pic->host->of_node, 0);
+	virq = irq_of_parse_and_map(of_node, 0);
 	if (virq)
 		return virq;
 
 	/* Now do the horrible hacks */
-	tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
+	tmp = of_get_property(of_node, "#interrupt-cells", NULL);
 	if (tmp == NULL)
 		return NO_IRQ;
 	intsize = *tmp;
-	imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen);
+	imap = of_get_property(of_node, "interrupt-map", &imaplen);
 	if (imap == NULL || imaplen < (intsize + 1))
 		return NO_IRQ;
 	iic = of_find_node_by_phandle(imap[intsize]);
diff --git a/arch/powerpc/platforms/pasemi/msi.c b/arch/powerpc/platforms/pasemi/msi.c
index b304a9f..d9af763 100644
--- a/arch/powerpc/platforms/pasemi/msi.c
+++ b/arch/powerpc/platforms/pasemi/msi.c
@@ -144,9 +144,11 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
 {
 	int rc;
 	struct pci_controller *phb;
+	struct device_node *of_node;
 
-	if (!mpic->irqhost->of_node ||
-	    !of_device_is_compatible(mpic->irqhost->of_node,
+	of_node = irq_domain_get_of_node(mpic->irqhost);
+	if (!of_node ||
+	    !of_device_is_compatible(of_node,
 				     "pasemi,pwrficient-openpic"))
 		return -ENODEV;
 
diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c
index 2c91ee7..6ccfb6c 100644
--- a/arch/powerpc/platforms/powernv/opal-irqchip.c
+++ b/arch/powerpc/platforms/powernv/opal-irqchip.c
@@ -137,7 +137,7 @@ static void opal_handle_irq_work(struct irq_work *work)
 static int opal_event_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
-	return h->of_node == node;
+	return irq_domain_get_of_node(h) == node;
 }
 
 static int opal_event_xlate(struct irq_domain *h, struct device_node *np,
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
index eca0b00..bffcc7a 100644
--- a/arch/powerpc/sysdev/ehv_pic.c
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -181,7 +181,8 @@ static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node,
 			      enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless ehv_pic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int ehv_pic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 48a576a..3a2be36 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -110,7 +110,7 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
 	int rc, hwirq;
 
 	rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS_MAX,
-			      msi_data->irqhost->of_node);
+			      irq_domain_get_of_node(msi_data->irqhost));
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index e1a9c2c..6f99ed3 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -165,7 +165,8 @@ static struct resource pic_edgectrl_iores = {
 static int i8259_host_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int i8259_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index b1297ab..f76ee39 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -675,7 +675,8 @@ static int ipic_host_match(struct irq_domain *h, struct device_node *node,
 			   enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless ipic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int ipic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 537e5db..cecd115 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1011,7 +1011,8 @@ static int mpic_host_match(struct irq_domain *h, struct device_node *node,
 			   enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless mpic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int mpic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 7dc39f3..1d48a53 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -84,7 +84,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
 	int rc;
 
 	rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->num_sources,
-			      mpic->irqhost->of_node);
+			      irq_domain_get_of_node(mpic->irqhost));
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index fbcc1f8..ef36f16 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -248,7 +248,8 @@ static int qe_ic_host_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless qe_ic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 65bc9f4..34b02b4 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -102,7 +102,7 @@ static int sdv_xlate(struct irq_domain *h, struct device_node *node,
 {
 	u32 line, type;
 
-	if (node != h->of_node)
+	if (node != irq_domain_get_of_node(h))
 		return -EINVAL;
 
 	if (intsize < 2)
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index cd7d3bc..ead15be 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -144,7 +144,7 @@ static int combiner_irq_domain_xlate(struct irq_domain *d,
 				     unsigned long *out_hwirq,
 				     unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 
 	if (intsize < 2)
diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c
index 63cd031..b12a5d5 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -114,7 +114,7 @@ int aic_common_irq_domain_xlate(struct irq_domain *d,
 
 static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
 {
-	struct device_node *node = domain->of_node;
+	struct device_node *node = irq_domain_get_of_node(domain);
 	struct irq_chip_generic *gc;
 	struct aic_chip_data *aic;
 	struct property *prop;
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index a7f5626..f1d666a 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -94,7 +94,7 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 	if (i < 0)
 		return -ENODEV;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = 0;	/* SPI */
 	args.args[1] = i;
@@ -172,7 +172,7 @@ static int crossbar_domain_xlate(struct irq_domain *d,
 				 unsigned long *out_hwirq,
 				 unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;	/* Shouldn't happen, really... */
 	if (intsize != 3)
 		return -EINVAL;	/* Not GIC compliant */
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 12985da..695d489 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -117,7 +117,7 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
 	struct irq_data *d;
 	int err;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = 0;
 	args.args[1] = hwirq - 32;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 25ceae9f..ea4e5b2 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1243,7 +1243,7 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 {
 	struct of_phandle_args args;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = GIC_IRQ_TYPE_LPI;
 	args.args[1] = hwirq;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 36ecfc8..4c97ab6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -776,7 +776,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 				const u32 *intspec, unsigned int intsize,
 				unsigned long *out_hwirq, unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 982c09c..7f53acb 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -910,7 +910,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 {
 	unsigned long ret = 0;
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index 8f3ca8f..9688d2e 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -325,7 +325,7 @@ static int hip04_irq_domain_xlate(struct irq_domain *d,
 {
 	unsigned long ret = 0;
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index e48d330..8bba3c0 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -202,7 +202,7 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 	}
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
 }
 
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index c8753da..b072166 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -106,7 +106,7 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 					      &mtk_sysirq_chip,
 					      domain->host_data);
 
-	gic_data.np = domain->parent->of_node;
+	gic_data.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
 }
 
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index 7154b01..c71914e 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -311,7 +311,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
 	 * and one big domain for the dt case where the subintc
 	 * starts at hwirq number 32.
 	 */
-	offset = (intc->domain->of_node) ? 32 : 0;
+	offset = irq_domain_get_of_node(intc->domain) ? 32 : 0;
 
 	chained_irq_enter(chip, desc);
 
@@ -342,7 +342,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
 		return false;
 
 	/* non-dt machines use individual domains */
-	if (!intc->domain->of_node)
+	if (!irq_domain_get_of_node(intc->domain))
 		intc_offset = 0;
 
 	/* We have a problem that the INTOFFSET register does not always
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 2fd89eb..7bbf226 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -227,7 +227,7 @@ static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
 				    unsigned long *out_hwirq,
 				    unsigned int *out_type)
 {
-	if (domain->of_node != controller)
+	if (irq_domain_get_of_node(domain) != controller)
 		return -EINVAL;	/* Shouldn't happen, really... */
 	if (intsize != 3)
 		return -EINVAL;	/* Not GIC compliant */
@@ -267,7 +267,7 @@ static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 	}
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
 }
 
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
index 2c22558..ae82d7e 100644
--- a/drivers/irqchip/irq-vf610-mscm-ir.c
+++ b/drivers/irqchip/irq-vf610-mscm-ir.c
@@ -142,7 +142,7 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
 					      &vf610_mscm_ir_irq_chip,
 					      domain->host_data);
 
-	gic_data.np = domain->parent->of_node;
+	gic_data.np = irq_domain_get_of_node(domain->parent);
 
 	if (mscm_ir_data->is_nvic) {
 		gic_data.args_count = 1;
@@ -205,7 +205,8 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node,
 		goto out_unmap;
 	}
 
-	if (of_device_is_compatible(domain->parent->of_node, "arm,armv7m-nvic"))
+	if (of_device_is_compatible(irq_domain_get_of_node(domain->parent),
+				    "arm,armv7m-nvic"))
 		mscm_ir_data->is_nvic = true;
 
 	cpu_pm_register_notifier(&mscm_ir_notifier_block);
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 4a3cf9b..fb36810 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -657,7 +657,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 		"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
 		intspec[0], intspec[1], intspec[2]);
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize != 4)
 		return -EINVAL;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index d3ca792..f644fdb 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -161,6 +161,11 @@ enum {
 	IRQ_DOMAIN_FLAG_NONCORE		= (1 << 16),
 };
 
+static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
+{
+	return d->of_node;
+}
+
 #ifdef CONFIG_IRQ_DOMAIN
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index dc9d27c..8f8b538 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -102,7 +102,7 @@ void irq_domain_remove(struct irq_domain *domain)
 
 	pr_debug("Removed domain %s\n", domain->name);
 
-	of_node_put(domain->of_node);
+	of_node_put(irq_domain_get_of_node(domain));
 	kfree(domain);
 }
 EXPORT_SYMBOL_GPL(irq_domain_remove);
@@ -208,10 +208,12 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
+		struct device_node *of_node;
+		of_node = irq_domain_get_of_node(h);
 		if (h->ops->match)
 			rc = h->ops->match(h, node, bus_token);
 		else
-			rc = ((h->of_node != NULL) && (h->of_node == node) &&
+			rc = ((of_node != NULL) && (of_node == node) &&
 			      ((bus_token == DOMAIN_BUS_ANY) ||
 			       (h->bus_token == bus_token)));
 
@@ -336,10 +338,12 @@ EXPORT_SYMBOL_GPL(irq_domain_associate);
 void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
 			       irq_hw_number_t hwirq_base, int count)
 {
+	struct device_node *of_node;
 	int i;
 
+	of_node = irq_domain_get_of_node(domain);
 	pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
-		of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
+		of_node_full_name(of_node), irq_base, (int)hwirq_base, count);
 
 	for (i = 0; i < count; i++) {
 		irq_domain_associate(domain, irq_base + i, hwirq_base + i);
@@ -359,12 +363,14 @@ EXPORT_SYMBOL_GPL(irq_domain_associate_many);
  */
 unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 {
+	struct device_node *of_node;
 	unsigned int virq;
 
 	if (domain == NULL)
 		domain = irq_default_domain;
 
-	virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
+	of_node = irq_domain_get_of_node(domain);
+	virq = irq_alloc_desc_from(1, of_node_to_nid(of_node));
 	if (!virq) {
 		pr_debug("create_direct virq allocation failed\n");
 		return 0;
@@ -399,6 +405,7 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 unsigned int irq_create_mapping(struct irq_domain *domain,
 				irq_hw_number_t hwirq)
 {
+	struct device_node *of_node;
 	int virq;
 
 	pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
@@ -412,6 +419,8 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 	pr_debug("-> using domain @%p\n", domain);
 
+	of_node = irq_domain_get_of_node(domain);
+
 	/* Check if mapping already exists */
 	virq = irq_find_mapping(domain, hwirq);
 	if (virq) {
@@ -420,8 +429,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 
 	/* Allocate a virtual interrupt number */
-	virq = irq_domain_alloc_descs(-1, 1, hwirq,
-				      of_node_to_nid(domain->of_node));
+	virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node));
 	if (virq <= 0) {
 		pr_debug("-> virq allocation failed\n");
 		return 0;
@@ -433,7 +441,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 
 	pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
-		hwirq, of_node_full_name(domain->of_node), virq);
+		hwirq, of_node_full_name(of_node), virq);
 
 	return virq;
 }
@@ -460,10 +468,12 @@ EXPORT_SYMBOL_GPL(irq_create_mapping);
 int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
 			       irq_hw_number_t hwirq_base, int count)
 {
+	struct device_node *of_node;
 	int ret;
 
+	of_node = irq_domain_get_of_node(domain);
 	ret = irq_alloc_descs(irq_base, irq_base, count,
-			      of_node_to_nid(domain->of_node));
+			      of_node_to_nid(of_node));
 	if (unlikely(ret < 0))
 		return ret;
 
@@ -590,14 +600,16 @@ static int virq_debug_show(struct seq_file *m, void *private)
 		   "name", "mapped", "linear-max", "direct-max", "devtree-node");
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(domain, &irq_domain_list, link) {
+		struct device_node *of_node;
 		int count = 0;
+		of_node = irq_domain_get_of_node(domain);
 		radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0)
 			count++;
 		seq_printf(m, "%c%-16s  %6u  %10u  %10u  %s\n",
 			   domain == irq_default_domain ? '*' : ' ', domain->name,
 			   domain->revmap_size + count, domain->revmap_size,
 			   domain->revmap_direct_max_irq,
-			   domain->of_node ? of_node_full_name(domain->of_node) : "");
+			   of_node ? of_node_full_name(of_node) : "");
 	}
 	mutex_unlock(&irq_domain_mutex);
 
-- 
2.1.4

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

* [PATCH 01/16] irqdomain: Use an accessor for the of_node field
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

The struct irq_domain contains a "struct device_node *" field
(of_node) that is almost the only link between the irqdomain
and the device tree infrastructure.

In order to prepare for the removal of that field, convert all
users to use an accessor.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-omap2/omap-wakeupgen.c          |  2 +-
 arch/c6x/platforms/megamod-pic.c              |  2 +-
 arch/mips/cavium-octeon/octeon-irq.c          |  4 ++--
 arch/powerpc/platforms/cell/axon_msi.c        |  2 +-
 arch/powerpc/platforms/cell/spider-pic.c      |  9 +++++---
 arch/powerpc/platforms/pasemi/msi.c           |  6 ++++--
 arch/powerpc/platforms/powernv/opal-irqchip.c |  2 +-
 arch/powerpc/sysdev/ehv_pic.c                 |  3 ++-
 arch/powerpc/sysdev/fsl_msi.c                 |  2 +-
 arch/powerpc/sysdev/i8259.c                   |  3 ++-
 arch/powerpc/sysdev/ipic.c                    |  3 ++-
 arch/powerpc/sysdev/mpic.c                    |  3 ++-
 arch/powerpc/sysdev/mpic_msi.c                |  2 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c            |  3 ++-
 drivers/gpio/gpio-sodaville.c                 |  2 +-
 drivers/irqchip/exynos-combiner.c             |  2 +-
 drivers/irqchip/irq-atmel-aic-common.c        |  2 +-
 drivers/irqchip/irq-crossbar.c                |  4 ++--
 drivers/irqchip/irq-gic-v2m.c                 |  2 +-
 drivers/irqchip/irq-gic-v3-its.c              |  2 +-
 drivers/irqchip/irq-gic-v3.c                  |  2 +-
 drivers/irqchip/irq-gic.c                     |  2 +-
 drivers/irqchip/irq-hip04.c                   |  2 +-
 drivers/irqchip/irq-imx-gpcv2.c               |  2 +-
 drivers/irqchip/irq-mtk-sysirq.c              |  2 +-
 drivers/irqchip/irq-s3c24xx.c                 |  4 ++--
 drivers/irqchip/irq-tegra.c                   |  4 ++--
 drivers/irqchip/irq-vf610-mscm-ir.c           |  5 +++--
 drivers/spmi/spmi-pmic-arb.c                  |  2 +-
 include/linux/irqdomain.h                     |  5 +++++
 kernel/irq/irqdomain.c                        | 30 +++++++++++++++++++--------
 31 files changed, 74 insertions(+), 46 deletions(-)

diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index e1d2e99..a52fe5b 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -441,7 +441,7 @@ static int wakeupgen_domain_alloc(struct irq_domain *domain,
 					      &wakeupgen_chip, NULL);
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
 }
 
diff --git a/arch/c6x/platforms/megamod-pic.c b/arch/c6x/platforms/megamod-pic.c
index ddcb45d..43afc03 100644
--- a/arch/c6x/platforms/megamod-pic.c
+++ b/arch/c6x/platforms/megamod-pic.c
@@ -178,7 +178,7 @@ static void __init set_megamod_mux(struct megamod_pic *pic, int src, int output)
 static void __init parse_priority_map(struct megamod_pic *pic,
 				      int *mapping, int size)
 {
-	struct device_node *np = pic->irqhost->of_node;
+	struct device_node *np = irq_domain_get_of_node(pic->irqhost);
 	const __be32 *map;
 	int i, maplen;
 	u32 val;
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 0352bc8..4f9eb05 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -1094,7 +1094,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
 	unsigned int pin;
 	unsigned int trigger;
 
-	if (d->of_node != node)
+	if (irq_domain_get_of_node(d) != node)
 		return -EINVAL;
 
 	if (intsize < 2)
@@ -2163,7 +2163,7 @@ static int octeon_irq_cib_map(struct irq_domain *d,
 
 	if (hw >= host_data->max_bits) {
 		pr_err("ERROR: %s mapping %u is to big!\n",
-		       d->of_node->name, (unsigned)hw);
+		       irq_domain_get_of_node(d)->name, (unsigned)hw);
 		return -EINVAL;
 	}
 
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index e0e68a1..aed7714 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -327,7 +327,7 @@ static void axon_msi_shutdown(struct platform_device *device)
 	u32 tmp;
 
 	pr_devel("axon_msi: disabling %s\n",
-		  msic->irq_domain->of_node->full_name);
+		 irq_domain_get_of_node(msic->irq_domain)->full_name);
 	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 9d27de6..54ee574 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -231,20 +231,23 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
 	const u32 *imap, *tmp;
 	int imaplen, intsize, unit;
 	struct device_node *iic;
+	struct device_node *of_node;
+
+	of_node = irq_domain_get_of_node(pic->host);
 
 	/* First, we check whether we have a real "interrupts" in the device
 	 * tree in case the device-tree is ever fixed
 	 */
-	virq = irq_of_parse_and_map(pic->host->of_node, 0);
+	virq = irq_of_parse_and_map(of_node, 0);
 	if (virq)
 		return virq;
 
 	/* Now do the horrible hacks */
-	tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
+	tmp = of_get_property(of_node, "#interrupt-cells", NULL);
 	if (tmp == NULL)
 		return NO_IRQ;
 	intsize = *tmp;
-	imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen);
+	imap = of_get_property(of_node, "interrupt-map", &imaplen);
 	if (imap == NULL || imaplen < (intsize + 1))
 		return NO_IRQ;
 	iic = of_find_node_by_phandle(imap[intsize]);
diff --git a/arch/powerpc/platforms/pasemi/msi.c b/arch/powerpc/platforms/pasemi/msi.c
index b304a9f..d9af763 100644
--- a/arch/powerpc/platforms/pasemi/msi.c
+++ b/arch/powerpc/platforms/pasemi/msi.c
@@ -144,9 +144,11 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
 {
 	int rc;
 	struct pci_controller *phb;
+	struct device_node *of_node;
 
-	if (!mpic->irqhost->of_node ||
-	    !of_device_is_compatible(mpic->irqhost->of_node,
+	of_node = irq_domain_get_of_node(mpic->irqhost);
+	if (!of_node ||
+	    !of_device_is_compatible(of_node,
 				     "pasemi,pwrficient-openpic"))
 		return -ENODEV;
 
diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c
index 2c91ee7..6ccfb6c 100644
--- a/arch/powerpc/platforms/powernv/opal-irqchip.c
+++ b/arch/powerpc/platforms/powernv/opal-irqchip.c
@@ -137,7 +137,7 @@ static void opal_handle_irq_work(struct irq_work *work)
 static int opal_event_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
-	return h->of_node == node;
+	return irq_domain_get_of_node(h) == node;
 }
 
 static int opal_event_xlate(struct irq_domain *h, struct device_node *np,
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
index eca0b00..bffcc7a 100644
--- a/arch/powerpc/sysdev/ehv_pic.c
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -181,7 +181,8 @@ static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node,
 			      enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless ehv_pic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int ehv_pic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 48a576a..3a2be36 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -110,7 +110,7 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
 	int rc, hwirq;
 
 	rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS_MAX,
-			      msi_data->irqhost->of_node);
+			      irq_domain_get_of_node(msi_data->irqhost));
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index e1a9c2c..6f99ed3 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -165,7 +165,8 @@ static struct resource pic_edgectrl_iores = {
 static int i8259_host_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int i8259_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index b1297ab..f76ee39 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -675,7 +675,8 @@ static int ipic_host_match(struct irq_domain *h, struct device_node *node,
 			   enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless ipic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int ipic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 537e5db..cecd115 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1011,7 +1011,8 @@ static int mpic_host_match(struct irq_domain *h, struct device_node *node,
 			   enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless mpic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int mpic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 7dc39f3..1d48a53 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -84,7 +84,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
 	int rc;
 
 	rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->num_sources,
-			      mpic->irqhost->of_node);
+			      irq_domain_get_of_node(mpic->irqhost));
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index fbcc1f8..ef36f16 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -248,7 +248,8 @@ static int qe_ic_host_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless qe_ic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 65bc9f4..34b02b4 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -102,7 +102,7 @@ static int sdv_xlate(struct irq_domain *h, struct device_node *node,
 {
 	u32 line, type;
 
-	if (node != h->of_node)
+	if (node != irq_domain_get_of_node(h))
 		return -EINVAL;
 
 	if (intsize < 2)
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index cd7d3bc..ead15be 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -144,7 +144,7 @@ static int combiner_irq_domain_xlate(struct irq_domain *d,
 				     unsigned long *out_hwirq,
 				     unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 
 	if (intsize < 2)
diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c
index 63cd031..b12a5d5 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -114,7 +114,7 @@ int aic_common_irq_domain_xlate(struct irq_domain *d,
 
 static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
 {
-	struct device_node *node = domain->of_node;
+	struct device_node *node = irq_domain_get_of_node(domain);
 	struct irq_chip_generic *gc;
 	struct aic_chip_data *aic;
 	struct property *prop;
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index a7f5626..f1d666a 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -94,7 +94,7 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 	if (i < 0)
 		return -ENODEV;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = 0;	/* SPI */
 	args.args[1] = i;
@@ -172,7 +172,7 @@ static int crossbar_domain_xlate(struct irq_domain *d,
 				 unsigned long *out_hwirq,
 				 unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;	/* Shouldn't happen, really... */
 	if (intsize != 3)
 		return -EINVAL;	/* Not GIC compliant */
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 12985da..695d489 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -117,7 +117,7 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
 	struct irq_data *d;
 	int err;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = 0;
 	args.args[1] = hwirq - 32;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 25ceae9f..ea4e5b2 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1243,7 +1243,7 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 {
 	struct of_phandle_args args;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = GIC_IRQ_TYPE_LPI;
 	args.args[1] = hwirq;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 36ecfc8..4c97ab6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -776,7 +776,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 				const u32 *intspec, unsigned int intsize,
 				unsigned long *out_hwirq, unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 982c09c..7f53acb 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -910,7 +910,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 {
 	unsigned long ret = 0;
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index 8f3ca8f..9688d2e 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -325,7 +325,7 @@ static int hip04_irq_domain_xlate(struct irq_domain *d,
 {
 	unsigned long ret = 0;
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index e48d330..8bba3c0 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -202,7 +202,7 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 	}
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
 }
 
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index c8753da..b072166 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -106,7 +106,7 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 					      &mtk_sysirq_chip,
 					      domain->host_data);
 
-	gic_data.np = domain->parent->of_node;
+	gic_data.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
 }
 
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index 7154b01..c71914e 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -311,7 +311,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
 	 * and one big domain for the dt case where the subintc
 	 * starts at hwirq number 32.
 	 */
-	offset = (intc->domain->of_node) ? 32 : 0;
+	offset = irq_domain_get_of_node(intc->domain) ? 32 : 0;
 
 	chained_irq_enter(chip, desc);
 
@@ -342,7 +342,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
 		return false;
 
 	/* non-dt machines use individual domains */
-	if (!intc->domain->of_node)
+	if (!irq_domain_get_of_node(intc->domain))
 		intc_offset = 0;
 
 	/* We have a problem that the INTOFFSET register does not always
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 2fd89eb..7bbf226 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -227,7 +227,7 @@ static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
 				    unsigned long *out_hwirq,
 				    unsigned int *out_type)
 {
-	if (domain->of_node != controller)
+	if (irq_domain_get_of_node(domain) != controller)
 		return -EINVAL;	/* Shouldn't happen, really... */
 	if (intsize != 3)
 		return -EINVAL;	/* Not GIC compliant */
@@ -267,7 +267,7 @@ static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 	}
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
 }
 
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
index 2c22558..ae82d7e 100644
--- a/drivers/irqchip/irq-vf610-mscm-ir.c
+++ b/drivers/irqchip/irq-vf610-mscm-ir.c
@@ -142,7 +142,7 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
 					      &vf610_mscm_ir_irq_chip,
 					      domain->host_data);
 
-	gic_data.np = domain->parent->of_node;
+	gic_data.np = irq_domain_get_of_node(domain->parent);
 
 	if (mscm_ir_data->is_nvic) {
 		gic_data.args_count = 1;
@@ -205,7 +205,8 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node,
 		goto out_unmap;
 	}
 
-	if (of_device_is_compatible(domain->parent->of_node, "arm,armv7m-nvic"))
+	if (of_device_is_compatible(irq_domain_get_of_node(domain->parent),
+				    "arm,armv7m-nvic"))
 		mscm_ir_data->is_nvic = true;
 
 	cpu_pm_register_notifier(&mscm_ir_notifier_block);
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 4a3cf9b..fb36810 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -657,7 +657,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 		"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
 		intspec[0], intspec[1], intspec[2]);
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize != 4)
 		return -EINVAL;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index d3ca792..f644fdb 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -161,6 +161,11 @@ enum {
 	IRQ_DOMAIN_FLAG_NONCORE		= (1 << 16),
 };
 
+static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
+{
+	return d->of_node;
+}
+
 #ifdef CONFIG_IRQ_DOMAIN
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index dc9d27c..8f8b538 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -102,7 +102,7 @@ void irq_domain_remove(struct irq_domain *domain)
 
 	pr_debug("Removed domain %s\n", domain->name);
 
-	of_node_put(domain->of_node);
+	of_node_put(irq_domain_get_of_node(domain));
 	kfree(domain);
 }
 EXPORT_SYMBOL_GPL(irq_domain_remove);
@@ -208,10 +208,12 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
+		struct device_node *of_node;
+		of_node = irq_domain_get_of_node(h);
 		if (h->ops->match)
 			rc = h->ops->match(h, node, bus_token);
 		else
-			rc = ((h->of_node != NULL) && (h->of_node == node) &&
+			rc = ((of_node != NULL) && (of_node == node) &&
 			      ((bus_token == DOMAIN_BUS_ANY) ||
 			       (h->bus_token == bus_token)));
 
@@ -336,10 +338,12 @@ EXPORT_SYMBOL_GPL(irq_domain_associate);
 void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
 			       irq_hw_number_t hwirq_base, int count)
 {
+	struct device_node *of_node;
 	int i;
 
+	of_node = irq_domain_get_of_node(domain);
 	pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
-		of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
+		of_node_full_name(of_node), irq_base, (int)hwirq_base, count);
 
 	for (i = 0; i < count; i++) {
 		irq_domain_associate(domain, irq_base + i, hwirq_base + i);
@@ -359,12 +363,14 @@ EXPORT_SYMBOL_GPL(irq_domain_associate_many);
  */
 unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 {
+	struct device_node *of_node;
 	unsigned int virq;
 
 	if (domain == NULL)
 		domain = irq_default_domain;
 
-	virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
+	of_node = irq_domain_get_of_node(domain);
+	virq = irq_alloc_desc_from(1, of_node_to_nid(of_node));
 	if (!virq) {
 		pr_debug("create_direct virq allocation failed\n");
 		return 0;
@@ -399,6 +405,7 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 unsigned int irq_create_mapping(struct irq_domain *domain,
 				irq_hw_number_t hwirq)
 {
+	struct device_node *of_node;
 	int virq;
 
 	pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
@@ -412,6 +419,8 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 	pr_debug("-> using domain @%p\n", domain);
 
+	of_node = irq_domain_get_of_node(domain);
+
 	/* Check if mapping already exists */
 	virq = irq_find_mapping(domain, hwirq);
 	if (virq) {
@@ -420,8 +429,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 
 	/* Allocate a virtual interrupt number */
-	virq = irq_domain_alloc_descs(-1, 1, hwirq,
-				      of_node_to_nid(domain->of_node));
+	virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node));
 	if (virq <= 0) {
 		pr_debug("-> virq allocation failed\n");
 		return 0;
@@ -433,7 +441,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 
 	pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
-		hwirq, of_node_full_name(domain->of_node), virq);
+		hwirq, of_node_full_name(of_node), virq);
 
 	return virq;
 }
@@ -460,10 +468,12 @@ EXPORT_SYMBOL_GPL(irq_create_mapping);
 int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
 			       irq_hw_number_t hwirq_base, int count)
 {
+	struct device_node *of_node;
 	int ret;
 
+	of_node = irq_domain_get_of_node(domain);
 	ret = irq_alloc_descs(irq_base, irq_base, count,
-			      of_node_to_nid(domain->of_node));
+			      of_node_to_nid(of_node));
 	if (unlikely(ret < 0))
 		return ret;
 
@@ -590,14 +600,16 @@ static int virq_debug_show(struct seq_file *m, void *private)
 		   "name", "mapped", "linear-max", "direct-max", "devtree-node");
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(domain, &irq_domain_list, link) {
+		struct device_node *of_node;
 		int count = 0;
+		of_node = irq_domain_get_of_node(domain);
 		radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0)
 			count++;
 		seq_printf(m, "%c%-16s  %6u  %10u  %10u  %s\n",
 			   domain == irq_default_domain ? '*' : ' ', domain->name,
 			   domain->revmap_size + count, domain->revmap_size,
 			   domain->revmap_direct_max_irq,
-			   domain->of_node ? of_node_full_name(domain->of_node) : "");
+			   of_node ? of_node_full_name(of_node) : "");
 	}
 	mutex_unlock(&irq_domain_mutex);
 
-- 
2.1.4


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

* [PATCH 01/16] irqdomain: Use an accessor for the of_node field
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

The struct irq_domain contains a "struct device_node *" field
(of_node) that is almost the only link between the irqdomain
and the device tree infrastructure.

In order to prepare for the removal of that field, convert all
users to use an accessor.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-omap2/omap-wakeupgen.c          |  2 +-
 arch/c6x/platforms/megamod-pic.c              |  2 +-
 arch/mips/cavium-octeon/octeon-irq.c          |  4 ++--
 arch/powerpc/platforms/cell/axon_msi.c        |  2 +-
 arch/powerpc/platforms/cell/spider-pic.c      |  9 +++++---
 arch/powerpc/platforms/pasemi/msi.c           |  6 ++++--
 arch/powerpc/platforms/powernv/opal-irqchip.c |  2 +-
 arch/powerpc/sysdev/ehv_pic.c                 |  3 ++-
 arch/powerpc/sysdev/fsl_msi.c                 |  2 +-
 arch/powerpc/sysdev/i8259.c                   |  3 ++-
 arch/powerpc/sysdev/ipic.c                    |  3 ++-
 arch/powerpc/sysdev/mpic.c                    |  3 ++-
 arch/powerpc/sysdev/mpic_msi.c                |  2 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c            |  3 ++-
 drivers/gpio/gpio-sodaville.c                 |  2 +-
 drivers/irqchip/exynos-combiner.c             |  2 +-
 drivers/irqchip/irq-atmel-aic-common.c        |  2 +-
 drivers/irqchip/irq-crossbar.c                |  4 ++--
 drivers/irqchip/irq-gic-v2m.c                 |  2 +-
 drivers/irqchip/irq-gic-v3-its.c              |  2 +-
 drivers/irqchip/irq-gic-v3.c                  |  2 +-
 drivers/irqchip/irq-gic.c                     |  2 +-
 drivers/irqchip/irq-hip04.c                   |  2 +-
 drivers/irqchip/irq-imx-gpcv2.c               |  2 +-
 drivers/irqchip/irq-mtk-sysirq.c              |  2 +-
 drivers/irqchip/irq-s3c24xx.c                 |  4 ++--
 drivers/irqchip/irq-tegra.c                   |  4 ++--
 drivers/irqchip/irq-vf610-mscm-ir.c           |  5 +++--
 drivers/spmi/spmi-pmic-arb.c                  |  2 +-
 include/linux/irqdomain.h                     |  5 +++++
 kernel/irq/irqdomain.c                        | 30 +++++++++++++++++++--------
 31 files changed, 74 insertions(+), 46 deletions(-)

diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index e1d2e99..a52fe5b 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -441,7 +441,7 @@ static int wakeupgen_domain_alloc(struct irq_domain *domain,
 					      &wakeupgen_chip, NULL);
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
 }
 
diff --git a/arch/c6x/platforms/megamod-pic.c b/arch/c6x/platforms/megamod-pic.c
index ddcb45d..43afc03 100644
--- a/arch/c6x/platforms/megamod-pic.c
+++ b/arch/c6x/platforms/megamod-pic.c
@@ -178,7 +178,7 @@ static void __init set_megamod_mux(struct megamod_pic *pic, int src, int output)
 static void __init parse_priority_map(struct megamod_pic *pic,
 				      int *mapping, int size)
 {
-	struct device_node *np = pic->irqhost->of_node;
+	struct device_node *np = irq_domain_get_of_node(pic->irqhost);
 	const __be32 *map;
 	int i, maplen;
 	u32 val;
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 0352bc8..4f9eb05 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -1094,7 +1094,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
 	unsigned int pin;
 	unsigned int trigger;
 
-	if (d->of_node != node)
+	if (irq_domain_get_of_node(d) != node)
 		return -EINVAL;
 
 	if (intsize < 2)
@@ -2163,7 +2163,7 @@ static int octeon_irq_cib_map(struct irq_domain *d,
 
 	if (hw >= host_data->max_bits) {
 		pr_err("ERROR: %s mapping %u is to big!\n",
-		       d->of_node->name, (unsigned)hw);
+		       irq_domain_get_of_node(d)->name, (unsigned)hw);
 		return -EINVAL;
 	}
 
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index e0e68a1..aed7714 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -327,7 +327,7 @@ static void axon_msi_shutdown(struct platform_device *device)
 	u32 tmp;
 
 	pr_devel("axon_msi: disabling %s\n",
-		  msic->irq_domain->of_node->full_name);
+		 irq_domain_get_of_node(msic->irq_domain)->full_name);
 	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 9d27de6..54ee574 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -231,20 +231,23 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
 	const u32 *imap, *tmp;
 	int imaplen, intsize, unit;
 	struct device_node *iic;
+	struct device_node *of_node;
+
+	of_node = irq_domain_get_of_node(pic->host);
 
 	/* First, we check whether we have a real "interrupts" in the device
 	 * tree in case the device-tree is ever fixed
 	 */
-	virq = irq_of_parse_and_map(pic->host->of_node, 0);
+	virq = irq_of_parse_and_map(of_node, 0);
 	if (virq)
 		return virq;
 
 	/* Now do the horrible hacks */
-	tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
+	tmp = of_get_property(of_node, "#interrupt-cells", NULL);
 	if (tmp == NULL)
 		return NO_IRQ;
 	intsize = *tmp;
-	imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen);
+	imap = of_get_property(of_node, "interrupt-map", &imaplen);
 	if (imap == NULL || imaplen < (intsize + 1))
 		return NO_IRQ;
 	iic = of_find_node_by_phandle(imap[intsize]);
diff --git a/arch/powerpc/platforms/pasemi/msi.c b/arch/powerpc/platforms/pasemi/msi.c
index b304a9f..d9af763 100644
--- a/arch/powerpc/platforms/pasemi/msi.c
+++ b/arch/powerpc/platforms/pasemi/msi.c
@@ -144,9 +144,11 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
 {
 	int rc;
 	struct pci_controller *phb;
+	struct device_node *of_node;
 
-	if (!mpic->irqhost->of_node ||
-	    !of_device_is_compatible(mpic->irqhost->of_node,
+	of_node = irq_domain_get_of_node(mpic->irqhost);
+	if (!of_node ||
+	    !of_device_is_compatible(of_node,
 				     "pasemi,pwrficient-openpic"))
 		return -ENODEV;
 
diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c
index 2c91ee7..6ccfb6c 100644
--- a/arch/powerpc/platforms/powernv/opal-irqchip.c
+++ b/arch/powerpc/platforms/powernv/opal-irqchip.c
@@ -137,7 +137,7 @@ static void opal_handle_irq_work(struct irq_work *work)
 static int opal_event_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
-	return h->of_node == node;
+	return irq_domain_get_of_node(h) == node;
 }
 
 static int opal_event_xlate(struct irq_domain *h, struct device_node *np,
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
index eca0b00..bffcc7a 100644
--- a/arch/powerpc/sysdev/ehv_pic.c
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -181,7 +181,8 @@ static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node,
 			      enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless ehv_pic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int ehv_pic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 48a576a..3a2be36 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -110,7 +110,7 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
 	int rc, hwirq;
 
 	rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS_MAX,
-			      msi_data->irqhost->of_node);
+			      irq_domain_get_of_node(msi_data->irqhost));
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index e1a9c2c..6f99ed3 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -165,7 +165,8 @@ static struct resource pic_edgectrl_iores = {
 static int i8259_host_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int i8259_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index b1297ab..f76ee39 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -675,7 +675,8 @@ static int ipic_host_match(struct irq_domain *h, struct device_node *node,
 			   enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless ipic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int ipic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 537e5db..cecd115 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1011,7 +1011,8 @@ static int mpic_host_match(struct irq_domain *h, struct device_node *node,
 			   enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless mpic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int mpic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 7dc39f3..1d48a53 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -84,7 +84,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
 	int rc;
 
 	rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->num_sources,
-			      mpic->irqhost->of_node);
+			      irq_domain_get_of_node(mpic->irqhost));
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index fbcc1f8..ef36f16 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -248,7 +248,8 @@ static int qe_ic_host_match(struct irq_domain *h, struct device_node *node,
 			    enum irq_domain_bus_token bus_token)
 {
 	/* Exact match, unless qe_ic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	struct device_node *of_node = irq_domain_get_of_node(h);
+	return of_node == NULL || of_node == node;
 }
 
 static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 65bc9f4..34b02b4 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -102,7 +102,7 @@ static int sdv_xlate(struct irq_domain *h, struct device_node *node,
 {
 	u32 line, type;
 
-	if (node != h->of_node)
+	if (node != irq_domain_get_of_node(h))
 		return -EINVAL;
 
 	if (intsize < 2)
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index cd7d3bc..ead15be 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -144,7 +144,7 @@ static int combiner_irq_domain_xlate(struct irq_domain *d,
 				     unsigned long *out_hwirq,
 				     unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 
 	if (intsize < 2)
diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c
index 63cd031..b12a5d5 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -114,7 +114,7 @@ int aic_common_irq_domain_xlate(struct irq_domain *d,
 
 static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
 {
-	struct device_node *node = domain->of_node;
+	struct device_node *node = irq_domain_get_of_node(domain);
 	struct irq_chip_generic *gc;
 	struct aic_chip_data *aic;
 	struct property *prop;
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index a7f5626..f1d666a 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -94,7 +94,7 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 	if (i < 0)
 		return -ENODEV;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = 0;	/* SPI */
 	args.args[1] = i;
@@ -172,7 +172,7 @@ static int crossbar_domain_xlate(struct irq_domain *d,
 				 unsigned long *out_hwirq,
 				 unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;	/* Shouldn't happen, really... */
 	if (intsize != 3)
 		return -EINVAL;	/* Not GIC compliant */
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 12985da..695d489 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -117,7 +117,7 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
 	struct irq_data *d;
 	int err;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = 0;
 	args.args[1] = hwirq - 32;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 25ceae9f..ea4e5b2 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1243,7 +1243,7 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 {
 	struct of_phandle_args args;
 
-	args.np = domain->parent->of_node;
+	args.np = irq_domain_get_of_node(domain->parent);
 	args.args_count = 3;
 	args.args[0] = GIC_IRQ_TYPE_LPI;
 	args.args[1] = hwirq;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 36ecfc8..4c97ab6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -776,7 +776,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 				const u32 *intspec, unsigned int intsize,
 				unsigned long *out_hwirq, unsigned int *out_type)
 {
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 982c09c..7f53acb 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -910,7 +910,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 {
 	unsigned long ret = 0;
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index 8f3ca8f..9688d2e 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -325,7 +325,7 @@ static int hip04_irq_domain_xlate(struct irq_domain *d,
 {
 	unsigned long ret = 0;
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize < 3)
 		return -EINVAL;
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index e48d330..8bba3c0 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -202,7 +202,7 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 	}
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
 }
 
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index c8753da..b072166 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -106,7 +106,7 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 					      &mtk_sysirq_chip,
 					      domain->host_data);
 
-	gic_data.np = domain->parent->of_node;
+	gic_data.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
 }
 
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index 7154b01..c71914e 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -311,7 +311,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
 	 * and one big domain for the dt case where the subintc
 	 * starts at hwirq number 32.
 	 */
-	offset = (intc->domain->of_node) ? 32 : 0;
+	offset = irq_domain_get_of_node(intc->domain) ? 32 : 0;
 
 	chained_irq_enter(chip, desc);
 
@@ -342,7 +342,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
 		return false;
 
 	/* non-dt machines use individual domains */
-	if (!intc->domain->of_node)
+	if (!irq_domain_get_of_node(intc->domain))
 		intc_offset = 0;
 
 	/* We have a problem that the INTOFFSET register does not always
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 2fd89eb..7bbf226 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -227,7 +227,7 @@ static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
 				    unsigned long *out_hwirq,
 				    unsigned int *out_type)
 {
-	if (domain->of_node != controller)
+	if (irq_domain_get_of_node(domain) != controller)
 		return -EINVAL;	/* Shouldn't happen, really... */
 	if (intsize != 3)
 		return -EINVAL;	/* Not GIC compliant */
@@ -267,7 +267,7 @@ static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 	}
 
 	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
+	parent_args.np = irq_domain_get_of_node(domain->parent);
 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
 }
 
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
index 2c22558..ae82d7e 100644
--- a/drivers/irqchip/irq-vf610-mscm-ir.c
+++ b/drivers/irqchip/irq-vf610-mscm-ir.c
@@ -142,7 +142,7 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
 					      &vf610_mscm_ir_irq_chip,
 					      domain->host_data);
 
-	gic_data.np = domain->parent->of_node;
+	gic_data.np = irq_domain_get_of_node(domain->parent);
 
 	if (mscm_ir_data->is_nvic) {
 		gic_data.args_count = 1;
@@ -205,7 +205,8 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node,
 		goto out_unmap;
 	}
 
-	if (of_device_is_compatible(domain->parent->of_node, "arm,armv7m-nvic"))
+	if (of_device_is_compatible(irq_domain_get_of_node(domain->parent),
+				    "arm,armv7m-nvic"))
 		mscm_ir_data->is_nvic = true;
 
 	cpu_pm_register_notifier(&mscm_ir_notifier_block);
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 4a3cf9b..fb36810 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -657,7 +657,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 		"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
 		intspec[0], intspec[1], intspec[2]);
 
-	if (d->of_node != controller)
+	if (irq_domain_get_of_node(d) != controller)
 		return -EINVAL;
 	if (intsize != 4)
 		return -EINVAL;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index d3ca792..f644fdb 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -161,6 +161,11 @@ enum {
 	IRQ_DOMAIN_FLAG_NONCORE		= (1 << 16),
 };
 
+static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
+{
+	return d->of_node;
+}
+
 #ifdef CONFIG_IRQ_DOMAIN
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index dc9d27c..8f8b538 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -102,7 +102,7 @@ void irq_domain_remove(struct irq_domain *domain)
 
 	pr_debug("Removed domain %s\n", domain->name);
 
-	of_node_put(domain->of_node);
+	of_node_put(irq_domain_get_of_node(domain));
 	kfree(domain);
 }
 EXPORT_SYMBOL_GPL(irq_domain_remove);
@@ -208,10 +208,12 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
+		struct device_node *of_node;
+		of_node = irq_domain_get_of_node(h);
 		if (h->ops->match)
 			rc = h->ops->match(h, node, bus_token);
 		else
-			rc = ((h->of_node != NULL) && (h->of_node == node) &&
+			rc = ((of_node != NULL) && (of_node == node) &&
 			      ((bus_token == DOMAIN_BUS_ANY) ||
 			       (h->bus_token == bus_token)));
 
@@ -336,10 +338,12 @@ EXPORT_SYMBOL_GPL(irq_domain_associate);
 void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
 			       irq_hw_number_t hwirq_base, int count)
 {
+	struct device_node *of_node;
 	int i;
 
+	of_node = irq_domain_get_of_node(domain);
 	pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
-		of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
+		of_node_full_name(of_node), irq_base, (int)hwirq_base, count);
 
 	for (i = 0; i < count; i++) {
 		irq_domain_associate(domain, irq_base + i, hwirq_base + i);
@@ -359,12 +363,14 @@ EXPORT_SYMBOL_GPL(irq_domain_associate_many);
  */
 unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 {
+	struct device_node *of_node;
 	unsigned int virq;
 
 	if (domain == NULL)
 		domain = irq_default_domain;
 
-	virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
+	of_node = irq_domain_get_of_node(domain);
+	virq = irq_alloc_desc_from(1, of_node_to_nid(of_node));
 	if (!virq) {
 		pr_debug("create_direct virq allocation failed\n");
 		return 0;
@@ -399,6 +405,7 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 unsigned int irq_create_mapping(struct irq_domain *domain,
 				irq_hw_number_t hwirq)
 {
+	struct device_node *of_node;
 	int virq;
 
 	pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
@@ -412,6 +419,8 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 	pr_debug("-> using domain @%p\n", domain);
 
+	of_node = irq_domain_get_of_node(domain);
+
 	/* Check if mapping already exists */
 	virq = irq_find_mapping(domain, hwirq);
 	if (virq) {
@@ -420,8 +429,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 
 	/* Allocate a virtual interrupt number */
-	virq = irq_domain_alloc_descs(-1, 1, hwirq,
-				      of_node_to_nid(domain->of_node));
+	virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node));
 	if (virq <= 0) {
 		pr_debug("-> virq allocation failed\n");
 		return 0;
@@ -433,7 +441,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 
 	pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
-		hwirq, of_node_full_name(domain->of_node), virq);
+		hwirq, of_node_full_name(of_node), virq);
 
 	return virq;
 }
@@ -460,10 +468,12 @@ EXPORT_SYMBOL_GPL(irq_create_mapping);
 int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
 			       irq_hw_number_t hwirq_base, int count)
 {
+	struct device_node *of_node;
 	int ret;
 
+	of_node = irq_domain_get_of_node(domain);
 	ret = irq_alloc_descs(irq_base, irq_base, count,
-			      of_node_to_nid(domain->of_node));
+			      of_node_to_nid(of_node));
 	if (unlikely(ret < 0))
 		return ret;
 
@@ -590,14 +600,16 @@ static int virq_debug_show(struct seq_file *m, void *private)
 		   "name", "mapped", "linear-max", "direct-max", "devtree-node");
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(domain, &irq_domain_list, link) {
+		struct device_node *of_node;
 		int count = 0;
+		of_node = irq_domain_get_of_node(domain);
 		radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0)
 			count++;
 		seq_printf(m, "%c%-16s  %6u  %10u  %10u  %s\n",
 			   domain == irq_default_domain ? '*' : ' ', domain->name,
 			   domain->revmap_size + count, domain->revmap_size,
 			   domain->revmap_direct_max_irq,
-			   domain->of_node ? of_node_full_name(domain->of_node) : "");
+			   of_node ? of_node_full_name(of_node) : "");
 	}
 	mutex_unlock(&irq_domain_mutex);
 
-- 
2.1.4

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

* [PATCH 02/16] irqdomain: Convert irqdomain->of_node to fwnode
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Now that we have everyone accessing the of_node field via the
irq_domain_get_of_node accessor, it is pretty easy to swap it
for a pointer to a fwnode_handle.

This translates into a few limited changes in __irq_domain_add,
and an updated irq_domain_get_of_node.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 5 +++--
 kernel/irq/irqdomain.c    | 6 +++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index f644fdb..2f508f4 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -34,6 +34,7 @@
 
 #include <linux/types.h>
 #include <linux/irqhandler.h>
+#include <linux/of.h>
 #include <linux/radix-tree.h>
 
 struct device_node;
@@ -130,7 +131,7 @@ struct irq_domain {
 	unsigned int flags;
 
 	/* Optional data */
-	struct device_node *of_node;
+	struct fwnode_handle *fwnode;
 	enum irq_domain_bus_token bus_token;
 	struct irq_domain_chip_generic *gc;
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
@@ -163,7 +164,7 @@ enum {
 
 static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 {
-	return d->of_node;
+	return to_of_node(d->fwnode);
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 8f8b538..1aee5c1 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -46,17 +46,21 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    void *host_data)
 {
 	struct irq_domain *domain;
+	struct fwnode_handle *fwnode;
 
 	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
 			      GFP_KERNEL, of_node_to_nid(of_node));
 	if (WARN_ON(!domain))
 		return NULL;
 
+	of_node_get(of_node);
+	fwnode = of_node ? &of_node->fwnode : NULL;
+
 	/* Fill structure */
 	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
 	domain->ops = ops;
 	domain->host_data = host_data;
-	domain->of_node = of_node_get(of_node);
+	domain->fwnode = fwnode;
 	domain->hwirq_max = hwirq_max;
 	domain->revmap_size = size;
 	domain->revmap_direct_max_irq = direct_max;
-- 
2.1.4

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

* [PATCH 02/16] irqdomain: Convert irqdomain->of_node to fwnode
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Now that we have everyone accessing the of_node field via the
irq_domain_get_of_node accessor, it is pretty easy to swap it
for a pointer to a fwnode_handle.

This translates into a few limited changes in __irq_domain_add,
and an updated irq_domain_get_of_node.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 5 +++--
 kernel/irq/irqdomain.c    | 6 +++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index f644fdb..2f508f4 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -34,6 +34,7 @@
 
 #include <linux/types.h>
 #include <linux/irqhandler.h>
+#include <linux/of.h>
 #include <linux/radix-tree.h>
 
 struct device_node;
@@ -130,7 +131,7 @@ struct irq_domain {
 	unsigned int flags;
 
 	/* Optional data */
-	struct device_node *of_node;
+	struct fwnode_handle *fwnode;
 	enum irq_domain_bus_token bus_token;
 	struct irq_domain_chip_generic *gc;
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
@@ -163,7 +164,7 @@ enum {
 
 static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 {
-	return d->of_node;
+	return to_of_node(d->fwnode);
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 8f8b538..1aee5c1 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -46,17 +46,21 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    void *host_data)
 {
 	struct irq_domain *domain;
+	struct fwnode_handle *fwnode;
 
 	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
 			      GFP_KERNEL, of_node_to_nid(of_node));
 	if (WARN_ON(!domain))
 		return NULL;
 
+	of_node_get(of_node);
+	fwnode = of_node ? &of_node->fwnode : NULL;
+
 	/* Fill structure */
 	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
 	domain->ops = ops;
 	domain->host_data = host_data;
-	domain->of_node = of_node_get(of_node);
+	domain->fwnode = fwnode;
 	domain->hwirq_max = hwirq_max;
 	domain->revmap_size = size;
 	domain->revmap_direct_max_irq = direct_max;
-- 
2.1.4


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

* [PATCH 02/16] irqdomain: Convert irqdomain->of_node to fwnode
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we have everyone accessing the of_node field via the
irq_domain_get_of_node accessor, it is pretty easy to swap it
for a pointer to a fwnode_handle.

This translates into a few limited changes in __irq_domain_add,
and an updated irq_domain_get_of_node.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 5 +++--
 kernel/irq/irqdomain.c    | 6 +++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index f644fdb..2f508f4 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -34,6 +34,7 @@
 
 #include <linux/types.h>
 #include <linux/irqhandler.h>
+#include <linux/of.h>
 #include <linux/radix-tree.h>
 
 struct device_node;
@@ -130,7 +131,7 @@ struct irq_domain {
 	unsigned int flags;
 
 	/* Optional data */
-	struct device_node *of_node;
+	struct fwnode_handle *fwnode;
 	enum irq_domain_bus_token bus_token;
 	struct irq_domain_chip_generic *gc;
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
@@ -163,7 +164,7 @@ enum {
 
 static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 {
-	return d->of_node;
+	return to_of_node(d->fwnode);
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 8f8b538..1aee5c1 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -46,17 +46,21 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 				    void *host_data)
 {
 	struct irq_domain *domain;
+	struct fwnode_handle *fwnode;
 
 	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
 			      GFP_KERNEL, of_node_to_nid(of_node));
 	if (WARN_ON(!domain))
 		return NULL;
 
+	of_node_get(of_node);
+	fwnode = of_node ? &of_node->fwnode : NULL;
+
 	/* Fill structure */
 	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
 	domain->ops = ops;
 	domain->host_data = host_data;
-	domain->of_node = of_node_get(of_node);
+	domain->fwnode = fwnode;
 	domain->hwirq_max = hwirq_max;
 	domain->revmap_size = size;
 	domain->revmap_direct_max_irq = direct_max;
-- 
2.1.4

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

* [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Suravee Suthikulpanit, Jake Oshins, Graeme Gregory,
	linux-arm-kernel

So far, our irq domains are still looked up by device node.
Let's change this and allow a domain to be looked up using
a fwnode_handle pointer.

The existing interfaces are preserved with a couple of helpers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 11 +++++++++--
 kernel/irq/irqdomain.c    | 14 ++++++--------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 2f508f4..607c185 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 irq_hw_number_t first_hwirq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data);
-extern struct irq_domain *irq_find_matching_host(struct device_node *node,
-						 enum irq_domain_bus_token bus_token);
+extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
+						   enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 
+static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
+							enum irq_domain_bus_token bus_token)
+{
+	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
+					bus_token);
+}
+
 static inline struct irq_domain *irq_find_host(struct device_node *node)
 {
 	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 1aee5c1..10b6105 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
 
 /**
- * irq_find_matching_host() - Locates a domain for a given device node
- * @node: device-tree node of the interrupt controller
+ * irq_find_matching_fwnode() - Locates a domain for a given fwnode
+ * @fwnode: FW descriptor of the interrupt controller
  * @bus_token: domain-specific data
  */
-struct irq_domain *irq_find_matching_host(struct device_node *node,
-					  enum irq_domain_bus_token bus_token)
+struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
+					    enum irq_domain_bus_token bus_token)
 {
 	struct irq_domain *h, *found = NULL;
 	int rc;
@@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
-		struct device_node *of_node;
-		of_node = irq_domain_get_of_node(h);
 		if (h->ops->match)
-			rc = h->ops->match(h, node, bus_token);
+			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
 		else
-			rc = ((of_node != NULL) && (of_node == node) &&
+			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
 			      ((bus_token == DOMAIN_BUS_ANY) ||
 			       (h->bus_token == bus_token)));
 
-- 
2.1.4

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

* [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

So far, our irq domains are still looked up by device node.
Let's change this and allow a domain to be looked up using
a fwnode_handle pointer.

The existing interfaces are preserved with a couple of helpers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 11 +++++++++--
 kernel/irq/irqdomain.c    | 14 ++++++--------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 2f508f4..607c185 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 irq_hw_number_t first_hwirq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data);
-extern struct irq_domain *irq_find_matching_host(struct device_node *node,
-						 enum irq_domain_bus_token bus_token);
+extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
+						   enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 
+static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
+							enum irq_domain_bus_token bus_token)
+{
+	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
+					bus_token);
+}
+
 static inline struct irq_domain *irq_find_host(struct device_node *node)
 {
 	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 1aee5c1..10b6105 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
 
 /**
- * irq_find_matching_host() - Locates a domain for a given device node
- * @node: device-tree node of the interrupt controller
+ * irq_find_matching_fwnode() - Locates a domain for a given fwnode
+ * @fwnode: FW descriptor of the interrupt controller
  * @bus_token: domain-specific data
  */
-struct irq_domain *irq_find_matching_host(struct device_node *node,
-					  enum irq_domain_bus_token bus_token)
+struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
+					    enum irq_domain_bus_token bus_token)
 {
 	struct irq_domain *h, *found = NULL;
 	int rc;
@@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
-		struct device_node *of_node;
-		of_node = irq_domain_get_of_node(h);
 		if (h->ops->match)
-			rc = h->ops->match(h, node, bus_token);
+			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
 		else
-			rc = ((of_node != NULL) && (of_node == node) &&
+			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
 			      ((bus_token == DOMAIN_BUS_ANY) ||
 			       (h->bus_token == bus_token)));
 
-- 
2.1.4


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

* [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

So far, our irq domains are still looked up by device node.
Let's change this and allow a domain to be looked up using
a fwnode_handle pointer.

The existing interfaces are preserved with a couple of helpers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 11 +++++++++--
 kernel/irq/irqdomain.c    | 14 ++++++--------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 2f508f4..607c185 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 irq_hw_number_t first_hwirq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data);
-extern struct irq_domain *irq_find_matching_host(struct device_node *node,
-						 enum irq_domain_bus_token bus_token);
+extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
+						   enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 
+static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
+							enum irq_domain_bus_token bus_token)
+{
+	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
+					bus_token);
+}
+
 static inline struct irq_domain *irq_find_host(struct device_node *node)
 {
 	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 1aee5c1..10b6105 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
 
 /**
- * irq_find_matching_host() - Locates a domain for a given device node
- * @node: device-tree node of the interrupt controller
+ * irq_find_matching_fwnode() - Locates a domain for a given fwnode
+ * @fwnode: FW descriptor of the interrupt controller
  * @bus_token: domain-specific data
  */
-struct irq_domain *irq_find_matching_host(struct device_node *node,
-					  enum irq_domain_bus_token bus_token)
+struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
+					    enum irq_domain_bus_token bus_token)
 {
 	struct irq_domain *h, *found = NULL;
 	int rc;
@@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
-		struct device_node *of_node;
-		of_node = irq_domain_get_of_node(h);
 		if (h->ops->match)
-			rc = h->ops->match(h, node, bus_token);
+			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
 		else
-			rc = ((of_node != NULL) && (of_node == node) &&
+			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
 			      ((bus_token == DOMAIN_BUS_ANY) ||
 			       (h->bus_token == bus_token)));
 
-- 
2.1.4

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

* [PATCH 04/16] irqdomain: Introduce a firmware-specific IRQ specifier structure
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Suravee Suthikulpanit, Jake Oshins, Graeme Gregory,
	linux-arm-kernel

So far the closest thing to a generic IRQ specifier structure is
of_phandle_args, which happens to be pretty OF specific (the of_node
pointer in there is quite annoying).

Let's introduce 'struct irq_fwspec' that can be used in place of
of_phandle_args for OF, but also for other firmware implementations
(that'd be ACPI). This is used together with a new 'translate' method
that is the pendent of 'xlate'.

We convert irq_create_of_mapping to use this new structure (with a
small hack that will be removed later).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 20 ++++++++++++++++
 kernel/irq/irqdomain.c    | 59 ++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 607c185..533c974 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -46,6 +46,24 @@ struct irq_data;
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
 
+#define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16
+
+/**
+ * struct irq_fwspec - generic IRQ specifier structure
+ *
+ * @fwnode:		Pointer to a firmware-specific descriptor
+ * @param_count:	Number of device-specific parameters
+ * @param:		Device-specific parameters
+ *
+ * This structure, directly modeled after of_phandle_args, is used to
+ * pass a device-specific description of an interrupt.
+ */
+struct irq_fwspec {
+	struct fwnode_handle *fwnode;
+	int param_count;
+	u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
+};
+
 /*
  * Should several domains have the same device node, but serve
  * different purposes (for example one domain is for PCI/MSI, and the
@@ -92,6 +110,8 @@ struct irq_domain_ops {
 		     unsigned int nr_irqs);
 	void (*activate)(struct irq_domain *d, struct irq_data *irq_data);
 	void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
+	int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec,
+			 unsigned long *out_hwirq, unsigned int *out_type);
 #endif
 };
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 10b6105..3f07055 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -484,30 +484,67 @@ int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
 }
 EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
 
+static int irq_domain_translate(struct irq_domain *d,
+				struct irq_fwspec *fwspec,
+				irq_hw_number_t *hwirq, unsigned int *type)
+{
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+	if (d->ops->translate)
+		return d->ops->translate(d, fwspec, hwirq, type);
+#endif
+	if (d->ops->xlate)
+		return d->ops->xlate(d, to_of_node(fwspec->fwnode),
+				     fwspec->param, fwspec->param_count,
+				     hwirq, type);
+
+	/* If domain has no translation, then we assume interrupt line */
+	*hwirq = fwspec->param[0];
+	return 0;
+}
+
+static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
+				      struct irq_fwspec *fwspec)
+{
+	int i;
+
+	fwspec->fwnode = irq_data->np ? &irq_data->np->fwnode : NULL;
+	fwspec->param_count = irq_data->args_count;
+
+	for (i = 0; i < irq_data->args_count; i++)
+		fwspec->param[i] = irq_data->args[i];
+}
+
 unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 {
+	struct irq_fwspec fwspec;
 	struct irq_domain *domain;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	int virq;
 
-	domain = irq_data->np ? irq_find_host(irq_data->np) : irq_default_domain;
+	of_phandle_args_to_fwspec(irq_data, &fwspec);
+
+	if (fwspec.fwnode)
+		domain = irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY);
+	else
+		domain = irq_default_domain;
+
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
-			of_node_full_name(irq_data->np));
+			of_node_full_name(to_of_node(fwspec.fwnode)));
 		return 0;
 	}
 
-	/* If domain has no translation, then we assume interrupt line */
-	if (domain->ops->xlate == NULL)
-		hwirq = irq_data->args[0];
-	else {
-		if (domain->ops->xlate(domain, irq_data->np, irq_data->args,
-					irq_data->args_count, &hwirq, &type))
-			return 0;
-	}
+	if (irq_domain_translate(domain, &fwspec, &hwirq, &type))
+		return 0;
 
 	if (irq_domain_is_hierarchy(domain)) {
+		/* Temporary hack */
+		void *desc = &fwspec;
+#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
+		if (!domain->ops->translate)
+			desc = irq_data;
+#endif
 		/*
 		 * If we've already configured this interrupt,
 		 * don't do it again, or hell will break loose.
@@ -516,7 +553,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		if (virq)
 			return virq;
 
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, irq_data);
+		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, desc);
 		if (virq <= 0)
 			return 0;
 	} else {
-- 
2.1.4

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

* [PATCH 04/16] irqdomain: Introduce a firmware-specific IRQ specifier structure
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

So far the closest thing to a generic IRQ specifier structure is
of_phandle_args, which happens to be pretty OF specific (the of_node
pointer in there is quite annoying).

Let's introduce 'struct irq_fwspec' that can be used in place of
of_phandle_args for OF, but also for other firmware implementations
(that'd be ACPI). This is used together with a new 'translate' method
that is the pendent of 'xlate'.

We convert irq_create_of_mapping to use this new structure (with a
small hack that will be removed later).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 20 ++++++++++++++++
 kernel/irq/irqdomain.c    | 59 ++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 607c185..533c974 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -46,6 +46,24 @@ struct irq_data;
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
 
+#define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16
+
+/**
+ * struct irq_fwspec - generic IRQ specifier structure
+ *
+ * @fwnode:		Pointer to a firmware-specific descriptor
+ * @param_count:	Number of device-specific parameters
+ * @param:		Device-specific parameters
+ *
+ * This structure, directly modeled after of_phandle_args, is used to
+ * pass a device-specific description of an interrupt.
+ */
+struct irq_fwspec {
+	struct fwnode_handle *fwnode;
+	int param_count;
+	u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
+};
+
 /*
  * Should several domains have the same device node, but serve
  * different purposes (for example one domain is for PCI/MSI, and the
@@ -92,6 +110,8 @@ struct irq_domain_ops {
 		     unsigned int nr_irqs);
 	void (*activate)(struct irq_domain *d, struct irq_data *irq_data);
 	void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
+	int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec,
+			 unsigned long *out_hwirq, unsigned int *out_type);
 #endif
 };
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 10b6105..3f07055 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -484,30 +484,67 @@ int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
 }
 EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
 
+static int irq_domain_translate(struct irq_domain *d,
+				struct irq_fwspec *fwspec,
+				irq_hw_number_t *hwirq, unsigned int *type)
+{
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+	if (d->ops->translate)
+		return d->ops->translate(d, fwspec, hwirq, type);
+#endif
+	if (d->ops->xlate)
+		return d->ops->xlate(d, to_of_node(fwspec->fwnode),
+				     fwspec->param, fwspec->param_count,
+				     hwirq, type);
+
+	/* If domain has no translation, then we assume interrupt line */
+	*hwirq = fwspec->param[0];
+	return 0;
+}
+
+static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
+				      struct irq_fwspec *fwspec)
+{
+	int i;
+
+	fwspec->fwnode = irq_data->np ? &irq_data->np->fwnode : NULL;
+	fwspec->param_count = irq_data->args_count;
+
+	for (i = 0; i < irq_data->args_count; i++)
+		fwspec->param[i] = irq_data->args[i];
+}
+
 unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 {
+	struct irq_fwspec fwspec;
 	struct irq_domain *domain;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	int virq;
 
-	domain = irq_data->np ? irq_find_host(irq_data->np) : irq_default_domain;
+	of_phandle_args_to_fwspec(irq_data, &fwspec);
+
+	if (fwspec.fwnode)
+		domain = irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY);
+	else
+		domain = irq_default_domain;
+
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
-			of_node_full_name(irq_data->np));
+			of_node_full_name(to_of_node(fwspec.fwnode)));
 		return 0;
 	}
 
-	/* If domain has no translation, then we assume interrupt line */
-	if (domain->ops->xlate == NULL)
-		hwirq = irq_data->args[0];
-	else {
-		if (domain->ops->xlate(domain, irq_data->np, irq_data->args,
-					irq_data->args_count, &hwirq, &type))
-			return 0;
-	}
+	if (irq_domain_translate(domain, &fwspec, &hwirq, &type))
+		return 0;
 
 	if (irq_domain_is_hierarchy(domain)) {
+		/* Temporary hack */
+		void *desc = &fwspec;
+#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
+		if (!domain->ops->translate)
+			desc = irq_data;
+#endif
 		/*
 		 * If we've already configured this interrupt,
 		 * don't do it again, or hell will break loose.
@@ -516,7 +553,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		if (virq)
 			return virq;
 
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, irq_data);
+		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, desc);
 		if (virq <= 0)
 			return 0;
 	} else {
-- 
2.1.4


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

* [PATCH 04/16] irqdomain: Introduce a firmware-specific IRQ specifier structure
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

So far the closest thing to a generic IRQ specifier structure is
of_phandle_args, which happens to be pretty OF specific (the of_node
pointer in there is quite annoying).

Let's introduce 'struct irq_fwspec' that can be used in place of
of_phandle_args for OF, but also for other firmware implementations
(that'd be ACPI). This is used together with a new 'translate' method
that is the pendent of 'xlate'.

We convert irq_create_of_mapping to use this new structure (with a
small hack that will be removed later).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 20 ++++++++++++++++
 kernel/irq/irqdomain.c    | 59 ++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 607c185..533c974 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -46,6 +46,24 @@ struct irq_data;
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
 
+#define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16
+
+/**
+ * struct irq_fwspec - generic IRQ specifier structure
+ *
+ * @fwnode:		Pointer to a firmware-specific descriptor
+ * @param_count:	Number of device-specific parameters
+ * @param:		Device-specific parameters
+ *
+ * This structure, directly modeled after of_phandle_args, is used to
+ * pass a device-specific description of an interrupt.
+ */
+struct irq_fwspec {
+	struct fwnode_handle *fwnode;
+	int param_count;
+	u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
+};
+
 /*
  * Should several domains have the same device node, but serve
  * different purposes (for example one domain is for PCI/MSI, and the
@@ -92,6 +110,8 @@ struct irq_domain_ops {
 		     unsigned int nr_irqs);
 	void (*activate)(struct irq_domain *d, struct irq_data *irq_data);
 	void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
+	int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec,
+			 unsigned long *out_hwirq, unsigned int *out_type);
 #endif
 };
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 10b6105..3f07055 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -484,30 +484,67 @@ int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
 }
 EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
 
+static int irq_domain_translate(struct irq_domain *d,
+				struct irq_fwspec *fwspec,
+				irq_hw_number_t *hwirq, unsigned int *type)
+{
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+	if (d->ops->translate)
+		return d->ops->translate(d, fwspec, hwirq, type);
+#endif
+	if (d->ops->xlate)
+		return d->ops->xlate(d, to_of_node(fwspec->fwnode),
+				     fwspec->param, fwspec->param_count,
+				     hwirq, type);
+
+	/* If domain has no translation, then we assume interrupt line */
+	*hwirq = fwspec->param[0];
+	return 0;
+}
+
+static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
+				      struct irq_fwspec *fwspec)
+{
+	int i;
+
+	fwspec->fwnode = irq_data->np ? &irq_data->np->fwnode : NULL;
+	fwspec->param_count = irq_data->args_count;
+
+	for (i = 0; i < irq_data->args_count; i++)
+		fwspec->param[i] = irq_data->args[i];
+}
+
 unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 {
+	struct irq_fwspec fwspec;
 	struct irq_domain *domain;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	int virq;
 
-	domain = irq_data->np ? irq_find_host(irq_data->np) : irq_default_domain;
+	of_phandle_args_to_fwspec(irq_data, &fwspec);
+
+	if (fwspec.fwnode)
+		domain = irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY);
+	else
+		domain = irq_default_domain;
+
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
-			of_node_full_name(irq_data->np));
+			of_node_full_name(to_of_node(fwspec.fwnode)));
 		return 0;
 	}
 
-	/* If domain has no translation, then we assume interrupt line */
-	if (domain->ops->xlate == NULL)
-		hwirq = irq_data->args[0];
-	else {
-		if (domain->ops->xlate(domain, irq_data->np, irq_data->args,
-					irq_data->args_count, &hwirq, &type))
-			return 0;
-	}
+	if (irq_domain_translate(domain, &fwspec, &hwirq, &type))
+		return 0;
 
 	if (irq_domain_is_hierarchy(domain)) {
+		/* Temporary hack */
+		void *desc = &fwspec;
+#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
+		if (!domain->ops->translate)
+			desc = irq_data;
+#endif
 		/*
 		 * If we've already configured this interrupt,
 		 * don't do it again, or hell will break loose.
@@ -516,7 +553,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		if (virq)
 			return virq;
 
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, irq_data);
+		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, desc);
 		if (virq <= 0)
 			return 0;
 	} else {
-- 
2.1.4

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

* [PATCH 05/16] irqchip: Convert all alloc/xlate users from of_node to fwnode
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Suravee Suthikulpanit, Jake Oshins, Graeme Gregory,
	linux-arm-kernel

Since we now have a generic data structure to express an
interrupt specifier, convert all hierarchical irqchips that
are OF based to use a fwnode_handle as part of their alloc
and xlate (which becomes translate) callbacks.

As most of these drivers have dependencies (they exchange IRQ
specifiers), change them all in a single, massive patch...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-exynos/suspend.c       | 55 ++++++++++++++++---------------
 arch/arm/mach-imx/gpc.c              | 55 ++++++++++++++++---------------
 arch/arm/mach-omap2/omap-wakeupgen.c | 55 ++++++++++++++++---------------
 drivers/irqchip/irq-crossbar.c       | 62 ++++++++++++++++++----------------
 drivers/irqchip/irq-gic-v2m.c        | 18 ++++++----
 drivers/irqchip/irq-gic-v3-its.c     | 20 ++++++-----
 drivers/irqchip/irq-gic-v3.c         | 49 +++++++++++++--------------
 drivers/irqchip/irq-gic.c            | 33 ++++++++++++++++---
 drivers/irqchip/irq-imx-gpcv2.c      | 64 ++++++++++++++++--------------------
 drivers/irqchip/irq-mtk-sysirq.c     | 49 ++++++++++++++-------------
 drivers/irqchip/irq-nvic.c           | 18 +++++++---
 drivers/irqchip/irq-tegra.c          | 55 ++++++++++++++++---------------
 drivers/irqchip/irq-vf610-mscm-ir.c  | 42 +++++++++++++++--------
 13 files changed, 323 insertions(+), 252 deletions(-)

diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index e00eb39..5a7e47c 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -177,54 +177,57 @@ static struct irq_chip exynos_pmu_chip = {
 #endif
 };
 
-static int exynos_pmu_domain_xlate(struct irq_domain *domain,
-				   struct device_node *controller,
-				   const u32 *intspec,
-				   unsigned int intsize,
-				   unsigned long *out_hwirq,
-				   unsigned int *out_type)
+static int exynos_pmu_domain_translate(struct irq_domain *d,
+				       struct irq_fwspec *fwspec,
+				       unsigned long *hwirq,
+				       unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int exynos_pmu_domain_alloc(struct irq_domain *domain,
 				   unsigned int virq,
 				   unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &exynos_pmu_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops exynos_pmu_domain_ops = {
-	.xlate	= exynos_pmu_domain_xlate,
-	.alloc	= exynos_pmu_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= exynos_pmu_domain_translate,
+	.alloc		= exynos_pmu_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init exynos_pmu_irq_init(struct device_node *node,
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 8c4467f..10bf715 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -181,40 +181,42 @@ static struct irq_chip imx_gpc_chip = {
 #endif
 };
 
-static int imx_gpc_domain_xlate(struct irq_domain *domain,
-				struct device_node *controller,
-				const u32 *intspec,
-				unsigned int intsize,
-				unsigned long *out_hwirq,
-				unsigned int *out_type)
+static int imx_gpc_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int imx_gpc_domain_alloc(struct irq_domain *domain,
 				  unsigned int irq,
 				  unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= GPC_MAX_IRQS)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -222,15 +224,16 @@ static int imx_gpc_domain_alloc(struct irq_domain *domain,
 		irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
 					      &imx_gpc_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
-	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops imx_gpc_domain_ops = {
-	.xlate	= imx_gpc_domain_xlate,
-	.alloc	= imx_gpc_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= imx_gpc_domain_translate,
+	.alloc		= imx_gpc_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init imx_gpc_init(struct device_node *node,
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index a52fe5b..db7e0ba 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -399,40 +399,42 @@ static struct irq_chip wakeupgen_chip = {
 #endif
 };
 
-static int wakeupgen_domain_xlate(struct irq_domain *domain,
-				  struct device_node *controller,
-				  const u32 *intspec,
-				  unsigned int intsize,
-				  unsigned long *out_hwirq,
-				  unsigned int *out_type)
+static int wakeupgen_domain_translate(struct irq_domain *d,
+				      struct irq_fwspec *fwspec,
+				      unsigned long *hwirq,
+				      unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int wakeupgen_domain_alloc(struct irq_domain *domain,
 				  unsigned int virq,
 				  unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= MAX_IRQS)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -440,15 +442,16 @@ static int wakeupgen_domain_alloc(struct irq_domain *domain,
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &wakeupgen_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops wakeupgen_domain_ops = {
-	.xlate	= wakeupgen_domain_xlate,
-	.alloc	= wakeupgen_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= wakeupgen_domain_translate,
+	.alloc		= wakeupgen_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 /*
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index f1d666a..75573fa 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -78,10 +78,13 @@ static struct irq_chip crossbar_chip = {
 static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 			    irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
+	struct irq_fwspec fwspec;
 	int i;
 	int err;
 
+	if (!irq_domain_get_of_node(domain->parent))
+		return -EINVAL;
+
 	raw_spin_lock(&cb->lock);
 	for (i = cb->int_max - 1; i >= 0; i--) {
 		if (cb->irq_map[i] == IRQ_FREE) {
@@ -94,13 +97,13 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 	if (i < 0)
 		return -ENODEV;
 
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = 0;	/* SPI */
-	args.args[1] = i;
-	args.args[2] = IRQ_TYPE_LEVEL_HIGH;
+	fwspec.fwnode = domain->parent->fwnode;
+	fwspec.param_count = 3;
+	fwspec.param[0] = 0;	/* SPI */
+	fwspec.param[1] = i;
+	fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
 
-	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (err)
 		cb->irq_map[i] = IRQ_FREE;
 	else
@@ -112,16 +115,16 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
 				 unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
+	struct irq_fwspec *fwspec = data;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if ((hwirq + nr_irqs) > cb->max_crossbar_sources)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -166,28 +169,31 @@ static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
 	raw_spin_unlock(&cb->lock);
 }
 
-static int crossbar_domain_xlate(struct irq_domain *d,
-				 struct device_node *controller,
-				 const u32 *intspec, unsigned int intsize,
-				 unsigned long *out_hwirq,
-				 unsigned int *out_type)
+static int crossbar_domain_translate(struct irq_domain *d,
+				     struct irq_fwspec *fwspec,
+				     unsigned long *hwirq,
+				     unsigned int *type)
 {
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static const struct irq_domain_ops crossbar_domain_ops = {
-	.alloc	= crossbar_domain_alloc,
-	.free	= crossbar_domain_free,
-	.xlate	= crossbar_domain_xlate,
+	.alloc		= crossbar_domain_alloc,
+	.free		= crossbar_domain_free,
+	.translate	= crossbar_domain_translate,
 };
 
 static int __init crossbar_of_init(struct device_node *node)
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 695d489..b2b08dd 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -113,17 +113,21 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
 				       unsigned int virq,
 				       irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
+	struct irq_fwspec fwspec;
 	struct irq_data *d;
 	int err;
 
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = 0;
-	args.args[1] = hwirq - 32;
-	args.args[2] = IRQ_TYPE_EDGE_RISING;
+	if (is_of_node(domain->parent->fwnode)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 3;
+		fwspec.param[0] = 0;
+		fwspec.param[1] = hwirq - 32;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		return -EINVAL;
+	}
 
-	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (err)
 		return err;
 
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index ea4e5b2..f0d64e4 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1241,15 +1241,19 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 				    unsigned int virq,
 				    irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
-
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = GIC_IRQ_TYPE_LPI;
-	args.args[1] = hwirq;
-	args.args[2] = IRQ_TYPE_EDGE_RISING;
+	struct irq_fwspec fwspec;
+
+	if (irq_domain_get_of_node(domain->parent)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 3;
+		fwspec.param[0] = GIC_IRQ_TYPE_LPI;
+		fwspec.param[1] = hwirq;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		return -EINVAL;
+	}
 
-	return irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 }
 
 static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 4c97ab6..e26a934 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -771,32 +771,30 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 	return 0;
 }
 
-static int gic_irq_domain_xlate(struct irq_domain *d,
-				struct device_node *controller,
-				const u32 *intspec, unsigned int intsize,
-				unsigned long *out_hwirq, unsigned int *out_type)
+static int gic_irq_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
 {
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;
-	if (intsize < 3)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count < 3)
+			return -EINVAL;
 
-	switch(intspec[0]) {
-	case 0:			/* SPI */
-		*out_hwirq = intspec[1] + 32;
-		break;
-	case 1:			/* PPI */
-		*out_hwirq = intspec[1] + 16;
-		break;
-	case GIC_IRQ_TYPE_LPI:	/* LPI */
-		*out_hwirq = intspec[1];
-		break;
-	default:
-		return -EINVAL;
+		/* Get the interrupt number and add 16 to skip over SGIs */
+		*hwirq = fwspec->param[1] + 16;
+
+		/*
+		 * For SPIs, we need to add 16 more to get the GIC irq
+		 * ID number
+		 */
+		if (!fwspec->param[0])
+			*hwirq += 16;
+
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
 	}
 
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-	return 0;
+	return -EINVAL;
 }
 
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -805,10 +803,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -831,7 +828,7 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops gic_irq_domain_ops = {
-	.xlate = gic_irq_domain_xlate,
+	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = gic_irq_domain_free,
 };
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 7f53acb..b0135be 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -927,6 +927,32 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 	return ret;
 }
 
+static int gic_irq_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
+{
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count < 3)
+			return -EINVAL;
+
+		/* Get the interrupt number and add 16 to skip over SGIs */
+		*hwirq = fwspec->param[1] + 16;
+
+		/*
+		 * For SPIs, we need to add 16 more to get the GIC irq
+		 * ID number
+		 */
+		if (!fwspec->param[0])
+			*hwirq += 16;
+
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 #ifdef CONFIG_SMP
 static int gic_secondary_init(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
@@ -952,10 +978,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -966,7 +991,7 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
-	.xlate = gic_irq_domain_xlate,
+	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = irq_domain_free_irqs_top,
 };
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index 8bba3c0..15af9a9 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -150,49 +150,42 @@ static struct irq_chip gpcv2_irqchip_data_chip = {
 #endif
 };
 
-static int imx_gpcv2_domain_xlate(struct irq_domain *domain,
-				struct device_node *controller,
-				const u32 *intspec,
-				unsigned int intsize,
-				unsigned long *out_hwirq,
-				unsigned int *out_type)
+static int imx_gpcv2_domain_translate(struct irq_domain *d,
+				      struct irq_fwspec *fwspec,
+				      unsigned long *hwirq,
+				      unsigned int *type)
 {
-	/* Shouldn't happen, really... */
-	if (domain->of_node != controller)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	/* Not GIC compliant */
-	if (intsize != 3)
-		return -EINVAL;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
 
-	/* No PPI should point to this domain */
-	if (intspec[0] != 0)
-		return -EINVAL;
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+	return -EINVAL;
 }
 
 static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 				  unsigned int irq, unsigned int nr_irqs,
 				  void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
+	unsigned int type;
+	int err;
 	int i;
 
-	/* Not GIC compliant */
-	if (args->args_count != 3)
-		return -EINVAL;
-
-	/* No PPI should point to this domain */
-	if (args->args[0] != 0)
-		return -EINVAL;
+	err = imx_gpcv2_domain_translate(domain, fwspec, &hwirq, &type);
+	if (err)
+		return err;
 
-	/* Can't deal with this */
-	hwirq = args->args[1];
 	if (hwirq >= GPC_MAX_IRQS)
 		return -EINVAL;
 
@@ -201,15 +194,16 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 				&gpcv2_irqchip_data_chip, domain->host_data);
 	}
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static struct irq_domain_ops gpcv2_irqchip_data_domain_ops = {
-	.xlate	= imx_gpcv2_domain_xlate,
-	.alloc	= imx_gpcv2_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= imx_gpcv2_domain_translate,
+	.alloc		= imx_gpcv2_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init imx_gpcv2_irqchip_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index b072166..63ac73b 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -67,22 +67,25 @@ static struct irq_chip mtk_sysirq_chip = {
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 };
 
-static int mtk_sysirq_domain_xlate(struct irq_domain *d,
-				   struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize,
-				   unsigned long *out_hwirq,
-				   unsigned int *out_type)
+static int mtk_sysirq_domain_translate(struct irq_domain *d,
+				       struct irq_fwspec *fwspec,
+				       unsigned long *hwirq,
+				       unsigned int *type)
 {
-	if (intsize != 3)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	/* sysirq doesn't support PPI */
-	if (intspec[0])
-		return -EINVAL;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-	return 0;
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -90,30 +93,30 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 {
 	int i;
 	irq_hw_number_t hwirq;
-	struct of_phandle_args *irq_data = arg;
-	struct of_phandle_args gic_data = *irq_data;
+	struct irq_fwspec *fwspec = arg;
+	struct irq_fwspec gic_fwspec = *fwspec;
 
-	if (irq_data->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;
 
 	/* sysirq doesn't support PPI */
-	if (irq_data->args[0])
+	if (fwspec->param[0])
 		return -EINVAL;
 
-	hwirq = irq_data->args[1];
+	hwirq = fwspec->param[1];
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &mtk_sysirq_chip,
 					      domain->host_data);
 
-	gic_data.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+	gic_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_fwspec);
 }
 
 static const struct irq_domain_ops sysirq_domain_ops = {
-	.xlate = mtk_sysirq_domain_xlate,
-	.alloc = mtk_sysirq_domain_alloc,
-	.free = irq_domain_free_irqs_common,
+	.translate	= mtk_sysirq_domain_translate,
+	.alloc		= mtk_sysirq_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init mtk_sysirq_of_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c
index a878b8d..b177710 100644
--- a/drivers/irqchip/irq-nvic.c
+++ b/drivers/irqchip/irq-nvic.c
@@ -48,16 +48,26 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
 	handle_IRQ(irq, regs);
 }
 
+static int nvic_irq_domain_translate(struct irq_domain *d,
+				     struct irq_fwspec *fwspec,
+				     unsigned long *hwirq, unsigned int *type)
+{
+	if (WARN_ON(fwspec->param_count < 1))
+		return -EINVAL;
+	*hwirq = fwspec->param[0];
+	*type = IRQ_TYPE_NONE;
+	return 0;
+}
+
 static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = irq_domain_xlate_onecell(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = nvic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -68,7 +78,7 @@ static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops nvic_irq_domain_ops = {
-	.xlate = irq_domain_xlate_onecell,
+	.translate = nvic_irq_domain_translate,
 	.alloc = nvic_irq_domain_alloc,
 	.free = irq_domain_free_irqs_top,
 };
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 7bbf226..557e15e 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -220,41 +220,43 @@ static struct irq_chip tegra_ictlr_chip = {
 #endif
 };
 
-static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
-				    struct device_node *controller,
-				    const u32 *intspec,
-				    unsigned int intsize,
-				    unsigned long *out_hwirq,
-				    unsigned int *out_type)
+static int tegra_ictlr_domain_translate(struct irq_domain *d,
+					struct irq_fwspec *fwspec,
+					unsigned long *hwirq,
+					unsigned int *type)
 {
-	if (irq_domain_get_of_node(domain) != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != GIC_SPI)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 				    unsigned int virq,
 				    unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	struct tegra_ictlr_info *info = domain->host_data;
 	irq_hw_number_t hwirq;
 	unsigned int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != GIC_SPI)
+	if (fwspec->param[0] != GIC_SPI)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= (num_ictlrs * 32))
 		return -EINVAL;
 
@@ -266,9 +268,10 @@ static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 					      info->base[ictlr]);
 	}
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static void tegra_ictlr_domain_free(struct irq_domain *domain,
@@ -284,9 +287,9 @@ static void tegra_ictlr_domain_free(struct irq_domain *domain,
 }
 
 static const struct irq_domain_ops tegra_ictlr_domain_ops = {
-	.xlate	= tegra_ictlr_domain_xlate,
-	.alloc	= tegra_ictlr_domain_alloc,
-	.free	= tegra_ictlr_domain_free,
+	.translate	= tegra_ictlr_domain_translate,
+	.alloc		= tegra_ictlr_domain_alloc,
+	.free		= tegra_ictlr_domain_free,
 };
 
 static int __init tegra_ictlr_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
index ae82d7e..56b5e3c 100644
--- a/drivers/irqchip/irq-vf610-mscm-ir.c
+++ b/drivers/irqchip/irq-vf610-mscm-ir.c
@@ -130,35 +130,51 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
 {
 	int i;
 	irq_hw_number_t hwirq;
-	struct of_phandle_args *irq_data = arg;
-	struct of_phandle_args gic_data;
+	struct irq_fwspec *fwspec = arg;
+	struct irq_fwspec parent_fwspec;
 
-	if (irq_data->args_count != 2)
+	if (!irq_domain_get_of_node(domain->parent))
 		return -EINVAL;
 
-	hwirq = irq_data->args[0];
+	if (fwspec->param_count != 2)
+		return -EINVAL;
+
+	hwirq = fwspec->param[0];
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &vf610_mscm_ir_irq_chip,
 					      domain->host_data);
 
-	gic_data.np = irq_domain_get_of_node(domain->parent);
+	parent_fwspec.fwnode = domain->parent->fwnode;
 
 	if (mscm_ir_data->is_nvic) {
-		gic_data.args_count = 1;
-		gic_data.args[0] = irq_data->args[0];
+		parent_fwspec.param_count = 1;
+		parent_fwspec.param[0] = fwspec->param[0];
 	} else {
-		gic_data.args_count = 3;
-		gic_data.args[0] = GIC_SPI;
-		gic_data.args[1] = irq_data->args[0];
-		gic_data.args[2] = irq_data->args[1];
+		parent_fwspec.param_count = 3;
+		parent_fwspec.param[0] = GIC_SPI;
+		parent_fwspec.param[1] = fwspec->param[0];
+		parent_fwspec.param[2] = fwspec->param[1];
 	}
 
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
+}
+
+static int vf610_mscm_ir_domain_translate(struct irq_domain *d,
+					  struct irq_fwspec *fwspec,
+					  unsigned long *hwirq,
+					  unsigned int *type)
+{
+	if (WARN_ON(fwspec->param_count < 2))
+		return -EINVAL;
+	*hwirq = fwspec->param[0];
+	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
 }
 
 static const struct irq_domain_ops mscm_irq_domain_ops = {
-	.xlate = irq_domain_xlate_twocell,
+	.translate = vf610_mscm_ir_domain_translate,
 	.alloc = vf610_mscm_ir_domain_alloc,
 	.free = irq_domain_free_irqs_common,
 };
-- 
2.1.4

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

* [PATCH 05/16] irqchip: Convert all alloc/xlate users from of_node to fwnode
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Since we now have a generic data structure to express an
interrupt specifier, convert all hierarchical irqchips that
are OF based to use a fwnode_handle as part of their alloc
and xlate (which becomes translate) callbacks.

As most of these drivers have dependencies (they exchange IRQ
specifiers), change them all in a single, massive patch...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-exynos/suspend.c       | 55 ++++++++++++++++---------------
 arch/arm/mach-imx/gpc.c              | 55 ++++++++++++++++---------------
 arch/arm/mach-omap2/omap-wakeupgen.c | 55 ++++++++++++++++---------------
 drivers/irqchip/irq-crossbar.c       | 62 ++++++++++++++++++----------------
 drivers/irqchip/irq-gic-v2m.c        | 18 ++++++----
 drivers/irqchip/irq-gic-v3-its.c     | 20 ++++++-----
 drivers/irqchip/irq-gic-v3.c         | 49 +++++++++++++--------------
 drivers/irqchip/irq-gic.c            | 33 ++++++++++++++++---
 drivers/irqchip/irq-imx-gpcv2.c      | 64 ++++++++++++++++--------------------
 drivers/irqchip/irq-mtk-sysirq.c     | 49 ++++++++++++++-------------
 drivers/irqchip/irq-nvic.c           | 18 +++++++---
 drivers/irqchip/irq-tegra.c          | 55 ++++++++++++++++---------------
 drivers/irqchip/irq-vf610-mscm-ir.c  | 42 +++++++++++++++--------
 13 files changed, 323 insertions(+), 252 deletions(-)

diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index e00eb39..5a7e47c 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -177,54 +177,57 @@ static struct irq_chip exynos_pmu_chip = {
 #endif
 };
 
-static int exynos_pmu_domain_xlate(struct irq_domain *domain,
-				   struct device_node *controller,
-				   const u32 *intspec,
-				   unsigned int intsize,
-				   unsigned long *out_hwirq,
-				   unsigned int *out_type)
+static int exynos_pmu_domain_translate(struct irq_domain *d,
+				       struct irq_fwspec *fwspec,
+				       unsigned long *hwirq,
+				       unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int exynos_pmu_domain_alloc(struct irq_domain *domain,
 				   unsigned int virq,
 				   unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &exynos_pmu_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops exynos_pmu_domain_ops = {
-	.xlate	= exynos_pmu_domain_xlate,
-	.alloc	= exynos_pmu_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= exynos_pmu_domain_translate,
+	.alloc		= exynos_pmu_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init exynos_pmu_irq_init(struct device_node *node,
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 8c4467f..10bf715 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -181,40 +181,42 @@ static struct irq_chip imx_gpc_chip = {
 #endif
 };
 
-static int imx_gpc_domain_xlate(struct irq_domain *domain,
-				struct device_node *controller,
-				const u32 *intspec,
-				unsigned int intsize,
-				unsigned long *out_hwirq,
-				unsigned int *out_type)
+static int imx_gpc_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int imx_gpc_domain_alloc(struct irq_domain *domain,
 				  unsigned int irq,
 				  unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= GPC_MAX_IRQS)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -222,15 +224,16 @@ static int imx_gpc_domain_alloc(struct irq_domain *domain,
 		irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
 					      &imx_gpc_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
-	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops imx_gpc_domain_ops = {
-	.xlate	= imx_gpc_domain_xlate,
-	.alloc	= imx_gpc_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= imx_gpc_domain_translate,
+	.alloc		= imx_gpc_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init imx_gpc_init(struct device_node *node,
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index a52fe5b..db7e0ba 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -399,40 +399,42 @@ static struct irq_chip wakeupgen_chip = {
 #endif
 };
 
-static int wakeupgen_domain_xlate(struct irq_domain *domain,
-				  struct device_node *controller,
-				  const u32 *intspec,
-				  unsigned int intsize,
-				  unsigned long *out_hwirq,
-				  unsigned int *out_type)
+static int wakeupgen_domain_translate(struct irq_domain *d,
+				      struct irq_fwspec *fwspec,
+				      unsigned long *hwirq,
+				      unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int wakeupgen_domain_alloc(struct irq_domain *domain,
 				  unsigned int virq,
 				  unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= MAX_IRQS)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -440,15 +442,16 @@ static int wakeupgen_domain_alloc(struct irq_domain *domain,
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &wakeupgen_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops wakeupgen_domain_ops = {
-	.xlate	= wakeupgen_domain_xlate,
-	.alloc	= wakeupgen_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= wakeupgen_domain_translate,
+	.alloc		= wakeupgen_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 /*
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index f1d666a..75573fa 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -78,10 +78,13 @@ static struct irq_chip crossbar_chip = {
 static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 			    irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
+	struct irq_fwspec fwspec;
 	int i;
 	int err;
 
+	if (!irq_domain_get_of_node(domain->parent))
+		return -EINVAL;
+
 	raw_spin_lock(&cb->lock);
 	for (i = cb->int_max - 1; i >= 0; i--) {
 		if (cb->irq_map[i] == IRQ_FREE) {
@@ -94,13 +97,13 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 	if (i < 0)
 		return -ENODEV;
 
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = 0;	/* SPI */
-	args.args[1] = i;
-	args.args[2] = IRQ_TYPE_LEVEL_HIGH;
+	fwspec.fwnode = domain->parent->fwnode;
+	fwspec.param_count = 3;
+	fwspec.param[0] = 0;	/* SPI */
+	fwspec.param[1] = i;
+	fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
 
-	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (err)
 		cb->irq_map[i] = IRQ_FREE;
 	else
@@ -112,16 +115,16 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
 				 unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
+	struct irq_fwspec *fwspec = data;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if ((hwirq + nr_irqs) > cb->max_crossbar_sources)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -166,28 +169,31 @@ static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
 	raw_spin_unlock(&cb->lock);
 }
 
-static int crossbar_domain_xlate(struct irq_domain *d,
-				 struct device_node *controller,
-				 const u32 *intspec, unsigned int intsize,
-				 unsigned long *out_hwirq,
-				 unsigned int *out_type)
+static int crossbar_domain_translate(struct irq_domain *d,
+				     struct irq_fwspec *fwspec,
+				     unsigned long *hwirq,
+				     unsigned int *type)
 {
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static const struct irq_domain_ops crossbar_domain_ops = {
-	.alloc	= crossbar_domain_alloc,
-	.free	= crossbar_domain_free,
-	.xlate	= crossbar_domain_xlate,
+	.alloc		= crossbar_domain_alloc,
+	.free		= crossbar_domain_free,
+	.translate	= crossbar_domain_translate,
 };
 
 static int __init crossbar_of_init(struct device_node *node)
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 695d489..b2b08dd 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -113,17 +113,21 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
 				       unsigned int virq,
 				       irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
+	struct irq_fwspec fwspec;
 	struct irq_data *d;
 	int err;
 
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = 0;
-	args.args[1] = hwirq - 32;
-	args.args[2] = IRQ_TYPE_EDGE_RISING;
+	if (is_of_node(domain->parent->fwnode)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 3;
+		fwspec.param[0] = 0;
+		fwspec.param[1] = hwirq - 32;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		return -EINVAL;
+	}
 
-	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (err)
 		return err;
 
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index ea4e5b2..f0d64e4 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1241,15 +1241,19 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 				    unsigned int virq,
 				    irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
-
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = GIC_IRQ_TYPE_LPI;
-	args.args[1] = hwirq;
-	args.args[2] = IRQ_TYPE_EDGE_RISING;
+	struct irq_fwspec fwspec;
+
+	if (irq_domain_get_of_node(domain->parent)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 3;
+		fwspec.param[0] = GIC_IRQ_TYPE_LPI;
+		fwspec.param[1] = hwirq;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		return -EINVAL;
+	}
 
-	return irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 }
 
 static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 4c97ab6..e26a934 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -771,32 +771,30 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 	return 0;
 }
 
-static int gic_irq_domain_xlate(struct irq_domain *d,
-				struct device_node *controller,
-				const u32 *intspec, unsigned int intsize,
-				unsigned long *out_hwirq, unsigned int *out_type)
+static int gic_irq_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
 {
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;
-	if (intsize < 3)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count < 3)
+			return -EINVAL;
 
-	switch(intspec[0]) {
-	case 0:			/* SPI */
-		*out_hwirq = intspec[1] + 32;
-		break;
-	case 1:			/* PPI */
-		*out_hwirq = intspec[1] + 16;
-		break;
-	case GIC_IRQ_TYPE_LPI:	/* LPI */
-		*out_hwirq = intspec[1];
-		break;
-	default:
-		return -EINVAL;
+		/* Get the interrupt number and add 16 to skip over SGIs */
+		*hwirq = fwspec->param[1] + 16;
+
+		/*
+		 * For SPIs, we need to add 16 more to get the GIC irq
+		 * ID number
+		 */
+		if (!fwspec->param[0])
+			*hwirq += 16;
+
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
 	}
 
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-	return 0;
+	return -EINVAL;
 }
 
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -805,10 +803,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -831,7 +828,7 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops gic_irq_domain_ops = {
-	.xlate = gic_irq_domain_xlate,
+	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = gic_irq_domain_free,
 };
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 7f53acb..b0135be 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -927,6 +927,32 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 	return ret;
 }
 
+static int gic_irq_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
+{
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count < 3)
+			return -EINVAL;
+
+		/* Get the interrupt number and add 16 to skip over SGIs */
+		*hwirq = fwspec->param[1] + 16;
+
+		/*
+		 * For SPIs, we need to add 16 more to get the GIC irq
+		 * ID number
+		 */
+		if (!fwspec->param[0])
+			*hwirq += 16;
+
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 #ifdef CONFIG_SMP
 static int gic_secondary_init(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
@@ -952,10 +978,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -966,7 +991,7 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
-	.xlate = gic_irq_domain_xlate,
+	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = irq_domain_free_irqs_top,
 };
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index 8bba3c0..15af9a9 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -150,49 +150,42 @@ static struct irq_chip gpcv2_irqchip_data_chip = {
 #endif
 };
 
-static int imx_gpcv2_domain_xlate(struct irq_domain *domain,
-				struct device_node *controller,
-				const u32 *intspec,
-				unsigned int intsize,
-				unsigned long *out_hwirq,
-				unsigned int *out_type)
+static int imx_gpcv2_domain_translate(struct irq_domain *d,
+				      struct irq_fwspec *fwspec,
+				      unsigned long *hwirq,
+				      unsigned int *type)
 {
-	/* Shouldn't happen, really... */
-	if (domain->of_node != controller)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	/* Not GIC compliant */
-	if (intsize != 3)
-		return -EINVAL;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
 
-	/* No PPI should point to this domain */
-	if (intspec[0] != 0)
-		return -EINVAL;
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+	return -EINVAL;
 }
 
 static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 				  unsigned int irq, unsigned int nr_irqs,
 				  void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
+	unsigned int type;
+	int err;
 	int i;
 
-	/* Not GIC compliant */
-	if (args->args_count != 3)
-		return -EINVAL;
-
-	/* No PPI should point to this domain */
-	if (args->args[0] != 0)
-		return -EINVAL;
+	err = imx_gpcv2_domain_translate(domain, fwspec, &hwirq, &type);
+	if (err)
+		return err;
 
-	/* Can't deal with this */
-	hwirq = args->args[1];
 	if (hwirq >= GPC_MAX_IRQS)
 		return -EINVAL;
 
@@ -201,15 +194,16 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 				&gpcv2_irqchip_data_chip, domain->host_data);
 	}
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static struct irq_domain_ops gpcv2_irqchip_data_domain_ops = {
-	.xlate	= imx_gpcv2_domain_xlate,
-	.alloc	= imx_gpcv2_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= imx_gpcv2_domain_translate,
+	.alloc		= imx_gpcv2_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init imx_gpcv2_irqchip_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index b072166..63ac73b 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -67,22 +67,25 @@ static struct irq_chip mtk_sysirq_chip = {
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 };
 
-static int mtk_sysirq_domain_xlate(struct irq_domain *d,
-				   struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize,
-				   unsigned long *out_hwirq,
-				   unsigned int *out_type)
+static int mtk_sysirq_domain_translate(struct irq_domain *d,
+				       struct irq_fwspec *fwspec,
+				       unsigned long *hwirq,
+				       unsigned int *type)
 {
-	if (intsize != 3)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	/* sysirq doesn't support PPI */
-	if (intspec[0])
-		return -EINVAL;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-	return 0;
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -90,30 +93,30 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 {
 	int i;
 	irq_hw_number_t hwirq;
-	struct of_phandle_args *irq_data = arg;
-	struct of_phandle_args gic_data = *irq_data;
+	struct irq_fwspec *fwspec = arg;
+	struct irq_fwspec gic_fwspec = *fwspec;
 
-	if (irq_data->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;
 
 	/* sysirq doesn't support PPI */
-	if (irq_data->args[0])
+	if (fwspec->param[0])
 		return -EINVAL;
 
-	hwirq = irq_data->args[1];
+	hwirq = fwspec->param[1];
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &mtk_sysirq_chip,
 					      domain->host_data);
 
-	gic_data.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+	gic_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_fwspec);
 }
 
 static const struct irq_domain_ops sysirq_domain_ops = {
-	.xlate = mtk_sysirq_domain_xlate,
-	.alloc = mtk_sysirq_domain_alloc,
-	.free = irq_domain_free_irqs_common,
+	.translate	= mtk_sysirq_domain_translate,
+	.alloc		= mtk_sysirq_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init mtk_sysirq_of_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c
index a878b8d..b177710 100644
--- a/drivers/irqchip/irq-nvic.c
+++ b/drivers/irqchip/irq-nvic.c
@@ -48,16 +48,26 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
 	handle_IRQ(irq, regs);
 }
 
+static int nvic_irq_domain_translate(struct irq_domain *d,
+				     struct irq_fwspec *fwspec,
+				     unsigned long *hwirq, unsigned int *type)
+{
+	if (WARN_ON(fwspec->param_count < 1))
+		return -EINVAL;
+	*hwirq = fwspec->param[0];
+	*type = IRQ_TYPE_NONE;
+	return 0;
+}
+
 static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = irq_domain_xlate_onecell(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = nvic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -68,7 +78,7 @@ static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops nvic_irq_domain_ops = {
-	.xlate = irq_domain_xlate_onecell,
+	.translate = nvic_irq_domain_translate,
 	.alloc = nvic_irq_domain_alloc,
 	.free = irq_domain_free_irqs_top,
 };
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 7bbf226..557e15e 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -220,41 +220,43 @@ static struct irq_chip tegra_ictlr_chip = {
 #endif
 };
 
-static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
-				    struct device_node *controller,
-				    const u32 *intspec,
-				    unsigned int intsize,
-				    unsigned long *out_hwirq,
-				    unsigned int *out_type)
+static int tegra_ictlr_domain_translate(struct irq_domain *d,
+					struct irq_fwspec *fwspec,
+					unsigned long *hwirq,
+					unsigned int *type)
 {
-	if (irq_domain_get_of_node(domain) != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != GIC_SPI)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 				    unsigned int virq,
 				    unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	struct tegra_ictlr_info *info = domain->host_data;
 	irq_hw_number_t hwirq;
 	unsigned int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != GIC_SPI)
+	if (fwspec->param[0] != GIC_SPI)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= (num_ictlrs * 32))
 		return -EINVAL;
 
@@ -266,9 +268,10 @@ static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 					      info->base[ictlr]);
 	}
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static void tegra_ictlr_domain_free(struct irq_domain *domain,
@@ -284,9 +287,9 @@ static void tegra_ictlr_domain_free(struct irq_domain *domain,
 }
 
 static const struct irq_domain_ops tegra_ictlr_domain_ops = {
-	.xlate	= tegra_ictlr_domain_xlate,
-	.alloc	= tegra_ictlr_domain_alloc,
-	.free	= tegra_ictlr_domain_free,
+	.translate	= tegra_ictlr_domain_translate,
+	.alloc		= tegra_ictlr_domain_alloc,
+	.free		= tegra_ictlr_domain_free,
 };
 
 static int __init tegra_ictlr_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
index ae82d7e..56b5e3c 100644
--- a/drivers/irqchip/irq-vf610-mscm-ir.c
+++ b/drivers/irqchip/irq-vf610-mscm-ir.c
@@ -130,35 +130,51 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
 {
 	int i;
 	irq_hw_number_t hwirq;
-	struct of_phandle_args *irq_data = arg;
-	struct of_phandle_args gic_data;
+	struct irq_fwspec *fwspec = arg;
+	struct irq_fwspec parent_fwspec;
 
-	if (irq_data->args_count != 2)
+	if (!irq_domain_get_of_node(domain->parent))
 		return -EINVAL;
 
-	hwirq = irq_data->args[0];
+	if (fwspec->param_count != 2)
+		return -EINVAL;
+
+	hwirq = fwspec->param[0];
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &vf610_mscm_ir_irq_chip,
 					      domain->host_data);
 
-	gic_data.np = irq_domain_get_of_node(domain->parent);
+	parent_fwspec.fwnode = domain->parent->fwnode;
 
 	if (mscm_ir_data->is_nvic) {
-		gic_data.args_count = 1;
-		gic_data.args[0] = irq_data->args[0];
+		parent_fwspec.param_count = 1;
+		parent_fwspec.param[0] = fwspec->param[0];
 	} else {
-		gic_data.args_count = 3;
-		gic_data.args[0] = GIC_SPI;
-		gic_data.args[1] = irq_data->args[0];
-		gic_data.args[2] = irq_data->args[1];
+		parent_fwspec.param_count = 3;
+		parent_fwspec.param[0] = GIC_SPI;
+		parent_fwspec.param[1] = fwspec->param[0];
+		parent_fwspec.param[2] = fwspec->param[1];
 	}
 
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
+}
+
+static int vf610_mscm_ir_domain_translate(struct irq_domain *d,
+					  struct irq_fwspec *fwspec,
+					  unsigned long *hwirq,
+					  unsigned int *type)
+{
+	if (WARN_ON(fwspec->param_count < 2))
+		return -EINVAL;
+	*hwirq = fwspec->param[0];
+	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
 }
 
 static const struct irq_domain_ops mscm_irq_domain_ops = {
-	.xlate = irq_domain_xlate_twocell,
+	.translate = vf610_mscm_ir_domain_translate,
 	.alloc = vf610_mscm_ir_domain_alloc,
 	.free = irq_domain_free_irqs_common,
 };
-- 
2.1.4


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

* [PATCH 05/16] irqchip: Convert all alloc/xlate users from of_node to fwnode
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Since we now have a generic data structure to express an
interrupt specifier, convert all hierarchical irqchips that
are OF based to use a fwnode_handle as part of their alloc
and xlate (which becomes translate) callbacks.

As most of these drivers have dependencies (they exchange IRQ
specifiers), change them all in a single, massive patch...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-exynos/suspend.c       | 55 ++++++++++++++++---------------
 arch/arm/mach-imx/gpc.c              | 55 ++++++++++++++++---------------
 arch/arm/mach-omap2/omap-wakeupgen.c | 55 ++++++++++++++++---------------
 drivers/irqchip/irq-crossbar.c       | 62 ++++++++++++++++++----------------
 drivers/irqchip/irq-gic-v2m.c        | 18 ++++++----
 drivers/irqchip/irq-gic-v3-its.c     | 20 ++++++-----
 drivers/irqchip/irq-gic-v3.c         | 49 +++++++++++++--------------
 drivers/irqchip/irq-gic.c            | 33 ++++++++++++++++---
 drivers/irqchip/irq-imx-gpcv2.c      | 64 ++++++++++++++++--------------------
 drivers/irqchip/irq-mtk-sysirq.c     | 49 ++++++++++++++-------------
 drivers/irqchip/irq-nvic.c           | 18 +++++++---
 drivers/irqchip/irq-tegra.c          | 55 ++++++++++++++++---------------
 drivers/irqchip/irq-vf610-mscm-ir.c  | 42 +++++++++++++++--------
 13 files changed, 323 insertions(+), 252 deletions(-)

diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index e00eb39..5a7e47c 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -177,54 +177,57 @@ static struct irq_chip exynos_pmu_chip = {
 #endif
 };
 
-static int exynos_pmu_domain_xlate(struct irq_domain *domain,
-				   struct device_node *controller,
-				   const u32 *intspec,
-				   unsigned int intsize,
-				   unsigned long *out_hwirq,
-				   unsigned int *out_type)
+static int exynos_pmu_domain_translate(struct irq_domain *d,
+				       struct irq_fwspec *fwspec,
+				       unsigned long *hwirq,
+				       unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int exynos_pmu_domain_alloc(struct irq_domain *domain,
 				   unsigned int virq,
 				   unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &exynos_pmu_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops exynos_pmu_domain_ops = {
-	.xlate	= exynos_pmu_domain_xlate,
-	.alloc	= exynos_pmu_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= exynos_pmu_domain_translate,
+	.alloc		= exynos_pmu_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init exynos_pmu_irq_init(struct device_node *node,
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 8c4467f..10bf715 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -181,40 +181,42 @@ static struct irq_chip imx_gpc_chip = {
 #endif
 };
 
-static int imx_gpc_domain_xlate(struct irq_domain *domain,
-				struct device_node *controller,
-				const u32 *intspec,
-				unsigned int intsize,
-				unsigned long *out_hwirq,
-				unsigned int *out_type)
+static int imx_gpc_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int imx_gpc_domain_alloc(struct irq_domain *domain,
 				  unsigned int irq,
 				  unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= GPC_MAX_IRQS)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -222,15 +224,16 @@ static int imx_gpc_domain_alloc(struct irq_domain *domain,
 		irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
 					      &imx_gpc_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = domain->parent->of_node;
-	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops imx_gpc_domain_ops = {
-	.xlate	= imx_gpc_domain_xlate,
-	.alloc	= imx_gpc_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= imx_gpc_domain_translate,
+	.alloc		= imx_gpc_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init imx_gpc_init(struct device_node *node,
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index a52fe5b..db7e0ba 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -399,40 +399,42 @@ static struct irq_chip wakeupgen_chip = {
 #endif
 };
 
-static int wakeupgen_domain_xlate(struct irq_domain *domain,
-				  struct device_node *controller,
-				  const u32 *intspec,
-				  unsigned int intsize,
-				  unsigned long *out_hwirq,
-				  unsigned int *out_type)
+static int wakeupgen_domain_translate(struct irq_domain *d,
+				      struct irq_fwspec *fwspec,
+				      unsigned long *hwirq,
+				      unsigned int *type)
 {
-	if (domain->of_node != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int wakeupgen_domain_alloc(struct irq_domain *domain,
 				  unsigned int virq,
 				  unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= MAX_IRQS)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -440,15 +442,16 @@ static int wakeupgen_domain_alloc(struct irq_domain *domain,
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &wakeupgen_chip, NULL);
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static const struct irq_domain_ops wakeupgen_domain_ops = {
-	.xlate	= wakeupgen_domain_xlate,
-	.alloc	= wakeupgen_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= wakeupgen_domain_translate,
+	.alloc		= wakeupgen_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 /*
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index f1d666a..75573fa 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -78,10 +78,13 @@ static struct irq_chip crossbar_chip = {
 static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 			    irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
+	struct irq_fwspec fwspec;
 	int i;
 	int err;
 
+	if (!irq_domain_get_of_node(domain->parent))
+		return -EINVAL;
+
 	raw_spin_lock(&cb->lock);
 	for (i = cb->int_max - 1; i >= 0; i--) {
 		if (cb->irq_map[i] == IRQ_FREE) {
@@ -94,13 +97,13 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 	if (i < 0)
 		return -ENODEV;
 
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = 0;	/* SPI */
-	args.args[1] = i;
-	args.args[2] = IRQ_TYPE_LEVEL_HIGH;
+	fwspec.fwnode = domain->parent->fwnode;
+	fwspec.param_count = 3;
+	fwspec.param[0] = 0;	/* SPI */
+	fwspec.param[1] = i;
+	fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
 
-	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (err)
 		cb->irq_map[i] = IRQ_FREE;
 	else
@@ -112,16 +115,16 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
 static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
 				 unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
+	struct irq_fwspec *fwspec = data;
 	irq_hw_number_t hwirq;
 	int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != 0)
+	if (fwspec->param[0] != 0)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if ((hwirq + nr_irqs) > cb->max_crossbar_sources)
 		return -EINVAL;	/* Can't deal with this */
 
@@ -166,28 +169,31 @@ static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
 	raw_spin_unlock(&cb->lock);
 }
 
-static int crossbar_domain_xlate(struct irq_domain *d,
-				 struct device_node *controller,
-				 const u32 *intspec, unsigned int intsize,
-				 unsigned long *out_hwirq,
-				 unsigned int *out_type)
+static int crossbar_domain_translate(struct irq_domain *d,
+				     struct irq_fwspec *fwspec,
+				     unsigned long *hwirq,
+				     unsigned int *type)
 {
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != 0)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static const struct irq_domain_ops crossbar_domain_ops = {
-	.alloc	= crossbar_domain_alloc,
-	.free	= crossbar_domain_free,
-	.xlate	= crossbar_domain_xlate,
+	.alloc		= crossbar_domain_alloc,
+	.free		= crossbar_domain_free,
+	.translate	= crossbar_domain_translate,
 };
 
 static int __init crossbar_of_init(struct device_node *node)
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 695d489..b2b08dd 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -113,17 +113,21 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
 				       unsigned int virq,
 				       irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
+	struct irq_fwspec fwspec;
 	struct irq_data *d;
 	int err;
 
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = 0;
-	args.args[1] = hwirq - 32;
-	args.args[2] = IRQ_TYPE_EDGE_RISING;
+	if (is_of_node(domain->parent->fwnode)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 3;
+		fwspec.param[0] = 0;
+		fwspec.param[1] = hwirq - 32;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		return -EINVAL;
+	}
 
-	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (err)
 		return err;
 
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index ea4e5b2..f0d64e4 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1241,15 +1241,19 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 				    unsigned int virq,
 				    irq_hw_number_t hwirq)
 {
-	struct of_phandle_args args;
-
-	args.np = irq_domain_get_of_node(domain->parent);
-	args.args_count = 3;
-	args.args[0] = GIC_IRQ_TYPE_LPI;
-	args.args[1] = hwirq;
-	args.args[2] = IRQ_TYPE_EDGE_RISING;
+	struct irq_fwspec fwspec;
+
+	if (irq_domain_get_of_node(domain->parent)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 3;
+		fwspec.param[0] = GIC_IRQ_TYPE_LPI;
+		fwspec.param[1] = hwirq;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		return -EINVAL;
+	}
 
-	return irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 }
 
 static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 4c97ab6..e26a934 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -771,32 +771,30 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 	return 0;
 }
 
-static int gic_irq_domain_xlate(struct irq_domain *d,
-				struct device_node *controller,
-				const u32 *intspec, unsigned int intsize,
-				unsigned long *out_hwirq, unsigned int *out_type)
+static int gic_irq_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
 {
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;
-	if (intsize < 3)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count < 3)
+			return -EINVAL;
 
-	switch(intspec[0]) {
-	case 0:			/* SPI */
-		*out_hwirq = intspec[1] + 32;
-		break;
-	case 1:			/* PPI */
-		*out_hwirq = intspec[1] + 16;
-		break;
-	case GIC_IRQ_TYPE_LPI:	/* LPI */
-		*out_hwirq = intspec[1];
-		break;
-	default:
-		return -EINVAL;
+		/* Get the interrupt number and add 16 to skip over SGIs */
+		*hwirq = fwspec->param[1] + 16;
+
+		/*
+		 * For SPIs, we need to add 16 more to get the GIC irq
+		 * ID number
+		 */
+		if (!fwspec->param[0])
+			*hwirq += 16;
+
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
 	}
 
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-	return 0;
+	return -EINVAL;
 }
 
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -805,10 +803,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -831,7 +828,7 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops gic_irq_domain_ops = {
-	.xlate = gic_irq_domain_xlate,
+	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = gic_irq_domain_free,
 };
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 7f53acb..b0135be 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -927,6 +927,32 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 	return ret;
 }
 
+static int gic_irq_domain_translate(struct irq_domain *d,
+				    struct irq_fwspec *fwspec,
+				    unsigned long *hwirq,
+				    unsigned int *type)
+{
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count < 3)
+			return -EINVAL;
+
+		/* Get the interrupt number and add 16 to skip over SGIs */
+		*hwirq = fwspec->param[1] + 16;
+
+		/*
+		 * For SPIs, we need to add 16 more to get the GIC irq
+		 * ID number
+		 */
+		if (!fwspec->param[0])
+			*hwirq += 16;
+
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 #ifdef CONFIG_SMP
 static int gic_secondary_init(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
@@ -952,10 +978,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -966,7 +991,7 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
-	.xlate = gic_irq_domain_xlate,
+	.translate = gic_irq_domain_translate,
 	.alloc = gic_irq_domain_alloc,
 	.free = irq_domain_free_irqs_top,
 };
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index 8bba3c0..15af9a9 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -150,49 +150,42 @@ static struct irq_chip gpcv2_irqchip_data_chip = {
 #endif
 };
 
-static int imx_gpcv2_domain_xlate(struct irq_domain *domain,
-				struct device_node *controller,
-				const u32 *intspec,
-				unsigned int intsize,
-				unsigned long *out_hwirq,
-				unsigned int *out_type)
+static int imx_gpcv2_domain_translate(struct irq_domain *d,
+				      struct irq_fwspec *fwspec,
+				      unsigned long *hwirq,
+				      unsigned int *type)
 {
-	/* Shouldn't happen, really... */
-	if (domain->of_node != controller)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	/* Not GIC compliant */
-	if (intsize != 3)
-		return -EINVAL;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
 
-	/* No PPI should point to this domain */
-	if (intspec[0] != 0)
-		return -EINVAL;
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+	return -EINVAL;
 }
 
 static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 				  unsigned int irq, unsigned int nr_irqs,
 				  void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	irq_hw_number_t hwirq;
+	unsigned int type;
+	int err;
 	int i;
 
-	/* Not GIC compliant */
-	if (args->args_count != 3)
-		return -EINVAL;
-
-	/* No PPI should point to this domain */
-	if (args->args[0] != 0)
-		return -EINVAL;
+	err = imx_gpcv2_domain_translate(domain, fwspec, &hwirq, &type);
+	if (err)
+		return err;
 
-	/* Can't deal with this */
-	hwirq = args->args[1];
 	if (hwirq >= GPC_MAX_IRQS)
 		return -EINVAL;
 
@@ -201,15 +194,16 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
 				&gpcv2_irqchip_data_chip, domain->host_data);
 	}
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static struct irq_domain_ops gpcv2_irqchip_data_domain_ops = {
-	.xlate	= imx_gpcv2_domain_xlate,
-	.alloc	= imx_gpcv2_domain_alloc,
-	.free	= irq_domain_free_irqs_common,
+	.translate	= imx_gpcv2_domain_translate,
+	.alloc		= imx_gpcv2_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init imx_gpcv2_irqchip_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index b072166..63ac73b 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -67,22 +67,25 @@ static struct irq_chip mtk_sysirq_chip = {
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 };
 
-static int mtk_sysirq_domain_xlate(struct irq_domain *d,
-				   struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize,
-				   unsigned long *out_hwirq,
-				   unsigned int *out_type)
+static int mtk_sysirq_domain_translate(struct irq_domain *d,
+				       struct irq_fwspec *fwspec,
+				       unsigned long *hwirq,
+				       unsigned int *type)
 {
-	if (intsize != 3)
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	/* sysirq doesn't support PPI */
-	if (intspec[0])
-		return -EINVAL;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-	return 0;
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -90,30 +93,30 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 {
 	int i;
 	irq_hw_number_t hwirq;
-	struct of_phandle_args *irq_data = arg;
-	struct of_phandle_args gic_data = *irq_data;
+	struct irq_fwspec *fwspec = arg;
+	struct irq_fwspec gic_fwspec = *fwspec;
 
-	if (irq_data->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;
 
 	/* sysirq doesn't support PPI */
-	if (irq_data->args[0])
+	if (fwspec->param[0])
 		return -EINVAL;
 
-	hwirq = irq_data->args[1];
+	hwirq = fwspec->param[1];
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &mtk_sysirq_chip,
 					      domain->host_data);
 
-	gic_data.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+	gic_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_fwspec);
 }
 
 static const struct irq_domain_ops sysirq_domain_ops = {
-	.xlate = mtk_sysirq_domain_xlate,
-	.alloc = mtk_sysirq_domain_alloc,
-	.free = irq_domain_free_irqs_common,
+	.translate	= mtk_sysirq_domain_translate,
+	.alloc		= mtk_sysirq_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int __init mtk_sysirq_of_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c
index a878b8d..b177710 100644
--- a/drivers/irqchip/irq-nvic.c
+++ b/drivers/irqchip/irq-nvic.c
@@ -48,16 +48,26 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
 	handle_IRQ(irq, regs);
 }
 
+static int nvic_irq_domain_translate(struct irq_domain *d,
+				     struct irq_fwspec *fwspec,
+				     unsigned long *hwirq, unsigned int *type)
+{
+	if (WARN_ON(fwspec->param_count < 1))
+		return -EINVAL;
+	*hwirq = fwspec->param[0];
+	*type = IRQ_TYPE_NONE;
+	return 0;
+}
+
 static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs, void *arg)
 {
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct irq_fwspec *fwspec = arg;
 
-	ret = irq_domain_xlate_onecell(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+	ret = nvic_irq_domain_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -68,7 +78,7 @@ static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 }
 
 static const struct irq_domain_ops nvic_irq_domain_ops = {
-	.xlate = irq_domain_xlate_onecell,
+	.translate = nvic_irq_domain_translate,
 	.alloc = nvic_irq_domain_alloc,
 	.free = irq_domain_free_irqs_top,
 };
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 7bbf226..557e15e 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -220,41 +220,43 @@ static struct irq_chip tegra_ictlr_chip = {
 #endif
 };
 
-static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
-				    struct device_node *controller,
-				    const u32 *intspec,
-				    unsigned int intsize,
-				    unsigned long *out_hwirq,
-				    unsigned int *out_type)
+static int tegra_ictlr_domain_translate(struct irq_domain *d,
+					struct irq_fwspec *fwspec,
+					unsigned long *hwirq,
+					unsigned int *type)
 {
-	if (irq_domain_get_of_node(domain) != controller)
-		return -EINVAL;	/* Shouldn't happen, really... */
-	if (intsize != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (intspec[0] != GIC_SPI)
-		return -EINVAL;	/* No PPI should point to this domain */
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
 
-	*out_hwirq = intspec[1];
-	*out_type = intspec[2];
-	return 0;
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2];
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 				    unsigned int virq,
 				    unsigned int nr_irqs, void *data)
 {
-	struct of_phandle_args *args = data;
-	struct of_phandle_args parent_args;
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
 	struct tegra_ictlr_info *info = domain->host_data;
 	irq_hw_number_t hwirq;
 	unsigned int i;
 
-	if (args->args_count != 3)
+	if (fwspec->param_count != 3)
 		return -EINVAL;	/* Not GIC compliant */
-	if (args->args[0] != GIC_SPI)
+	if (fwspec->param[0] != GIC_SPI)
 		return -EINVAL;	/* No PPI should point to this domain */
 
-	hwirq = args->args[1];
+	hwirq = fwspec->param[1];
 	if (hwirq >= (num_ictlrs * 32))
 		return -EINVAL;
 
@@ -266,9 +268,10 @@ static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
 					      info->base[ictlr]);
 	}
 
-	parent_args = *args;
-	parent_args.np = irq_domain_get_of_node(domain->parent);
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
 }
 
 static void tegra_ictlr_domain_free(struct irq_domain *domain,
@@ -284,9 +287,9 @@ static void tegra_ictlr_domain_free(struct irq_domain *domain,
 }
 
 static const struct irq_domain_ops tegra_ictlr_domain_ops = {
-	.xlate	= tegra_ictlr_domain_xlate,
-	.alloc	= tegra_ictlr_domain_alloc,
-	.free	= tegra_ictlr_domain_free,
+	.translate	= tegra_ictlr_domain_translate,
+	.alloc		= tegra_ictlr_domain_alloc,
+	.free		= tegra_ictlr_domain_free,
 };
 
 static int __init tegra_ictlr_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
index ae82d7e..56b5e3c 100644
--- a/drivers/irqchip/irq-vf610-mscm-ir.c
+++ b/drivers/irqchip/irq-vf610-mscm-ir.c
@@ -130,35 +130,51 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
 {
 	int i;
 	irq_hw_number_t hwirq;
-	struct of_phandle_args *irq_data = arg;
-	struct of_phandle_args gic_data;
+	struct irq_fwspec *fwspec = arg;
+	struct irq_fwspec parent_fwspec;
 
-	if (irq_data->args_count != 2)
+	if (!irq_domain_get_of_node(domain->parent))
 		return -EINVAL;
 
-	hwirq = irq_data->args[0];
+	if (fwspec->param_count != 2)
+		return -EINVAL;
+
+	hwirq = fwspec->param[0];
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
 					      &vf610_mscm_ir_irq_chip,
 					      domain->host_data);
 
-	gic_data.np = irq_domain_get_of_node(domain->parent);
+	parent_fwspec.fwnode = domain->parent->fwnode;
 
 	if (mscm_ir_data->is_nvic) {
-		gic_data.args_count = 1;
-		gic_data.args[0] = irq_data->args[0];
+		parent_fwspec.param_count = 1;
+		parent_fwspec.param[0] = fwspec->param[0];
 	} else {
-		gic_data.args_count = 3;
-		gic_data.args[0] = GIC_SPI;
-		gic_data.args[1] = irq_data->args[0];
-		gic_data.args[2] = irq_data->args[1];
+		parent_fwspec.param_count = 3;
+		parent_fwspec.param[0] = GIC_SPI;
+		parent_fwspec.param[1] = fwspec->param[0];
+		parent_fwspec.param[2] = fwspec->param[1];
 	}
 
-	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
+}
+
+static int vf610_mscm_ir_domain_translate(struct irq_domain *d,
+					  struct irq_fwspec *fwspec,
+					  unsigned long *hwirq,
+					  unsigned int *type)
+{
+	if (WARN_ON(fwspec->param_count < 2))
+		return -EINVAL;
+	*hwirq = fwspec->param[0];
+	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
 }
 
 static const struct irq_domain_ops mscm_irq_domain_ops = {
-	.xlate = irq_domain_xlate_twocell,
+	.translate = vf610_mscm_ir_domain_translate,
 	.alloc = vf610_mscm_ir_domain_alloc,
 	.free = irq_domain_free_irqs_common,
 };
-- 
2.1.4

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

* [PATCH 06/16] irqdomain: Introduce irq_create_fwspec_mapping
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Suravee Suthikulpanit, Jake Oshins, Graeme Gregory,
	linux-arm-kernel

Just like we have irq_create_of_mapping, irq_create_fwspec_mapping
creates a IRQ domain mapping for an interrupt described in a
struct irq_fwspec.

irq_create_of_mapping gets rewritten in terms of the new function,
and the hack we introduced before gets removed (now that no stacked
irqchip uses of_phandle_args anymore).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h |  1 +
 kernel/irq/irqdomain.c    | 30 +++++++++++++++---------------
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 533c974..7e7842e 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -267,6 +267,7 @@ extern void irq_domain_disassociate(struct irq_domain *domain,
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
 				       irq_hw_number_t hwirq);
+extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec);
 extern void irq_dispose_mapping(unsigned int virq);
 
 /**
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 3f07055..2adc84e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -514,37 +514,28 @@ static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
 		fwspec->param[i] = irq_data->args[i];
 }
 
-unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
+unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 {
-	struct irq_fwspec fwspec;
 	struct irq_domain *domain;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	int virq;
 
-	of_phandle_args_to_fwspec(irq_data, &fwspec);
-
-	if (fwspec.fwnode)
-		domain = irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY);
+	if (fwspec->fwnode)
+		domain = irq_find_matching_fwnode(fwspec->fwnode, DOMAIN_BUS_ANY);
 	else
 		domain = irq_default_domain;
 
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
-			of_node_full_name(to_of_node(fwspec.fwnode)));
+			of_node_full_name(to_of_node(fwspec->fwnode)));
 		return 0;
 	}
 
-	if (irq_domain_translate(domain, &fwspec, &hwirq, &type))
+	if (irq_domain_translate(domain, fwspec, &hwirq, &type))
 		return 0;
 
 	if (irq_domain_is_hierarchy(domain)) {
-		/* Temporary hack */
-		void *desc = &fwspec;
-#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
-		if (!domain->ops->translate)
-			desc = irq_data;
-#endif
 		/*
 		 * If we've already configured this interrupt,
 		 * don't do it again, or hell will break loose.
@@ -553,7 +544,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		if (virq)
 			return virq;
 
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, desc);
+		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
 		if (virq <= 0)
 			return 0;
 	} else {
@@ -569,6 +560,15 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		irq_set_irq_type(virq, type);
 	return virq;
 }
+EXPORT_SYMBOL_GPL(irq_create_fwspec_mapping);
+
+unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
+{
+	struct irq_fwspec fwspec;
+
+	of_phandle_args_to_fwspec(irq_data, &fwspec);
+	return irq_create_fwspec_mapping(&fwspec);
+}
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
 
 /**
-- 
2.1.4

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

* [PATCH 06/16] irqdomain: Introduce irq_create_fwspec_mapping
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Just like we have irq_create_of_mapping, irq_create_fwspec_mapping
creates a IRQ domain mapping for an interrupt described in a
struct irq_fwspec.

irq_create_of_mapping gets rewritten in terms of the new function,
and the hack we introduced before gets removed (now that no stacked
irqchip uses of_phandle_args anymore).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h |  1 +
 kernel/irq/irqdomain.c    | 30 +++++++++++++++---------------
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 533c974..7e7842e 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -267,6 +267,7 @@ extern void irq_domain_disassociate(struct irq_domain *domain,
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
 				       irq_hw_number_t hwirq);
+extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec);
 extern void irq_dispose_mapping(unsigned int virq);
 
 /**
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 3f07055..2adc84e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -514,37 +514,28 @@ static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
 		fwspec->param[i] = irq_data->args[i];
 }
 
-unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
+unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 {
-	struct irq_fwspec fwspec;
 	struct irq_domain *domain;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	int virq;
 
-	of_phandle_args_to_fwspec(irq_data, &fwspec);
-
-	if (fwspec.fwnode)
-		domain = irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY);
+	if (fwspec->fwnode)
+		domain = irq_find_matching_fwnode(fwspec->fwnode, DOMAIN_BUS_ANY);
 	else
 		domain = irq_default_domain;
 
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
-			of_node_full_name(to_of_node(fwspec.fwnode)));
+			of_node_full_name(to_of_node(fwspec->fwnode)));
 		return 0;
 	}
 
-	if (irq_domain_translate(domain, &fwspec, &hwirq, &type))
+	if (irq_domain_translate(domain, fwspec, &hwirq, &type))
 		return 0;
 
 	if (irq_domain_is_hierarchy(domain)) {
-		/* Temporary hack */
-		void *desc = &fwspec;
-#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
-		if (!domain->ops->translate)
-			desc = irq_data;
-#endif
 		/*
 		 * If we've already configured this interrupt,
 		 * don't do it again, or hell will break loose.
@@ -553,7 +544,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		if (virq)
 			return virq;
 
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, desc);
+		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
 		if (virq <= 0)
 			return 0;
 	} else {
@@ -569,6 +560,15 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		irq_set_irq_type(virq, type);
 	return virq;
 }
+EXPORT_SYMBOL_GPL(irq_create_fwspec_mapping);
+
+unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
+{
+	struct irq_fwspec fwspec;
+
+	of_phandle_args_to_fwspec(irq_data, &fwspec);
+	return irq_create_fwspec_mapping(&fwspec);
+}
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
 
 /**
-- 
2.1.4


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

* [PATCH 06/16] irqdomain: Introduce irq_create_fwspec_mapping
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Just like we have irq_create_of_mapping, irq_create_fwspec_mapping
creates a IRQ domain mapping for an interrupt described in a
struct irq_fwspec.

irq_create_of_mapping gets rewritten in terms of the new function,
and the hack we introduced before gets removed (now that no stacked
irqchip uses of_phandle_args anymore).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h |  1 +
 kernel/irq/irqdomain.c    | 30 +++++++++++++++---------------
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 533c974..7e7842e 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -267,6 +267,7 @@ extern void irq_domain_disassociate(struct irq_domain *domain,
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
 				       irq_hw_number_t hwirq);
+extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec);
 extern void irq_dispose_mapping(unsigned int virq);
 
 /**
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 3f07055..2adc84e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -514,37 +514,28 @@ static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
 		fwspec->param[i] = irq_data->args[i];
 }
 
-unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
+unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 {
-	struct irq_fwspec fwspec;
 	struct irq_domain *domain;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	int virq;
 
-	of_phandle_args_to_fwspec(irq_data, &fwspec);
-
-	if (fwspec.fwnode)
-		domain = irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY);
+	if (fwspec->fwnode)
+		domain = irq_find_matching_fwnode(fwspec->fwnode, DOMAIN_BUS_ANY);
 	else
 		domain = irq_default_domain;
 
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
-			of_node_full_name(to_of_node(fwspec.fwnode)));
+			of_node_full_name(to_of_node(fwspec->fwnode)));
 		return 0;
 	}
 
-	if (irq_domain_translate(domain, &fwspec, &hwirq, &type))
+	if (irq_domain_translate(domain, fwspec, &hwirq, &type))
 		return 0;
 
 	if (irq_domain_is_hierarchy(domain)) {
-		/* Temporary hack */
-		void *desc = &fwspec;
-#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
-		if (!domain->ops->translate)
-			desc = irq_data;
-#endif
 		/*
 		 * If we've already configured this interrupt,
 		 * don't do it again, or hell will break loose.
@@ -553,7 +544,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		if (virq)
 			return virq;
 
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, desc);
+		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
 		if (virq <= 0)
 			return 0;
 	} else {
@@ -569,6 +560,15 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 		irq_set_irq_type(virq, type);
 	return virq;
 }
+EXPORT_SYMBOL_GPL(irq_create_fwspec_mapping);
+
+unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
+{
+	struct irq_fwspec fwspec;
+
+	of_phandle_args_to_fwspec(irq_data, &fwspec);
+	return irq_create_fwspec_mapping(&fwspec);
+}
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
 
 /**
-- 
2.1.4

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

* [PATCH 07/16] irqdomain: Introduce irq_domain_create_{linear,tree}
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Just like we have irq_domain_add_{linear,tree} to create a irq domain
identified by an of_node, introduce irq_domain_create_{linear,tree}
that do the same thing, except that they take a struct fwnode_handle.

Existing functions get rewritten in terms of the new ones so that
everything keeps working as before (and __irq_domain_add is now
fwnode_handle based as well).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 31 +++++++++++++++++++++++++------
 kernel/irq/irqdomain.c    | 11 ++++++-----
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 7e7842e..995d4c5 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -188,7 +188,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
 				    void *host_data);
@@ -207,11 +207,15 @@ extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
 						   enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 
+static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
+{
+	return node ? &node->fwnode : NULL;
+}
+
 static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
 							enum irq_domain_bus_token bus_token)
 {
-	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
-					bus_token);
+	return irq_find_matching_fwnode(of_node_to_fwnode(node), bus_token);
 }
 
 static inline struct irq_domain *irq_find_host(struct device_node *node)
@@ -231,14 +235,14 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
 }
 static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
 					 unsigned int max_irq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), 0, max_irq, max_irq, ops, host_data);
 }
 static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
@@ -252,7 +256,22 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), 0, ~0, 0, ops, host_data);
+}
+
+static inline struct irq_domain *irq_domain_create_linear(struct fwnode_handle *fwnode,
+					 unsigned int size,
+					 const struct irq_domain_ops *ops,
+					 void *host_data)
+{
+	return __irq_domain_add(fwnode, size, size, 0, ops, host_data);
+}
+
+static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fwnode,
+					 const struct irq_domain_ops *ops,
+					 void *host_data)
+{
+	return __irq_domain_add(fwnode, 0, ~0, 0, ops, host_data);
 }
 
 extern void irq_domain_remove(struct irq_domain *host);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 2adc84e..ea62f67 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -40,13 +40,15 @@ static void irq_domain_check_hierarchy(struct irq_domain *domain);
  * Allocates and initialize and irq_domain structure.
  * Returns pointer to IRQ domain, or NULL on failure.
  */
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
 				    void *host_data)
 {
 	struct irq_domain *domain;
-	struct fwnode_handle *fwnode;
+	struct device_node *of_node;
+
+	of_node = to_of_node(fwnode);
 
 	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
 			      GFP_KERNEL, of_node_to_nid(of_node));
@@ -54,7 +56,6 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 		return NULL;
 
 	of_node_get(of_node);
-	fwnode = of_node ? &of_node->fwnode : NULL;
 
 	/* Fill structure */
 	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
@@ -137,7 +138,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	domain = __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
 	if (!domain)
 		return NULL;
 
@@ -181,7 +182,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, first_hwirq + size,
+	domain = __irq_domain_add(of_node_to_fwnode(of_node), first_hwirq + size,
 				  first_hwirq + size, 0, ops, host_data);
 	if (domain)
 		irq_domain_associate_many(domain, first_irq, first_hwirq, size);
-- 
2.1.4

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

* [PATCH 07/16] irqdomain: Introduce irq_domain_create_{linear,tree}
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Just like we have irq_domain_add_{linear,tree} to create a irq domain
identified by an of_node, introduce irq_domain_create_{linear,tree}
that do the same thing, except that they take a struct fwnode_handle.

Existing functions get rewritten in terms of the new ones so that
everything keeps working as before (and __irq_domain_add is now
fwnode_handle based as well).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 31 +++++++++++++++++++++++++------
 kernel/irq/irqdomain.c    | 11 ++++++-----
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 7e7842e..995d4c5 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -188,7 +188,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
 				    void *host_data);
@@ -207,11 +207,15 @@ extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
 						   enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 
+static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
+{
+	return node ? &node->fwnode : NULL;
+}
+
 static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
 							enum irq_domain_bus_token bus_token)
 {
-	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
-					bus_token);
+	return irq_find_matching_fwnode(of_node_to_fwnode(node), bus_token);
 }
 
 static inline struct irq_domain *irq_find_host(struct device_node *node)
@@ -231,14 +235,14 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
 }
 static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
 					 unsigned int max_irq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), 0, max_irq, max_irq, ops, host_data);
 }
 static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
@@ -252,7 +256,22 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), 0, ~0, 0, ops, host_data);
+}
+
+static inline struct irq_domain *irq_domain_create_linear(struct fwnode_handle *fwnode,
+					 unsigned int size,
+					 const struct irq_domain_ops *ops,
+					 void *host_data)
+{
+	return __irq_domain_add(fwnode, size, size, 0, ops, host_data);
+}
+
+static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fwnode,
+					 const struct irq_domain_ops *ops,
+					 void *host_data)
+{
+	return __irq_domain_add(fwnode, 0, ~0, 0, ops, host_data);
 }
 
 extern void irq_domain_remove(struct irq_domain *host);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 2adc84e..ea62f67 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -40,13 +40,15 @@ static void irq_domain_check_hierarchy(struct irq_domain *domain);
  * Allocates and initialize and irq_domain structure.
  * Returns pointer to IRQ domain, or NULL on failure.
  */
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
 				    void *host_data)
 {
 	struct irq_domain *domain;
-	struct fwnode_handle *fwnode;
+	struct device_node *of_node;
+
+	of_node = to_of_node(fwnode);
 
 	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
 			      GFP_KERNEL, of_node_to_nid(of_node));
@@ -54,7 +56,6 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 		return NULL;
 
 	of_node_get(of_node);
-	fwnode = of_node ? &of_node->fwnode : NULL;
 
 	/* Fill structure */
 	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
@@ -137,7 +138,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	domain = __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
 	if (!domain)
 		return NULL;
 
@@ -181,7 +182,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, first_hwirq + size,
+	domain = __irq_domain_add(of_node_to_fwnode(of_node), first_hwirq + size,
 				  first_hwirq + size, 0, ops, host_data);
 	if (domain)
 		irq_domain_associate_many(domain, first_irq, first_hwirq, size);
-- 
2.1.4


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

* [PATCH 07/16] irqdomain: Introduce irq_domain_create_{linear,tree}
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Just like we have irq_domain_add_{linear,tree} to create a irq domain
identified by an of_node, introduce irq_domain_create_{linear,tree}
that do the same thing, except that they take a struct fwnode_handle.

Existing functions get rewritten in terms of the new ones so that
everything keeps working as before (and __irq_domain_add is now
fwnode_handle based as well).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 31 +++++++++++++++++++++++++------
 kernel/irq/irqdomain.c    | 11 ++++++-----
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 7e7842e..995d4c5 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -188,7 +188,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
 				    void *host_data);
@@ -207,11 +207,15 @@ extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
 						   enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 
+static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
+{
+	return node ? &node->fwnode : NULL;
+}
+
 static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
 							enum irq_domain_bus_token bus_token)
 {
-	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
-					bus_token);
+	return irq_find_matching_fwnode(of_node_to_fwnode(node), bus_token);
 }
 
 static inline struct irq_domain *irq_find_host(struct device_node *node)
@@ -231,14 +235,14 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
 }
 static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
 					 unsigned int max_irq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), 0, max_irq, max_irq, ops, host_data);
 }
 static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
@@ -252,7 +256,22 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
+	return __irq_domain_add(of_node_to_fwnode(of_node), 0, ~0, 0, ops, host_data);
+}
+
+static inline struct irq_domain *irq_domain_create_linear(struct fwnode_handle *fwnode,
+					 unsigned int size,
+					 const struct irq_domain_ops *ops,
+					 void *host_data)
+{
+	return __irq_domain_add(fwnode, size, size, 0, ops, host_data);
+}
+
+static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fwnode,
+					 const struct irq_domain_ops *ops,
+					 void *host_data)
+{
+	return __irq_domain_add(fwnode, 0, ~0, 0, ops, host_data);
 }
 
 extern void irq_domain_remove(struct irq_domain *host);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 2adc84e..ea62f67 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -40,13 +40,15 @@ static void irq_domain_check_hierarchy(struct irq_domain *domain);
  * Allocates and initialize and irq_domain structure.
  * Returns pointer to IRQ domain, or NULL on failure.
  */
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
 				    void *host_data)
 {
 	struct irq_domain *domain;
-	struct fwnode_handle *fwnode;
+	struct device_node *of_node;
+
+	of_node = to_of_node(fwnode);
 
 	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
 			      GFP_KERNEL, of_node_to_nid(of_node));
@@ -54,7 +56,6 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 		return NULL;
 
 	of_node_get(of_node);
-	fwnode = of_node ? &of_node->fwnode : NULL;
 
 	/* Fill structure */
 	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
@@ -137,7 +138,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	domain = __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
 	if (!domain)
 		return NULL;
 
@@ -181,7 +182,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, first_hwirq + size,
+	domain = __irq_domain_add(of_node_to_fwnode(of_node), first_hwirq + size,
 				  first_hwirq + size, 0, ops, host_data);
 	if (domain)
 		irq_domain_associate_many(domain, first_irq, first_hwirq, size);
-- 
2.1.4

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

* [PATCH 08/16] irqdomain: Add a fwnode_handle allocator
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Suravee Suthikulpanit, Jake Oshins, Graeme Gregory,
	linux-arm-kernel

In order to be able to reference an irqdomain from ACPI, we need
to be able to create an identifier, which is usually a struct
device_node.

This device node does't really fit the ACPI infrastructure, so
we cunningly allocate a new structure containing a fwnode_handle,
and return that.

This structure doesn't really point to a device (interrupt
controllers are not "real" devices in Linux), but as we cannot
really deny that they exist, we create them with a new fwnode_type
(FWNODE_IRQCHIP).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/fwnode.h    |  1 +
 include/linux/irqdomain.h |  2 ++
 kernel/irq/irqdomain.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 0408545..37ec668 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -17,6 +17,7 @@ enum fwnode_type {
 	FWNODE_OF,
 	FWNODE_ACPI,
 	FWNODE_PDATA,
+	FWNODE_IRQCHIP,
 };
 
 struct fwnode_handle {
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 995d4c5..949caa7 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
+struct fwnode_handle *irq_domain_alloc_fwnode(void *data);
+void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
 struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index ea62f67..6fbecae 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
 				  irq_hw_number_t hwirq, int node);
 static void irq_domain_check_hierarchy(struct irq_domain *domain);
 
+struct irqchip_fwid {
+	struct fwnode_handle fwnode;
+	char *name;
+	void *data;
+};
+
+/**
+ * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
+ *                           identifying an irq domain
+ * @data: optional user-provided data
+ *
+ * Allocate a struct device_node, and return a poiner to the embedded
+ * fwnode_handle (or NULL on failure).
+ */
+struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+{
+	struct irqchip_fwid *fwid;
+	char *name;
+
+	fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
+	name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
+
+	if (!fwid || !name) {
+		kfree(fwid);
+		kfree(name);
+		return NULL;
+	}
+
+	fwid->name = name;
+	fwid->data = data;
+	fwid->fwnode.type = FWNODE_IRQCHIP;
+	return &fwid->fwnode;
+}
+
+/**
+ * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
+ *
+ * Free a fwnode_handle allocated with irq_domain_alloc_fwnode.
+ */
+void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
+{
+	struct irqchip_fwid *fwid;
+
+	if (WARN_ON(fwnode->type != FWNODE_IRQCHIP))
+		return;
+
+	fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
+	kfree(fwid->name);
+	kfree(fwid);
+}
+
 /**
  * __irq_domain_add() - Allocate a new irq_domain data structure
  * @of_node: optional device-tree node of the interrupt controller
-- 
2.1.4

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

* [PATCH 08/16] irqdomain: Add a fwnode_handle allocator
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

In order to be able to reference an irqdomain from ACPI, we need
to be able to create an identifier, which is usually a struct
device_node.

This device node does't really fit the ACPI infrastructure, so
we cunningly allocate a new structure containing a fwnode_handle,
and return that.

This structure doesn't really point to a device (interrupt
controllers are not "real" devices in Linux), but as we cannot
really deny that they exist, we create them with a new fwnode_type
(FWNODE_IRQCHIP).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/fwnode.h    |  1 +
 include/linux/irqdomain.h |  2 ++
 kernel/irq/irqdomain.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 0408545..37ec668 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -17,6 +17,7 @@ enum fwnode_type {
 	FWNODE_OF,
 	FWNODE_ACPI,
 	FWNODE_PDATA,
+	FWNODE_IRQCHIP,
 };
 
 struct fwnode_handle {
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 995d4c5..949caa7 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
+struct fwnode_handle *irq_domain_alloc_fwnode(void *data);
+void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
 struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index ea62f67..6fbecae 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
 				  irq_hw_number_t hwirq, int node);
 static void irq_domain_check_hierarchy(struct irq_domain *domain);
 
+struct irqchip_fwid {
+	struct fwnode_handle fwnode;
+	char *name;
+	void *data;
+};
+
+/**
+ * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
+ *                           identifying an irq domain
+ * @data: optional user-provided data
+ *
+ * Allocate a struct device_node, and return a poiner to the embedded
+ * fwnode_handle (or NULL on failure).
+ */
+struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+{
+	struct irqchip_fwid *fwid;
+	char *name;
+
+	fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
+	name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
+
+	if (!fwid || !name) {
+		kfree(fwid);
+		kfree(name);
+		return NULL;
+	}
+
+	fwid->name = name;
+	fwid->data = data;
+	fwid->fwnode.type = FWNODE_IRQCHIP;
+	return &fwid->fwnode;
+}
+
+/**
+ * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
+ *
+ * Free a fwnode_handle allocated with irq_domain_alloc_fwnode.
+ */
+void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
+{
+	struct irqchip_fwid *fwid;
+
+	if (WARN_ON(fwnode->type != FWNODE_IRQCHIP))
+		return;
+
+	fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
+	kfree(fwid->name);
+	kfree(fwid);
+}
+
 /**
  * __irq_domain_add() - Allocate a new irq_domain data structure
  * @of_node: optional device-tree node of the interrupt controller
-- 
2.1.4


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

* [PATCH 08/16] irqdomain: Add a fwnode_handle allocator
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

In order to be able to reference an irqdomain from ACPI, we need
to be able to create an identifier, which is usually a struct
device_node.

This device node does't really fit the ACPI infrastructure, so
we cunningly allocate a new structure containing a fwnode_handle,
and return that.

This structure doesn't really point to a device (interrupt
controllers are not "real" devices in Linux), but as we cannot
really deny that they exist, we create them with a new fwnode_type
(FWNODE_IRQCHIP).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/fwnode.h    |  1 +
 include/linux/irqdomain.h |  2 ++
 kernel/irq/irqdomain.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 0408545..37ec668 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -17,6 +17,7 @@ enum fwnode_type {
 	FWNODE_OF,
 	FWNODE_ACPI,
 	FWNODE_PDATA,
+	FWNODE_IRQCHIP,
 };
 
 struct fwnode_handle {
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 995d4c5..949caa7 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
+struct fwnode_handle *irq_domain_alloc_fwnode(void *data);
+void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
 struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index ea62f67..6fbecae 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
 				  irq_hw_number_t hwirq, int node);
 static void irq_domain_check_hierarchy(struct irq_domain *domain);
 
+struct irqchip_fwid {
+	struct fwnode_handle fwnode;
+	char *name;
+	void *data;
+};
+
+/**
+ * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
+ *                           identifying an irq domain
+ * @data: optional user-provided data
+ *
+ * Allocate a struct device_node, and return a poiner to the embedded
+ * fwnode_handle (or NULL on failure).
+ */
+struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+{
+	struct irqchip_fwid *fwid;
+	char *name;
+
+	fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
+	name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
+
+	if (!fwid || !name) {
+		kfree(fwid);
+		kfree(name);
+		return NULL;
+	}
+
+	fwid->name = name;
+	fwid->data = data;
+	fwid->fwnode.type = FWNODE_IRQCHIP;
+	return &fwid->fwnode;
+}
+
+/**
+ * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
+ *
+ * Free a fwnode_handle allocated with irq_domain_alloc_fwnode.
+ */
+void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
+{
+	struct irqchip_fwid *fwid;
+
+	if (WARN_ON(fwnode->type != FWNODE_IRQCHIP))
+		return;
+
+	fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
+	kfree(fwid->name);
+	kfree(fwid);
+}
+
 /**
  * __irq_domain_add() - Allocate a new irq_domain data structure
  * @of_node: optional device-tree node of the interrupt controller
-- 
2.1.4

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

* [PATCH 09/16] acpi/gsi: Always perform an irq domain lookup
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Instead of directly passing NULL to the various irq_domain functions,
start by looking up the domain with a domain identifier..

As this identifier is permanently set to NULL, the lookup function will
return the same value (no domain found) and the default will be used,
preserving the current behaviour.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/gsi.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2..2c39fe1 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -11,9 +11,12 @@
 #include <linux/acpi.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/of.h>
 
 enum acpi_irq_model_id acpi_irq_model;
 
+static struct fwnode_handle *acpi_gsi_domain_id;
+
 static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
 {
 	switch (polarity) {
@@ -45,12 +48,10 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	/*
-	 * Only default domain is supported at present, always find
-	 * the mapping corresponding to default domain by passing NULL
-	 * as irq_domain parameter
-	 */
-	*irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
+
+	*irq = irq_find_mapping(d, gsi);
 	/*
 	 * *irq == 0 means no mapping, that should
 	 * be reported as a failure
@@ -74,13 +75,10 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 {
 	unsigned int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
 
-	/*
-	 * There is no way at present to look-up the IRQ domain on ACPI,
-	 * hence always create mapping referring to the default domain
-	 * by passing NULL as irq_domain parameter
-	 */
-	irq = irq_create_mapping(NULL, gsi);
+	irq = irq_create_mapping(d, gsi);
 	if (!irq)
 		return -EINVAL;
 
@@ -98,7 +96,9 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	int irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
+	int irq = irq_find_mapping(d, gsi);
 
 	irq_dispose_mapping(irq);
 }
-- 
2.1.4

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

* [PATCH 09/16] acpi/gsi: Always perform an irq domain lookup
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Instead of directly passing NULL to the various irq_domain functions,
start by looking up the domain with a domain identifier..

As this identifier is permanently set to NULL, the lookup function will
return the same value (no domain found) and the default will be used,
preserving the current behaviour.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/gsi.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2..2c39fe1 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -11,9 +11,12 @@
 #include <linux/acpi.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/of.h>
 
 enum acpi_irq_model_id acpi_irq_model;
 
+static struct fwnode_handle *acpi_gsi_domain_id;
+
 static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
 {
 	switch (polarity) {
@@ -45,12 +48,10 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	/*
-	 * Only default domain is supported at present, always find
-	 * the mapping corresponding to default domain by passing NULL
-	 * as irq_domain parameter
-	 */
-	*irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
+
+	*irq = irq_find_mapping(d, gsi);
 	/*
 	 * *irq == 0 means no mapping, that should
 	 * be reported as a failure
@@ -74,13 +75,10 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 {
 	unsigned int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
 
-	/*
-	 * There is no way at present to look-up the IRQ domain on ACPI,
-	 * hence always create mapping referring to the default domain
-	 * by passing NULL as irq_domain parameter
-	 */
-	irq = irq_create_mapping(NULL, gsi);
+	irq = irq_create_mapping(d, gsi);
 	if (!irq)
 		return -EINVAL;
 
@@ -98,7 +96,9 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	int irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
+	int irq = irq_find_mapping(d, gsi);
 
 	irq_dispose_mapping(irq);
 }
-- 
2.1.4


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

* [PATCH 09/16] acpi/gsi: Always perform an irq domain lookup
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Instead of directly passing NULL to the various irq_domain functions,
start by looking up the domain with a domain identifier..

As this identifier is permanently set to NULL, the lookup function will
return the same value (no domain found) and the default will be used,
preserving the current behaviour.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/gsi.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2..2c39fe1 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -11,9 +11,12 @@
 #include <linux/acpi.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/of.h>
 
 enum acpi_irq_model_id acpi_irq_model;
 
+static struct fwnode_handle *acpi_gsi_domain_id;
+
 static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
 {
 	switch (polarity) {
@@ -45,12 +48,10 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	/*
-	 * Only default domain is supported at present, always find
-	 * the mapping corresponding to default domain by passing NULL
-	 * as irq_domain parameter
-	 */
-	*irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
+
+	*irq = irq_find_mapping(d, gsi);
 	/*
 	 * *irq == 0 means no mapping, that should
 	 * be reported as a failure
@@ -74,13 +75,10 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 {
 	unsigned int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
 
-	/*
-	 * There is no way at present to look-up the IRQ domain on ACPI,
-	 * hence always create mapping referring to the default domain
-	 * by passing NULL as irq_domain parameter
-	 */
-	irq = irq_create_mapping(NULL, gsi);
+	irq = irq_create_mapping(d, gsi);
 	if (!irq)
 		return -EINVAL;
 
@@ -98,7 +96,9 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	int irq = irq_find_mapping(NULL, gsi);
+	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+							DOMAIN_BUS_ANY);
+	int irq = irq_find_mapping(d, gsi);
 
 	irq_dispose_mapping(irq);
 }
-- 
2.1.4

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

* [PATCH 10/16] acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Suravee Suthikulpanit, Jake Oshins, Graeme Gregory,
	linux-arm-kernel

In order to start embrassing irqdomains at the GSI level, introduce
a new initializer:

void acpi_set_irq_model(enum acpi_irq_model_id model,
			struct fwnode_handle *fwnode);

where:
- model is the value assigned to acpi_irq_model
- fwnode is the identifier for the irqdomain mapping
  GSI interrupts

As nobody calls this code yet, the current code is (mostly)
left in place.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Conflicts:
	include/linux/acpi.h
---
 drivers/acpi/gsi.c   | 32 +++++++++++++++++++++++++++-----
 include/linux/acpi.h |  3 +++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 2c39fe1..202a8fe 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -75,12 +75,21 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 {
 	unsigned int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
-	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-							DOMAIN_BUS_ANY);
 
-	irq = irq_create_mapping(d, gsi);
-	if (!irq)
-		return -EINVAL;
+	if (acpi_gsi_domain_id) {
+		struct irq_fwspec fwspec;
+
+		fwspec.fwnode = acpi_gsi_domain_id;
+		fwspec.param[0] = gsi;
+		fwspec.param[1] = irq_type;
+		fwspec.param_count = 2;
+
+		return irq_create_fwspec_mapping(&fwspec);
+	} else {
+		irq = irq_create_mapping(NULL, gsi);
+		if (!irq)
+			return -EINVAL;
+	}
 
 	/* Set irq type if specified and different than the current one */
 	if (irq_type != IRQ_TYPE_NONE &&
@@ -103,3 +112,16 @@ void acpi_unregister_gsi(u32 gsi)
 	irq_dispose_mapping(irq);
 }
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
+
+/**
+ * acpi_set_irq_model - Setup the GSI irqdomain information
+ * @model: the value assigned to acpi_irq_model
+ * @fwnode: the irq_domain identifier for mapping and looking up
+ *          GSI interrupts
+ */
+void __init acpi_set_irq_model(enum acpi_irq_model_id model,
+			       struct fwnode_handle *fwnode)
+{
+	acpi_irq_model = model;
+	acpi_gsi_domain_id = fwnode;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 43856d1..d863e12 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -201,6 +201,9 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
 
+void acpi_set_irq_model(enum acpi_irq_model_id model,
+			struct fwnode_handle *fwnode);
+
 #ifdef CONFIG_X86_IO_APIC
 extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
 #else
-- 
2.1.4

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

* [PATCH 10/16] acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

In order to start embrassing irqdomains at the GSI level, introduce
a new initializer:

void acpi_set_irq_model(enum acpi_irq_model_id model,
			struct fwnode_handle *fwnode);

where:
- model is the value assigned to acpi_irq_model
- fwnode is the identifier for the irqdomain mapping
  GSI interrupts

As nobody calls this code yet, the current code is (mostly)
left in place.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Conflicts:
	include/linux/acpi.h
---
 drivers/acpi/gsi.c   | 32 +++++++++++++++++++++++++++-----
 include/linux/acpi.h |  3 +++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 2c39fe1..202a8fe 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -75,12 +75,21 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 {
 	unsigned int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
-	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-							DOMAIN_BUS_ANY);
 
-	irq = irq_create_mapping(d, gsi);
-	if (!irq)
-		return -EINVAL;
+	if (acpi_gsi_domain_id) {
+		struct irq_fwspec fwspec;
+
+		fwspec.fwnode = acpi_gsi_domain_id;
+		fwspec.param[0] = gsi;
+		fwspec.param[1] = irq_type;
+		fwspec.param_count = 2;
+
+		return irq_create_fwspec_mapping(&fwspec);
+	} else {
+		irq = irq_create_mapping(NULL, gsi);
+		if (!irq)
+			return -EINVAL;
+	}
 
 	/* Set irq type if specified and different than the current one */
 	if (irq_type != IRQ_TYPE_NONE &&
@@ -103,3 +112,16 @@ void acpi_unregister_gsi(u32 gsi)
 	irq_dispose_mapping(irq);
 }
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
+
+/**
+ * acpi_set_irq_model - Setup the GSI irqdomain information
+ * @model: the value assigned to acpi_irq_model
+ * @fwnode: the irq_domain identifier for mapping and looking up
+ *          GSI interrupts
+ */
+void __init acpi_set_irq_model(enum acpi_irq_model_id model,
+			       struct fwnode_handle *fwnode)
+{
+	acpi_irq_model = model;
+	acpi_gsi_domain_id = fwnode;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 43856d1..d863e12 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -201,6 +201,9 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
 
+void acpi_set_irq_model(enum acpi_irq_model_id model,
+			struct fwnode_handle *fwnode);
+
 #ifdef CONFIG_X86_IO_APIC
 extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
 #else
-- 
2.1.4


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

* [PATCH 10/16] acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

In order to start embrassing irqdomains at the GSI level, introduce
a new initializer:

void acpi_set_irq_model(enum acpi_irq_model_id model,
			struct fwnode_handle *fwnode);

where:
- model is the value assigned to acpi_irq_model
- fwnode is the identifier for the irqdomain mapping
  GSI interrupts

As nobody calls this code yet, the current code is (mostly)
left in place.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Conflicts:
	include/linux/acpi.h
---
 drivers/acpi/gsi.c   | 32 +++++++++++++++++++++++++++-----
 include/linux/acpi.h |  3 +++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 2c39fe1..202a8fe 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -75,12 +75,21 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 {
 	unsigned int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
-	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-							DOMAIN_BUS_ANY);
 
-	irq = irq_create_mapping(d, gsi);
-	if (!irq)
-		return -EINVAL;
+	if (acpi_gsi_domain_id) {
+		struct irq_fwspec fwspec;
+
+		fwspec.fwnode = acpi_gsi_domain_id;
+		fwspec.param[0] = gsi;
+		fwspec.param[1] = irq_type;
+		fwspec.param_count = 2;
+
+		return irq_create_fwspec_mapping(&fwspec);
+	} else {
+		irq = irq_create_mapping(NULL, gsi);
+		if (!irq)
+			return -EINVAL;
+	}
 
 	/* Set irq type if specified and different than the current one */
 	if (irq_type != IRQ_TYPE_NONE &&
@@ -103,3 +112,16 @@ void acpi_unregister_gsi(u32 gsi)
 	irq_dispose_mapping(irq);
 }
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
+
+/**
+ * acpi_set_irq_model - Setup the GSI irqdomain information
+ * @model: the value assigned to acpi_irq_model
+ * @fwnode: the irq_domain identifier for mapping and looking up
+ *          GSI interrupts
+ */
+void __init acpi_set_irq_model(enum acpi_irq_model_id model,
+			       struct fwnode_handle *fwnode)
+{
+	acpi_irq_model = model;
+	acpi_gsi_domain_id = fwnode;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 43856d1..d863e12 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -201,6 +201,9 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
 
+void acpi_set_irq_model(enum acpi_irq_model_id model,
+			struct fwnode_handle *fwnode);
+
 #ifdef CONFIG_X86_IO_APIC
 extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
 #else
-- 
2.1.4

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

* [PATCH 11/16] irqchip/gic: Get rid of gic_init_bases()
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Since nobody is using gic_init_bases anymore outside of the GIC
driver itself, let's do a bit of housekeeping and remove the now
useless entry point.

Only gic_init() is now exposed to the rest of the kernel for the
benefit of legacy systems.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 8 +++-----
 include/linux/irqchip/arm-gic.h | 9 ++-------
 2 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index b0135be..f1f4ca1 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1112,17 +1112,15 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 	gic_pm_init(gic);
 }
 
-void __init gic_init_bases(unsigned int gic_nr, int irq_start,
-			   void __iomem *dist_base, void __iomem *cpu_base,
-			   u32 percpu_offset, struct device_node *node)
+void __init gic_init(unsigned int gic_nr, int irq_start,
+		     void __iomem *dist_base, void __iomem *cpu_base)
 {
 	/*
 	 * Non-DT/ACPI systems won't run a hypervisor, so let's not
 	 * bother with these...
 	 */
 	static_key_slow_dec(&supports_deactivate);
-	__gic_init_bases(gic_nr, irq_start, dist_base, cpu_base,
-			 percpu_offset, node);
+	__gic_init_bases(gic_nr, irq_start, dist_base, cpu_base, 0, NULL);
 }
 
 #ifdef CONFIG_OF
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index b8901df..bae69e5 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -100,16 +100,11 @@
 
 struct device_node;
 
-void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
-		    u32 offset, struct device_node *);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 int gic_cpu_if_down(unsigned int gic_nr);
 
-static inline void gic_init(unsigned int nr, int start,
-			    void __iomem *dist , void __iomem *cpu)
-{
-	gic_init_bases(nr, start, dist, cpu, 0, NULL);
-}
+void gic_init(unsigned int nr, int start,
+	      void __iomem *dist , void __iomem *cpu);
 
 int gicv2m_of_init(struct device_node *node, struct irq_domain *parent);
 
-- 
2.1.4

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

* [PATCH 11/16] irqchip/gic: Get rid of gic_init_bases()
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Since nobody is using gic_init_bases anymore outside of the GIC
driver itself, let's do a bit of housekeeping and remove the now
useless entry point.

Only gic_init() is now exposed to the rest of the kernel for the
benefit of legacy systems.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 8 +++-----
 include/linux/irqchip/arm-gic.h | 9 ++-------
 2 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index b0135be..f1f4ca1 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1112,17 +1112,15 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 	gic_pm_init(gic);
 }
 
-void __init gic_init_bases(unsigned int gic_nr, int irq_start,
-			   void __iomem *dist_base, void __iomem *cpu_base,
-			   u32 percpu_offset, struct device_node *node)
+void __init gic_init(unsigned int gic_nr, int irq_start,
+		     void __iomem *dist_base, void __iomem *cpu_base)
 {
 	/*
 	 * Non-DT/ACPI systems won't run a hypervisor, so let's not
 	 * bother with these...
 	 */
 	static_key_slow_dec(&supports_deactivate);
-	__gic_init_bases(gic_nr, irq_start, dist_base, cpu_base,
-			 percpu_offset, node);
+	__gic_init_bases(gic_nr, irq_start, dist_base, cpu_base, 0, NULL);
 }
 
 #ifdef CONFIG_OF
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index b8901df..bae69e5 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -100,16 +100,11 @@
 
 struct device_node;
 
-void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
-		    u32 offset, struct device_node *);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 int gic_cpu_if_down(unsigned int gic_nr);
 
-static inline void gic_init(unsigned int nr, int start,
-			    void __iomem *dist , void __iomem *cpu)
-{
-	gic_init_bases(nr, start, dist, cpu, 0, NULL);
-}
+void gic_init(unsigned int nr, int start,
+	      void __iomem *dist , void __iomem *cpu);
 
 int gicv2m_of_init(struct device_node *node, struct irq_domain *parent);
 
-- 
2.1.4


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

* [PATCH 11/16] irqchip/gic: Get rid of gic_init_bases()
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Since nobody is using gic_init_bases anymore outside of the GIC
driver itself, let's do a bit of housekeeping and remove the now
useless entry point.

Only gic_init() is now exposed to the rest of the kernel for the
benefit of legacy systems.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 8 +++-----
 include/linux/irqchip/arm-gic.h | 9 ++-------
 2 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index b0135be..f1f4ca1 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1112,17 +1112,15 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 	gic_pm_init(gic);
 }
 
-void __init gic_init_bases(unsigned int gic_nr, int irq_start,
-			   void __iomem *dist_base, void __iomem *cpu_base,
-			   u32 percpu_offset, struct device_node *node)
+void __init gic_init(unsigned int gic_nr, int irq_start,
+		     void __iomem *dist_base, void __iomem *cpu_base)
 {
 	/*
 	 * Non-DT/ACPI systems won't run a hypervisor, so let's not
 	 * bother with these...
 	 */
 	static_key_slow_dec(&supports_deactivate);
-	__gic_init_bases(gic_nr, irq_start, dist_base, cpu_base,
-			 percpu_offset, node);
+	__gic_init_bases(gic_nr, irq_start, dist_base, cpu_base, 0, NULL);
 }
 
 #ifdef CONFIG_OF
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index b8901df..bae69e5 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -100,16 +100,11 @@
 
 struct device_node;
 
-void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
-		    u32 offset, struct device_node *);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 int gic_cpu_if_down(unsigned int gic_nr);
 
-static inline void gic_init(unsigned int nr, int start,
-			    void __iomem *dist , void __iomem *cpu)
-{
-	gic_init_bases(nr, start, dist, cpu, 0, NULL);
-}
+void gic_init(unsigned int nr, int start,
+	      void __iomem *dist , void __iomem *cpu);
 
 int gicv2m_of_init(struct device_node *node, struct irq_domain *parent);
 
-- 
2.1.4

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

* [PATCH 12/16] irqchip/gic: Switch ACPI support to stacked domains
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Now that the basic ACPI GSI code is irq domain aware, make sure
that the ACPI support in the GIC doesn't pointlessly deviate from
the DT path.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c | 44 ++++++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index f1f4ca1..ad5ecfd 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -950,6 +950,15 @@ static int gic_irq_domain_translate(struct irq_domain *d,
 		return 0;
 	}
 
+	if (fwspec->fwnode->type == FWNODE_IRQCHIP) {
+		if(fwspec->param_count != 2)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+
 	return -EINVAL;
 }
 
@@ -1004,7 +1013,7 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 
 static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 			   void __iomem *dist_base, void __iomem *cpu_base,
-			   u32 percpu_offset, struct device_node *node)
+			   u32 percpu_offset, struct fwnode_handle *handle)
 {
 	irq_hw_number_t hwirq_base;
 	struct gic_chip_data *gic;
@@ -1056,11 +1065,11 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	if (node) {		/* DT case */
-		gic->domain = irq_domain_add_linear(node, gic_irqs,
-						    &gic_irq_domain_hierarchy_ops,
-						    gic);
-	} else {		/* Non-DT case */
+	if (handle) {		/* DT/ACPI */
+		gic->domain = irq_domain_create_linear(handle, gic_irqs,
+						       &gic_irq_domain_hierarchy_ops,
+						       gic);
+	} else {		/* Legacy support */
 		/*
 		 * For primary GICs, skip over SGIs.
 		 * For secondary GICs, skip over PPIs, too.
@@ -1083,7 +1092,7 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 			irq_base = irq_start;
 		}
 
-		gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
+		gic->domain = irq_domain_add_legacy(NULL, gic_irqs, irq_base,
 					hwirq_base, &gic_irq_domain_ops, gic);
 	}
 
@@ -1191,7 +1200,8 @@ gic_of_init(struct device_node *node, struct device_node *parent)
 	if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
 		percpu_offset = 0;
 
-	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
+	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
+			 &node->fwnode);
 	if (!gic_cnt)
 		gic_init_physaddr(node);
 
@@ -1265,6 +1275,7 @@ int __init
 gic_v2_acpi_init(struct acpi_table_header *table)
 {
 	void __iomem *cpu_base, *dist_base;
+	struct fwnode_handle *domain_handle;
 	int count;
 
 	/* Collect CPU base addresses */
@@ -1315,14 +1326,19 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 		static_key_slow_dec(&supports_deactivate);
 
 	/*
-	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
-	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
-	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
+	 * Initialize GIC instance zero (no multi-GIC support).
 	 */
-	__gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
-	irq_set_default_host(gic_data[0].domain);
+	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	if (!domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		iounmap(cpu_base);
+		iounmap(dist_base);
+		return -ENOMEM;
+	}
+
+	__gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
 
-	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
+	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
 	return 0;
 }
 #endif
-- 
2.1.4

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

* [PATCH 12/16] irqchip/gic: Switch ACPI support to stacked domains
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

Now that the basic ACPI GSI code is irq domain aware, make sure
that the ACPI support in the GIC doesn't pointlessly deviate from
the DT path.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c | 44 ++++++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index f1f4ca1..ad5ecfd 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -950,6 +950,15 @@ static int gic_irq_domain_translate(struct irq_domain *d,
 		return 0;
 	}
 
+	if (fwspec->fwnode->type == FWNODE_IRQCHIP) {
+		if(fwspec->param_count != 2)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+
 	return -EINVAL;
 }
 
@@ -1004,7 +1013,7 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 
 static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 			   void __iomem *dist_base, void __iomem *cpu_base,
-			   u32 percpu_offset, struct device_node *node)
+			   u32 percpu_offset, struct fwnode_handle *handle)
 {
 	irq_hw_number_t hwirq_base;
 	struct gic_chip_data *gic;
@@ -1056,11 +1065,11 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	if (node) {		/* DT case */
-		gic->domain = irq_domain_add_linear(node, gic_irqs,
-						    &gic_irq_domain_hierarchy_ops,
-						    gic);
-	} else {		/* Non-DT case */
+	if (handle) {		/* DT/ACPI */
+		gic->domain = irq_domain_create_linear(handle, gic_irqs,
+						       &gic_irq_domain_hierarchy_ops,
+						       gic);
+	} else {		/* Legacy support */
 		/*
 		 * For primary GICs, skip over SGIs.
 		 * For secondary GICs, skip over PPIs, too.
@@ -1083,7 +1092,7 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 			irq_base = irq_start;
 		}
 
-		gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
+		gic->domain = irq_domain_add_legacy(NULL, gic_irqs, irq_base,
 					hwirq_base, &gic_irq_domain_ops, gic);
 	}
 
@@ -1191,7 +1200,8 @@ gic_of_init(struct device_node *node, struct device_node *parent)
 	if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
 		percpu_offset = 0;
 
-	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
+	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
+			 &node->fwnode);
 	if (!gic_cnt)
 		gic_init_physaddr(node);
 
@@ -1265,6 +1275,7 @@ int __init
 gic_v2_acpi_init(struct acpi_table_header *table)
 {
 	void __iomem *cpu_base, *dist_base;
+	struct fwnode_handle *domain_handle;
 	int count;
 
 	/* Collect CPU base addresses */
@@ -1315,14 +1326,19 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 		static_key_slow_dec(&supports_deactivate);
 
 	/*
-	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
-	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
-	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
+	 * Initialize GIC instance zero (no multi-GIC support).
 	 */
-	__gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
-	irq_set_default_host(gic_data[0].domain);
+	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	if (!domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		iounmap(cpu_base);
+		iounmap(dist_base);
+		return -ENOMEM;
+	}
+
+	__gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
 
-	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
+	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
 	return 0;
 }
 #endif
-- 
2.1.4


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

* [PATCH 12/16] irqchip/gic: Switch ACPI support to stacked domains
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Now that the basic ACPI GSI code is irq domain aware, make sure
that the ACPI support in the GIC doesn't pointlessly deviate from
the DT path.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c | 44 ++++++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index f1f4ca1..ad5ecfd 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -950,6 +950,15 @@ static int gic_irq_domain_translate(struct irq_domain *d,
 		return 0;
 	}
 
+	if (fwspec->fwnode->type == FWNODE_IRQCHIP) {
+		if(fwspec->param_count != 2)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+
 	return -EINVAL;
 }
 
@@ -1004,7 +1013,7 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 
 static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 			   void __iomem *dist_base, void __iomem *cpu_base,
-			   u32 percpu_offset, struct device_node *node)
+			   u32 percpu_offset, struct fwnode_handle *handle)
 {
 	irq_hw_number_t hwirq_base;
 	struct gic_chip_data *gic;
@@ -1056,11 +1065,11 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	if (node) {		/* DT case */
-		gic->domain = irq_domain_add_linear(node, gic_irqs,
-						    &gic_irq_domain_hierarchy_ops,
-						    gic);
-	} else {		/* Non-DT case */
+	if (handle) {		/* DT/ACPI */
+		gic->domain = irq_domain_create_linear(handle, gic_irqs,
+						       &gic_irq_domain_hierarchy_ops,
+						       gic);
+	} else {		/* Legacy support */
 		/*
 		 * For primary GICs, skip over SGIs.
 		 * For secondary GICs, skip over PPIs, too.
@@ -1083,7 +1092,7 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 			irq_base = irq_start;
 		}
 
-		gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
+		gic->domain = irq_domain_add_legacy(NULL, gic_irqs, irq_base,
 					hwirq_base, &gic_irq_domain_ops, gic);
 	}
 
@@ -1191,7 +1200,8 @@ gic_of_init(struct device_node *node, struct device_node *parent)
 	if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
 		percpu_offset = 0;
 
-	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
+	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
+			 &node->fwnode);
 	if (!gic_cnt)
 		gic_init_physaddr(node);
 
@@ -1265,6 +1275,7 @@ int __init
 gic_v2_acpi_init(struct acpi_table_header *table)
 {
 	void __iomem *cpu_base, *dist_base;
+	struct fwnode_handle *domain_handle;
 	int count;
 
 	/* Collect CPU base addresses */
@@ -1315,14 +1326,19 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 		static_key_slow_dec(&supports_deactivate);
 
 	/*
-	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
-	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
-	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
+	 * Initialize GIC instance zero (no multi-GIC support).
 	 */
-	__gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
-	irq_set_default_host(gic_data[0].domain);
+	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	if (!domain_handle) {
+		pr_err("Unable to allocate domain handle\n");
+		iounmap(cpu_base);
+		iounmap(dist_base);
+		return -ENOMEM;
+	}
+
+	__gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
 
-	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
+	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
 	return 0;
 }
 #endif
-- 
2.1.4

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

* [PATCH 13/16] irqchip/gic: Kill the xlate method
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

We are now left with only two use models for the GIC driver:
- Via a firmware interface, which mandates a hierarchical domain,
  and the use of the 'translate' method
- The legacy platforms, which assume irq==hwirq, hence not using
  the 'xlate' method.

The logical conclusion is that we can now nuke the 'xlate' method
altogether.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index ad5ecfd..a4bd77f 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -903,30 +903,6 @@ static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
 {
 }
 
-static int gic_irq_domain_xlate(struct irq_domain *d,
-				struct device_node *controller,
-				const u32 *intspec, unsigned int intsize,
-				unsigned long *out_hwirq, unsigned int *out_type)
-{
-	unsigned long ret = 0;
-
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;
-	if (intsize < 3)
-		return -EINVAL;
-
-	/* Get the interrupt number and add 16 to skip over SGIs */
-	*out_hwirq = intspec[1] + 16;
-
-	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
-	if (!intspec[0])
-		*out_hwirq += 16;
-
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-
-	return ret;
-}
-
 static int gic_irq_domain_translate(struct irq_domain *d,
 				    struct irq_fwspec *fwspec,
 				    unsigned long *hwirq,
@@ -1008,7 +984,6 @@ static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
 static const struct irq_domain_ops gic_irq_domain_ops = {
 	.map = gic_irq_domain_map,
 	.unmap = gic_irq_domain_unmap,
-	.xlate = gic_irq_domain_xlate,
 };
 
 static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
-- 
2.1.4

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

* [PATCH 13/16] irqchip/gic: Kill the xlate method
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

We are now left with only two use models for the GIC driver:
- Via a firmware interface, which mandates a hierarchical domain,
  and the use of the 'translate' method
- The legacy platforms, which assume irq==hwirq, hence not using
  the 'xlate' method.

The logical conclusion is that we can now nuke the 'xlate' method
altogether.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index ad5ecfd..a4bd77f 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -903,30 +903,6 @@ static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
 {
 }
 
-static int gic_irq_domain_xlate(struct irq_domain *d,
-				struct device_node *controller,
-				const u32 *intspec, unsigned int intsize,
-				unsigned long *out_hwirq, unsigned int *out_type)
-{
-	unsigned long ret = 0;
-
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;
-	if (intsize < 3)
-		return -EINVAL;
-
-	/* Get the interrupt number and add 16 to skip over SGIs */
-	*out_hwirq = intspec[1] + 16;
-
-	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
-	if (!intspec[0])
-		*out_hwirq += 16;
-
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-
-	return ret;
-}
-
 static int gic_irq_domain_translate(struct irq_domain *d,
 				    struct irq_fwspec *fwspec,
 				    unsigned long *hwirq,
@@ -1008,7 +984,6 @@ static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
 static const struct irq_domain_ops gic_irq_domain_ops = {
 	.map = gic_irq_domain_map,
 	.unmap = gic_irq_domain_unmap,
-	.xlate = gic_irq_domain_xlate,
 };
 
 static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
-- 
2.1.4


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

* [PATCH 13/16] irqchip/gic: Kill the xlate method
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

We are now left with only two use models for the GIC driver:
- Via a firmware interface, which mandates a hierarchical domain,
  and the use of the 'translate' method
- The legacy platforms, which assume irq==hwirq, hence not using
  the 'xlate' method.

The logical conclusion is that we can now nuke the 'xlate' method
altogether.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index ad5ecfd..a4bd77f 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -903,30 +903,6 @@ static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
 {
 }
 
-static int gic_irq_domain_xlate(struct irq_domain *d,
-				struct device_node *controller,
-				const u32 *intspec, unsigned int intsize,
-				unsigned long *out_hwirq, unsigned int *out_type)
-{
-	unsigned long ret = 0;
-
-	if (irq_domain_get_of_node(d) != controller)
-		return -EINVAL;
-	if (intsize < 3)
-		return -EINVAL;
-
-	/* Get the interrupt number and add 16 to skip over SGIs */
-	*out_hwirq = intspec[1] + 16;
-
-	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
-	if (!intspec[0])
-		*out_hwirq += 16;
-
-	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-
-	return ret;
-}
-
 static int gic_irq_domain_translate(struct irq_domain *d,
 				    struct irq_fwspec *fwspec,
 				    unsigned long *hwirq,
@@ -1008,7 +984,6 @@ static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
 static const struct irq_domain_ops gic_irq_domain_ops = {
 	.map = gic_irq_domain_map,
 	.unmap = gic_irq_domain_unmap,
-	.xlate = gic_irq_domain_xlate,
 };
 
 static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
-- 
2.1.4

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

* [PATCH 14/16] acpi/gsi: Cleanup acpi_register_gsi
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

As the only user of drivers/acpi/gsi.c is now using acpi_set_irq_model
to set acpi_gsi_descriptor_populate to something meaningful, we can
always rely on that information to be present (its absence is an error),
and guarantee that new interrupt controllers will use this API.

Take this opportunity to cleanup acpi_register_gsi.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/gsi.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 202a8fe..fa4585a 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -73,29 +73,19 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 		      int polarity)
 {
-	unsigned int irq;
-	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_fwspec fwspec;
 
-	if (acpi_gsi_domain_id) {
-		struct irq_fwspec fwspec;
-
-		fwspec.fwnode = acpi_gsi_domain_id;
-		fwspec.param[0] = gsi;
-		fwspec.param[1] = irq_type;
-		fwspec.param_count = 2;
-
-		return irq_create_fwspec_mapping(&fwspec);
-	} else {
-		irq = irq_create_mapping(NULL, gsi);
-		if (!irq)
-			return -EINVAL;
+	if (WARN_ON(!acpi_gsi_domain_id)) {
+		pr_warn("GSI: No registered irqchip, giving up\n");
+		return -EINVAL;
 	}
 
-	/* Set irq type if specified and different than the current one */
-	if (irq_type != IRQ_TYPE_NONE &&
-		irq_type != irq_get_trigger_type(irq))
-		irq_set_irq_type(irq, irq_type);
-	return irq;
+	fwspec.fwnode = acpi_gsi_domain_id;
+	fwspec.param[0] = gsi;
+	fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
+	fwspec.param_count = 2;
+
+	return irq_create_fwspec_mapping(&fwspec);
 }
 EXPORT_SYMBOL_GPL(acpi_register_gsi);
 
-- 
2.1.4


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

* [PATCH 14/16] acpi/gsi: Cleanup acpi_register_gsi
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

As the only user of drivers/acpi/gsi.c is now using acpi_set_irq_model
to set acpi_gsi_descriptor_populate to something meaningful, we can
always rely on that information to be present (its absence is an error),
and guarantee that new interrupt controllers will use this API.

Take this opportunity to cleanup acpi_register_gsi.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/gsi.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 202a8fe..fa4585a 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -73,29 +73,19 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 		      int polarity)
 {
-	unsigned int irq;
-	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_fwspec fwspec;
 
-	if (acpi_gsi_domain_id) {
-		struct irq_fwspec fwspec;
-
-		fwspec.fwnode = acpi_gsi_domain_id;
-		fwspec.param[0] = gsi;
-		fwspec.param[1] = irq_type;
-		fwspec.param_count = 2;
-
-		return irq_create_fwspec_mapping(&fwspec);
-	} else {
-		irq = irq_create_mapping(NULL, gsi);
-		if (!irq)
-			return -EINVAL;
+	if (WARN_ON(!acpi_gsi_domain_id)) {
+		pr_warn("GSI: No registered irqchip, giving up\n");
+		return -EINVAL;
 	}
 
-	/* Set irq type if specified and different than the current one */
-	if (irq_type != IRQ_TYPE_NONE &&
-		irq_type != irq_get_trigger_type(irq))
-		irq_set_irq_type(irq, irq_type);
-	return irq;
+	fwspec.fwnode = acpi_gsi_domain_id;
+	fwspec.param[0] = gsi;
+	fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
+	fwspec.param_count = 2;
+
+	return irq_create_fwspec_mapping(&fwspec);
 }
 EXPORT_SYMBOL_GPL(acpi_register_gsi);
 
-- 
2.1.4


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

* [PATCH 14/16] acpi/gsi: Cleanup acpi_register_gsi
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

As the only user of drivers/acpi/gsi.c is now using acpi_set_irq_model
to set acpi_gsi_descriptor_populate to something meaningful, we can
always rely on that information to be present (its absence is an error),
and guarantee that new interrupt controllers will use this API.

Take this opportunity to cleanup acpi_register_gsi.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/gsi.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 202a8fe..fa4585a 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -73,29 +73,19 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 		      int polarity)
 {
-	unsigned int irq;
-	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+	struct irq_fwspec fwspec;
 
-	if (acpi_gsi_domain_id) {
-		struct irq_fwspec fwspec;
-
-		fwspec.fwnode = acpi_gsi_domain_id;
-		fwspec.param[0] = gsi;
-		fwspec.param[1] = irq_type;
-		fwspec.param_count = 2;
-
-		return irq_create_fwspec_mapping(&fwspec);
-	} else {
-		irq = irq_create_mapping(NULL, gsi);
-		if (!irq)
-			return -EINVAL;
+	if (WARN_ON(!acpi_gsi_domain_id)) {
+		pr_warn("GSI: No registered irqchip, giving up\n");
+		return -EINVAL;
 	}
 
-	/* Set irq type if specified and different than the current one */
-	if (irq_type != IRQ_TYPE_NONE &&
-		irq_type != irq_get_trigger_type(irq))
-		irq_set_irq_type(irq, irq_type);
-	return irq;
+	fwspec.fwnode = acpi_gsi_domain_id;
+	fwspec.param[0] = gsi;
+	fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
+	fwspec.param_count = 2;
+
+	return irq_create_fwspec_mapping(&fwspec);
 }
 EXPORT_SYMBOL_GPL(acpi_register_gsi);
 
-- 
2.1.4

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

* [PATCH 15/16] irqdomain: Introduce irq_domain_create_hierarchy
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

As we're about to start converting the various MSI layers to
use fwnode_handle instead of device_node, add irq_domain_create_hierarchy
as a directly equivalent of irq_domain_add_hierarchy (which still
exists as a compatibility interface).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 17 +++++++++++++++--
 kernel/irq/irqdomain.c    | 10 +++++-----
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 949caa7..2b3340ae 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -340,10 +340,23 @@ extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
 				void *chip_data, irq_flow_handler_t handler,
 				void *handler_data, const char *handler_name);
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
-extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+extern struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
 			unsigned int flags, unsigned int size,
-			struct device_node *node,
+			struct fwnode_handle *fwnode,
 			const struct irq_domain_ops *ops, void *host_data);
+
+static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+					    unsigned int flags,
+					    unsigned int size,
+					    struct device_node *node,
+					    const struct irq_domain_ops *ops,
+					    void *host_data)
+{
+	return irq_domain_create_hierarchy(parent, flags, size,
+					   of_node_to_fwnode(node),
+					   ops, host_data);
+}
+
 extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
 				   unsigned int nr_irqs, int node, void *arg,
 				   bool realloc);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 6fbecae..a53b60f 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -858,7 +858,7 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
  * @parent:	Parent irq domain to associate with the new domain
  * @flags:	Irq domain flags associated to the domain
  * @size:	Size of the domain. See below
- * @node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @ops:	Pointer to the interrupt domain callbacks
  * @host_data:	Controller private data pointer
  *
@@ -868,19 +868,19 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
  * domain flags are set.
  * Returns pointer to IRQ domain, or NULL on failure.
  */
-struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
 					    unsigned int flags,
 					    unsigned int size,
-					    struct device_node *node,
+					    struct fwnode_handle *fwnode,
 					    const struct irq_domain_ops *ops,
 					    void *host_data)
 {
 	struct irq_domain *domain;
 
 	if (size)
-		domain = irq_domain_add_linear(node, size, ops, host_data);
+		domain = irq_domain_create_linear(fwnode, size, ops, host_data);
 	else
-		domain = irq_domain_add_tree(node, ops, host_data);
+		domain = irq_domain_create_tree(fwnode, ops, host_data);
 	if (domain) {
 		domain->parent = parent;
 		domain->flags |= flags;
-- 
2.1.4

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

* [PATCH 15/16] irqdomain: Introduce irq_domain_create_hierarchy
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

As we're about to start converting the various MSI layers to
use fwnode_handle instead of device_node, add irq_domain_create_hierarchy
as a directly equivalent of irq_domain_add_hierarchy (which still
exists as a compatibility interface).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 17 +++++++++++++++--
 kernel/irq/irqdomain.c    | 10 +++++-----
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 949caa7..2b3340ae 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -340,10 +340,23 @@ extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
 				void *chip_data, irq_flow_handler_t handler,
 				void *handler_data, const char *handler_name);
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
-extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+extern struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
 			unsigned int flags, unsigned int size,
-			struct device_node *node,
+			struct fwnode_handle *fwnode,
 			const struct irq_domain_ops *ops, void *host_data);
+
+static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+					    unsigned int flags,
+					    unsigned int size,
+					    struct device_node *node,
+					    const struct irq_domain_ops *ops,
+					    void *host_data)
+{
+	return irq_domain_create_hierarchy(parent, flags, size,
+					   of_node_to_fwnode(node),
+					   ops, host_data);
+}
+
 extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
 				   unsigned int nr_irqs, int node, void *arg,
 				   bool realloc);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 6fbecae..a53b60f 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -858,7 +858,7 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
  * @parent:	Parent irq domain to associate with the new domain
  * @flags:	Irq domain flags associated to the domain
  * @size:	Size of the domain. See below
- * @node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @ops:	Pointer to the interrupt domain callbacks
  * @host_data:	Controller private data pointer
  *
@@ -868,19 +868,19 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
  * domain flags are set.
  * Returns pointer to IRQ domain, or NULL on failure.
  */
-struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
 					    unsigned int flags,
 					    unsigned int size,
-					    struct device_node *node,
+					    struct fwnode_handle *fwnode,
 					    const struct irq_domain_ops *ops,
 					    void *host_data)
 {
 	struct irq_domain *domain;
 
 	if (size)
-		domain = irq_domain_add_linear(node, size, ops, host_data);
+		domain = irq_domain_create_linear(fwnode, size, ops, host_data);
 	else
-		domain = irq_domain_add_tree(node, ops, host_data);
+		domain = irq_domain_create_tree(fwnode, ops, host_data);
 	if (domain) {
 		domain->parent = parent;
 		domain->flags |= flags;
-- 
2.1.4


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

* [PATCH 15/16] irqdomain: Introduce irq_domain_create_hierarchy
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

As we're about to start converting the various MSI layers to
use fwnode_handle instead of device_node, add irq_domain_create_hierarchy
as a directly equivalent of irq_domain_add_hierarchy (which still
exists as a compatibility interface).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqdomain.h | 17 +++++++++++++++--
 kernel/irq/irqdomain.c    | 10 +++++-----
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 949caa7..2b3340ae 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -340,10 +340,23 @@ extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
 				void *chip_data, irq_flow_handler_t handler,
 				void *handler_data, const char *handler_name);
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
-extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+extern struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
 			unsigned int flags, unsigned int size,
-			struct device_node *node,
+			struct fwnode_handle *fwnode,
 			const struct irq_domain_ops *ops, void *host_data);
+
+static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+					    unsigned int flags,
+					    unsigned int size,
+					    struct device_node *node,
+					    const struct irq_domain_ops *ops,
+					    void *host_data)
+{
+	return irq_domain_create_hierarchy(parent, flags, size,
+					   of_node_to_fwnode(node),
+					   ops, host_data);
+}
+
 extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
 				   unsigned int nr_irqs, int node, void *arg,
 				   bool realloc);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 6fbecae..a53b60f 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -858,7 +858,7 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
  * @parent:	Parent irq domain to associate with the new domain
  * @flags:	Irq domain flags associated to the domain
  * @size:	Size of the domain. See below
- * @node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @ops:	Pointer to the interrupt domain callbacks
  * @host_data:	Controller private data pointer
  *
@@ -868,19 +868,19 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
  * domain flags are set.
  * Returns pointer to IRQ domain, or NULL on failure.
  */
-struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
+struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
 					    unsigned int flags,
 					    unsigned int size,
-					    struct device_node *node,
+					    struct fwnode_handle *fwnode,
 					    const struct irq_domain_ops *ops,
 					    void *host_data)
 {
 	struct irq_domain *domain;
 
 	if (size)
-		domain = irq_domain_add_linear(node, size, ops, host_data);
+		domain = irq_domain_create_linear(fwnode, size, ops, host_data);
 	else
-		domain = irq_domain_add_tree(node, ops, host_data);
+		domain = irq_domain_create_tree(fwnode, ops, host_data);
 	if (domain) {
 		domain->parent = parent;
 		domain->flags |= flags;
-- 
2.1.4

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

* [PATCH 16/16] irqdomain/msi: Use fwnode instead of of_node
  2015-10-06 17:36 ` Marc Zyngier
  (?)
@ 2015-10-06 17:36   ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

As we continue to push of_node towards the outskirts of irq domains,
let's start tackling the case of msi_create_irq_domain and its little
friends.

This has limited impact in both PCI/MSI, platform MSI, and a few
drivers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/base/platform-msi.c                   |  6 +++---
 drivers/irqchip/irq-gic-v2m.c                 |  5 +++--
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |  3 ++-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |  3 ++-
 drivers/pci/host/pci-xgene-msi.c              |  2 +-
 drivers/pci/msi.c                             | 14 +++++++-------
 include/linux/msi.h                           |  9 +++++----
 kernel/irq/msi.c                              |  8 ++++----
 8 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 134483d..5df4575 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -152,7 +152,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
 
 /**
  * platform_msi_create_irq_domain - Create a platform MSI interrupt domain
- * @np:		Optional device-tree node of the interrupt controller
+ * @fwnode:		Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
@@ -162,7 +162,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
  * Returns:
  * A domain pointer or NULL in case of failure.
  */
-struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
 						  struct msi_domain_info *info,
 						  struct irq_domain *parent)
 {
@@ -173,7 +173,7 @@ struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		platform_msi_update_chip_ops(info);
 
-	domain = msi_create_irq_domain(np, info, parent);
+	domain = msi_create_irq_domain(fwnode, info, parent);
 	if (domain)
 		domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
 
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index b2b08dd..93bb843 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -286,9 +286,10 @@ static int __init gicv2m_init_one(struct device_node *node,
 
 	inner_domain->bus_token = DOMAIN_BUS_NEXUS;
 	inner_domain->parent = parent;
-	pci_domain = pci_msi_create_irq_domain(node, &gicv2m_msi_domain_info,
+	pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
+					       &gicv2m_msi_domain_info,
 					       inner_domain);
-	plat_domain = platform_msi_create_irq_domain(node,
+	plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
 						     &gicv2m_pmsi_domain_info,
 						     inner_domain);
 	if (!pci_domain || !plat_domain) {
diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index a7c8c9f..693c2f9 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -125,7 +125,8 @@ static int __init its_pci_msi_init(void)
 			continue;
 		}
 
-		if (!pci_msi_create_irq_domain(np, &its_pci_msi_domain_info,
+		if (!pci_msi_create_irq_domain(of_node_to_fwnode(np),
+					       &its_pci_msi_domain_info,
 					       parent)) {
 			pr_err("%s: unable to create PCI domain\n",
 			       np->full_name);
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
index a865505..960a816 100644
--- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
@@ -78,7 +78,8 @@ static int __init its_pmsi_init(void)
 			continue;
 		}
 
-		if (!platform_msi_create_irq_domain(np, &its_pmsi_domain_info,
+		if (!platform_msi_create_irq_domain(of_node_to_fwnode(np),
+						    &its_pmsi_domain_info,
 						    parent)) {
 			pr_err("%s: unable to create platform domain\n",
 			       np->full_name);
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
index e491681..a6456b5 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/host/pci-xgene-msi.c
@@ -256,7 +256,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
 	if (!msi->inner_domain)
 		return -ENOMEM;
 
-	msi->msi_domain = pci_msi_create_irq_domain(msi->node,
+	msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
 						    &xgene_msi_domain_info,
 						    msi->inner_domain);
 
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d449714..ddd59fe 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1246,8 +1246,8 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
 }
 
 /**
- * pci_msi_create_irq_domain - Creat a MSI interrupt domain
- * @node:	Optional device-tree node of the interrupt controller
+ * pci_msi_create_irq_domain - Create a MSI interrupt domain
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
@@ -1256,7 +1256,7 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
  * Returns:
  * A domain pointer or NULL in case of failure.
  */
-struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
 					     struct msi_domain_info *info,
 					     struct irq_domain *parent)
 {
@@ -1267,7 +1267,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		pci_msi_domain_update_chip_ops(info);
 
-	domain = msi_create_irq_domain(node, info, parent);
+	domain = msi_create_irq_domain(fwnode, info, parent);
 	if (!domain)
 		return NULL;
 
@@ -1303,14 +1303,14 @@ void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev)
 
 /**
  * pci_msi_create_default_irq_domain - Create a default MSI interrupt domain
- * @node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
  * Returns: A domain pointer or NULL in case of failure. If successful
  * the default PCI/MSI irqdomain pointer is updated.
  */
-struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode,
 		struct msi_domain_info *info, struct irq_domain *parent)
 {
 	struct irq_domain *domain;
@@ -1320,7 +1320,7 @@ struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
 		pr_err("PCI: default irq domain for PCI MSI has already been created.\n");
 		domain = NULL;
 	} else {
-		domain = pci_msi_create_irq_domain(node, info, parent);
+		domain = pci_msi_create_irq_domain(fwnode, info, parent);
 		pci_msi_default_domain = domain;
 	}
 	mutex_unlock(&pci_msi_domain_lock);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index ad939d0..32a24b9 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -174,6 +174,7 @@ struct msi_controller {
 struct irq_domain;
 struct irq_chip;
 struct device_node;
+struct fwnode_handle;
 struct msi_domain_info;
 
 /**
@@ -262,7 +263,7 @@ enum {
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
 			    bool force);
 
-struct irq_domain *msi_create_irq_domain(struct device_node *of_node,
+struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
 					 struct msi_domain_info *info,
 					 struct irq_domain *parent);
 int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
@@ -270,7 +271,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
 struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
 
-struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
 						  struct msi_domain_info *info,
 						  struct irq_domain *parent);
 int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
@@ -280,13 +281,13 @@ void platform_msi_domain_free_irqs(struct device *dev);
 
 #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
 void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg);
-struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
 					     struct msi_domain_info *info,
 					     struct irq_domain *parent);
 int pci_msi_domain_alloc_irqs(struct irq_domain *domain, struct pci_dev *dev,
 			      int nvec, int type);
 void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev);
-struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode,
 		 struct msi_domain_info *info, struct irq_domain *parent);
 
 irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 7e6512b..95354bb 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -239,11 +239,11 @@ static void msi_domain_update_chip_ops(struct msi_domain_info *info)
 
 /**
  * msi_create_irq_domain - Create a MSI interrupt domain
- * @of_node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  */
-struct irq_domain *msi_create_irq_domain(struct device_node *node,
+struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
 					 struct msi_domain_info *info,
 					 struct irq_domain *parent)
 {
@@ -252,8 +252,8 @@ struct irq_domain *msi_create_irq_domain(struct device_node *node,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		msi_domain_update_chip_ops(info);
 
-	return irq_domain_add_hierarchy(parent, 0, 0, node, &msi_domain_ops,
-					info);
+	return irq_domain_create_hierarchy(parent, 0, 0, fwnode,
+					   &msi_domain_ops, info);
 }
 
 /**
-- 
2.1.4

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

* [PATCH 16/16] irqdomain/msi: Use fwnode instead of of_node
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

As we continue to push of_node towards the outskirts of irq domains,
let's start tackling the case of msi_create_irq_domain and its little
friends.

This has limited impact in both PCI/MSI, platform MSI, and a few
drivers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/base/platform-msi.c                   |  6 +++---
 drivers/irqchip/irq-gic-v2m.c                 |  5 +++--
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |  3 ++-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |  3 ++-
 drivers/pci/host/pci-xgene-msi.c              |  2 +-
 drivers/pci/msi.c                             | 14 +++++++-------
 include/linux/msi.h                           |  9 +++++----
 kernel/irq/msi.c                              |  8 ++++----
 8 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 134483d..5df4575 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -152,7 +152,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
 
 /**
  * platform_msi_create_irq_domain - Create a platform MSI interrupt domain
- * @np:		Optional device-tree node of the interrupt controller
+ * @fwnode:		Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
@@ -162,7 +162,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
  * Returns:
  * A domain pointer or NULL in case of failure.
  */
-struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
 						  struct msi_domain_info *info,
 						  struct irq_domain *parent)
 {
@@ -173,7 +173,7 @@ struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		platform_msi_update_chip_ops(info);
 
-	domain = msi_create_irq_domain(np, info, parent);
+	domain = msi_create_irq_domain(fwnode, info, parent);
 	if (domain)
 		domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
 
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index b2b08dd..93bb843 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -286,9 +286,10 @@ static int __init gicv2m_init_one(struct device_node *node,
 
 	inner_domain->bus_token = DOMAIN_BUS_NEXUS;
 	inner_domain->parent = parent;
-	pci_domain = pci_msi_create_irq_domain(node, &gicv2m_msi_domain_info,
+	pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
+					       &gicv2m_msi_domain_info,
 					       inner_domain);
-	plat_domain = platform_msi_create_irq_domain(node,
+	plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
 						     &gicv2m_pmsi_domain_info,
 						     inner_domain);
 	if (!pci_domain || !plat_domain) {
diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index a7c8c9f..693c2f9 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -125,7 +125,8 @@ static int __init its_pci_msi_init(void)
 			continue;
 		}
 
-		if (!pci_msi_create_irq_domain(np, &its_pci_msi_domain_info,
+		if (!pci_msi_create_irq_domain(of_node_to_fwnode(np),
+					       &its_pci_msi_domain_info,
 					       parent)) {
 			pr_err("%s: unable to create PCI domain\n",
 			       np->full_name);
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
index a865505..960a816 100644
--- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
@@ -78,7 +78,8 @@ static int __init its_pmsi_init(void)
 			continue;
 		}
 
-		if (!platform_msi_create_irq_domain(np, &its_pmsi_domain_info,
+		if (!platform_msi_create_irq_domain(of_node_to_fwnode(np),
+						    &its_pmsi_domain_info,
 						    parent)) {
 			pr_err("%s: unable to create platform domain\n",
 			       np->full_name);
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
index e491681..a6456b5 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/host/pci-xgene-msi.c
@@ -256,7 +256,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
 	if (!msi->inner_domain)
 		return -ENOMEM;
 
-	msi->msi_domain = pci_msi_create_irq_domain(msi->node,
+	msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
 						    &xgene_msi_domain_info,
 						    msi->inner_domain);
 
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d449714..ddd59fe 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1246,8 +1246,8 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
 }
 
 /**
- * pci_msi_create_irq_domain - Creat a MSI interrupt domain
- * @node:	Optional device-tree node of the interrupt controller
+ * pci_msi_create_irq_domain - Create a MSI interrupt domain
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
@@ -1256,7 +1256,7 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
  * Returns:
  * A domain pointer or NULL in case of failure.
  */
-struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
 					     struct msi_domain_info *info,
 					     struct irq_domain *parent)
 {
@@ -1267,7 +1267,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		pci_msi_domain_update_chip_ops(info);
 
-	domain = msi_create_irq_domain(node, info, parent);
+	domain = msi_create_irq_domain(fwnode, info, parent);
 	if (!domain)
 		return NULL;
 
@@ -1303,14 +1303,14 @@ void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev)
 
 /**
  * pci_msi_create_default_irq_domain - Create a default MSI interrupt domain
- * @node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
  * Returns: A domain pointer or NULL in case of failure. If successful
  * the default PCI/MSI irqdomain pointer is updated.
  */
-struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode,
 		struct msi_domain_info *info, struct irq_domain *parent)
 {
 	struct irq_domain *domain;
@@ -1320,7 +1320,7 @@ struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
 		pr_err("PCI: default irq domain for PCI MSI has already been created.\n");
 		domain = NULL;
 	} else {
-		domain = pci_msi_create_irq_domain(node, info, parent);
+		domain = pci_msi_create_irq_domain(fwnode, info, parent);
 		pci_msi_default_domain = domain;
 	}
 	mutex_unlock(&pci_msi_domain_lock);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index ad939d0..32a24b9 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -174,6 +174,7 @@ struct msi_controller {
 struct irq_domain;
 struct irq_chip;
 struct device_node;
+struct fwnode_handle;
 struct msi_domain_info;
 
 /**
@@ -262,7 +263,7 @@ enum {
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
 			    bool force);
 
-struct irq_domain *msi_create_irq_domain(struct device_node *of_node,
+struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
 					 struct msi_domain_info *info,
 					 struct irq_domain *parent);
 int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
@@ -270,7 +271,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
 struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
 
-struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
 						  struct msi_domain_info *info,
 						  struct irq_domain *parent);
 int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
@@ -280,13 +281,13 @@ void platform_msi_domain_free_irqs(struct device *dev);
 
 #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
 void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg);
-struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
 					     struct msi_domain_info *info,
 					     struct irq_domain *parent);
 int pci_msi_domain_alloc_irqs(struct irq_domain *domain, struct pci_dev *dev,
 			      int nvec, int type);
 void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev);
-struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode,
 		 struct msi_domain_info *info, struct irq_domain *parent);
 
 irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 7e6512b..95354bb 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -239,11 +239,11 @@ static void msi_domain_update_chip_ops(struct msi_domain_info *info)
 
 /**
  * msi_create_irq_domain - Create a MSI interrupt domain
- * @of_node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  */
-struct irq_domain *msi_create_irq_domain(struct device_node *node,
+struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
 					 struct msi_domain_info *info,
 					 struct irq_domain *parent)
 {
@@ -252,8 +252,8 @@ struct irq_domain *msi_create_irq_domain(struct device_node *node,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		msi_domain_update_chip_ops(info);
 
-	return irq_domain_add_hierarchy(parent, 0, 0, node, &msi_domain_ops,
-					info);
+	return irq_domain_create_hierarchy(parent, 0, 0, fwnode,
+					   &msi_domain_ops, info);
 }
 
 /**
-- 
2.1.4


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

* [PATCH 16/16] irqdomain/msi: Use fwnode instead of of_node
@ 2015-10-06 17:36   ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-06 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

As we continue to push of_node towards the outskirts of irq domains,
let's start tackling the case of msi_create_irq_domain and its little
friends.

This has limited impact in both PCI/MSI, platform MSI, and a few
drivers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/base/platform-msi.c                   |  6 +++---
 drivers/irqchip/irq-gic-v2m.c                 |  5 +++--
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |  3 ++-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |  3 ++-
 drivers/pci/host/pci-xgene-msi.c              |  2 +-
 drivers/pci/msi.c                             | 14 +++++++-------
 include/linux/msi.h                           |  9 +++++----
 kernel/irq/msi.c                              |  8 ++++----
 8 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 134483d..5df4575 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -152,7 +152,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
 
 /**
  * platform_msi_create_irq_domain - Create a platform MSI interrupt domain
- * @np:		Optional device-tree node of the interrupt controller
+ * @fwnode:		Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
@@ -162,7 +162,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
  * Returns:
  * A domain pointer or NULL in case of failure.
  */
-struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
 						  struct msi_domain_info *info,
 						  struct irq_domain *parent)
 {
@@ -173,7 +173,7 @@ struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		platform_msi_update_chip_ops(info);
 
-	domain = msi_create_irq_domain(np, info, parent);
+	domain = msi_create_irq_domain(fwnode, info, parent);
 	if (domain)
 		domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
 
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index b2b08dd..93bb843 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -286,9 +286,10 @@ static int __init gicv2m_init_one(struct device_node *node,
 
 	inner_domain->bus_token = DOMAIN_BUS_NEXUS;
 	inner_domain->parent = parent;
-	pci_domain = pci_msi_create_irq_domain(node, &gicv2m_msi_domain_info,
+	pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
+					       &gicv2m_msi_domain_info,
 					       inner_domain);
-	plat_domain = platform_msi_create_irq_domain(node,
+	plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
 						     &gicv2m_pmsi_domain_info,
 						     inner_domain);
 	if (!pci_domain || !plat_domain) {
diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index a7c8c9f..693c2f9 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -125,7 +125,8 @@ static int __init its_pci_msi_init(void)
 			continue;
 		}
 
-		if (!pci_msi_create_irq_domain(np, &its_pci_msi_domain_info,
+		if (!pci_msi_create_irq_domain(of_node_to_fwnode(np),
+					       &its_pci_msi_domain_info,
 					       parent)) {
 			pr_err("%s: unable to create PCI domain\n",
 			       np->full_name);
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
index a865505..960a816 100644
--- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
@@ -78,7 +78,8 @@ static int __init its_pmsi_init(void)
 			continue;
 		}
 
-		if (!platform_msi_create_irq_domain(np, &its_pmsi_domain_info,
+		if (!platform_msi_create_irq_domain(of_node_to_fwnode(np),
+						    &its_pmsi_domain_info,
 						    parent)) {
 			pr_err("%s: unable to create platform domain\n",
 			       np->full_name);
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
index e491681..a6456b5 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/host/pci-xgene-msi.c
@@ -256,7 +256,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
 	if (!msi->inner_domain)
 		return -ENOMEM;
 
-	msi->msi_domain = pci_msi_create_irq_domain(msi->node,
+	msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
 						    &xgene_msi_domain_info,
 						    msi->inner_domain);
 
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d449714..ddd59fe 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1246,8 +1246,8 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
 }
 
 /**
- * pci_msi_create_irq_domain - Creat a MSI interrupt domain
- * @node:	Optional device-tree node of the interrupt controller
+ * pci_msi_create_irq_domain - Create a MSI interrupt domain
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
@@ -1256,7 +1256,7 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
  * Returns:
  * A domain pointer or NULL in case of failure.
  */
-struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
 					     struct msi_domain_info *info,
 					     struct irq_domain *parent)
 {
@@ -1267,7 +1267,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		pci_msi_domain_update_chip_ops(info);
 
-	domain = msi_create_irq_domain(node, info, parent);
+	domain = msi_create_irq_domain(fwnode, info, parent);
 	if (!domain)
 		return NULL;
 
@@ -1303,14 +1303,14 @@ void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev)
 
 /**
  * pci_msi_create_default_irq_domain - Create a default MSI interrupt domain
- * @node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  *
  * Returns: A domain pointer or NULL in case of failure. If successful
  * the default PCI/MSI irqdomain pointer is updated.
  */
-struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode,
 		struct msi_domain_info *info, struct irq_domain *parent)
 {
 	struct irq_domain *domain;
@@ -1320,7 +1320,7 @@ struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
 		pr_err("PCI: default irq domain for PCI MSI has already been created.\n");
 		domain = NULL;
 	} else {
-		domain = pci_msi_create_irq_domain(node, info, parent);
+		domain = pci_msi_create_irq_domain(fwnode, info, parent);
 		pci_msi_default_domain = domain;
 	}
 	mutex_unlock(&pci_msi_domain_lock);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index ad939d0..32a24b9 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -174,6 +174,7 @@ struct msi_controller {
 struct irq_domain;
 struct irq_chip;
 struct device_node;
+struct fwnode_handle;
 struct msi_domain_info;
 
 /**
@@ -262,7 +263,7 @@ enum {
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
 			    bool force);
 
-struct irq_domain *msi_create_irq_domain(struct device_node *of_node,
+struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
 					 struct msi_domain_info *info,
 					 struct irq_domain *parent);
 int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
@@ -270,7 +271,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
 struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
 
-struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
 						  struct msi_domain_info *info,
 						  struct irq_domain *parent);
 int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
@@ -280,13 +281,13 @@ void platform_msi_domain_free_irqs(struct device *dev);
 
 #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
 void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg);
-struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
 					     struct msi_domain_info *info,
 					     struct irq_domain *parent);
 int pci_msi_domain_alloc_irqs(struct irq_domain *domain, struct pci_dev *dev,
 			      int nvec, int type);
 void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev);
-struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode,
 		 struct msi_domain_info *info, struct irq_domain *parent);
 
 irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 7e6512b..95354bb 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -239,11 +239,11 @@ static void msi_domain_update_chip_ops(struct msi_domain_info *info)
 
 /**
  * msi_create_irq_domain - Create a MSI interrupt domain
- * @of_node:	Optional device-tree node of the interrupt controller
+ * @fwnode:	Optional fwnode of the interrupt controller
  * @info:	MSI domain info
  * @parent:	Parent irq domain
  */
-struct irq_domain *msi_create_irq_domain(struct device_node *node,
+struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
 					 struct msi_domain_info *info,
 					 struct irq_domain *parent)
 {
@@ -252,8 +252,8 @@ struct irq_domain *msi_create_irq_domain(struct device_node *node,
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		msi_domain_update_chip_ops(info);
 
-	return irq_domain_add_hierarchy(parent, 0, 0, node, &msi_domain_ops,
-					info);
+	return irq_domain_create_hierarchy(parent, 0, 0, fwnode,
+					   &msi_domain_ops, info);
 }
 
 /**
-- 
2.1.4

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

* Re: [PATCH 01/16] irqdomain: Use an accessor for the of_node field
  2015-10-06 17:36   ` Marc Zyngier
@ 2015-10-09 14:24     ` Thomas Gleixner
  -1 siblings, 0 replies; 87+ messages in thread
From: Thomas Gleixner @ 2015-10-09 14:24 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Jiang Liu, Jason Cooper, Rafael J. Wysocki, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On Tue, 6 Oct 2015, Marc Zyngier wrote:
> index d3ca792..f644fdb 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -161,6 +161,11 @@ enum {
>  	IRQ_DOMAIN_FLAG_NONCORE		= (1 << 16),
>  };
>  
> +static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
> +{
> +	return d->of_node;
> +}
> +

Can you please make that a seperate patch, which I can expedite to
Linus? That way we can fix stuff which shows up in next as well.

Thanks,

	tglx

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

* [PATCH 01/16] irqdomain: Use an accessor for the of_node field
@ 2015-10-09 14:24     ` Thomas Gleixner
  0 siblings, 0 replies; 87+ messages in thread
From: Thomas Gleixner @ 2015-10-09 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 6 Oct 2015, Marc Zyngier wrote:
> index d3ca792..f644fdb 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -161,6 +161,11 @@ enum {
>  	IRQ_DOMAIN_FLAG_NONCORE		= (1 << 16),
>  };
>  
> +static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
> +{
> +	return d->of_node;
> +}
> +

Can you please make that a seperate patch, which I can expedite to
Linus? That way we can fix stuff which shows up in next as well.

Thanks,

	tglx

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

* Re: [PATCH 01/16] irqdomain: Use an accessor for the of_node field
  2015-10-09 14:24     ` Thomas Gleixner
@ 2015-10-09 14:31       ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-09 14:31 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jiang Liu, Jason Cooper, Rafael J. Wysocki, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On 09/10/15 15:24, Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>> index d3ca792..f644fdb 100644
>> --- a/include/linux/irqdomain.h
>> +++ b/include/linux/irqdomain.h
>> @@ -161,6 +161,11 @@ enum {
>>  	IRQ_DOMAIN_FLAG_NONCORE		= (1 << 16),
>>  };
>>  
>> +static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
>> +{
>> +	return d->of_node;
>> +}
>> +
> 
> Can you please make that a seperate patch, which I can expedite to
> Linus? That way we can fix stuff which shows up in next as well.

Just this one hunk? Sure. Coming up!

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH 01/16] irqdomain: Use an accessor for the of_node field
@ 2015-10-09 14:31       ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-09 14:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/10/15 15:24, Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>> index d3ca792..f644fdb 100644
>> --- a/include/linux/irqdomain.h
>> +++ b/include/linux/irqdomain.h
>> @@ -161,6 +161,11 @@ enum {
>>  	IRQ_DOMAIN_FLAG_NONCORE		= (1 << 16),
>>  };
>>  
>> +static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
>> +{
>> +	return d->of_node;
>> +}
>> +
> 
> Can you please make that a seperate patch, which I can expedite to
> Linus? That way we can fix stuff which shows up in next as well.

Just this one hunk? Sure. Coming up!

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 00/16] Divorcing irqdomain and device_node
  2015-10-06 17:36 ` Marc Zyngier
@ 2015-10-11 21:01   ` Thomas Gleixner
  -1 siblings, 0 replies; 87+ messages in thread
From: Thomas Gleixner @ 2015-10-11 21:01 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Jiang Liu, Jason Cooper, Rafael J. Wysocki, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On Tue, 6 Oct 2015, Marc Zyngier wrote:
> [This patch series used to be called "Making the generic ACPI GSI
> layer irqdomain aware", but as I've radically changed my approach to
> this problem, I've decided to reset the counters...]
> 
> The irqdomain code is not entierely ACPI friendly, as it has some
> built-in knowledge of the device-tree. Nothing too harmful, but enough
> to scare the ARM ACPI developpers which end up with their own version
> of the square wheel. And some of the ramifications actually run deeper
> than initially expected.
> 
> This series adapts the irqdomain code to use 'struct fwnode_handle'
> instead of 'struct device_node' as the identifier for a domain
> (compatibility interfaces are of course added). It also introduces a
> generic IRQ specifier that firmware interfaces (DT or ACPI) can
> directly use to configure interrupts, and allow the ACPI GSI code to
> be plugged into this.
> 
> As examples, we convert the ARM GIC ACPI support to use irqdomains as
> originally intended, and rework the MSI code to also move away from
> using device nodes when using irqdomains.
> 
> Overall, this gives us a way to use irqdomains on both DT and ACPI
> enabled platforms, having very little changes made to the actual
> drivers (other than the probing infrastructure). Because we keep the
> flow of information between the various layers identical between ACPI
> and DT, we immediately benefit from the existing infrastructure.
> 
> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
> 
> Marc Zyngier (16):
>   irqdomain: Use an accessor for the of_node field
>   irqdomain: Convert irqdomain->of_node to fwnode
>   irqdomain: Allow irq domain lookup by fwnode
>   irqdomain: Introduce a firmware-specific IRQ specifier structure
>   irqchip: Convert all alloc/xlate users from of_node to fwnode
>   irqdomain: Introduce irq_create_fwspec_mapping
>   irqdomain: Introduce irq_domain_create_{linear,tree}
>   irqdomain: Add a fwnode_handle allocator
>   acpi/gsi: Always perform an irq domain lookup
>   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>   irqchip/gic: Get rid of gic_init_bases()
>   irqchip/gic: Switch ACPI support to stacked domains
>   irqchip/gic: Kill the xlate method
>   acpi/gsi: Cleanup acpi_register_gsi
>   irqdomain: Introduce irq_domain_create_hierarchy
>   irqdomain/msi: Use fwnode instead of of_node

I really like this one way better than the previous attempts and I
couldn't find any real issue when going through them with a fine comb.

I'd like to get that into 4.4, so I have to ask for the opinion of
ACPI folks. Having an ack on those patches would be nice.

Thanks,

	tglx

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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-11 21:01   ` Thomas Gleixner
  0 siblings, 0 replies; 87+ messages in thread
From: Thomas Gleixner @ 2015-10-11 21:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 6 Oct 2015, Marc Zyngier wrote:
> [This patch series used to be called "Making the generic ACPI GSI
> layer irqdomain aware", but as I've radically changed my approach to
> this problem, I've decided to reset the counters...]
> 
> The irqdomain code is not entierely ACPI friendly, as it has some
> built-in knowledge of the device-tree. Nothing too harmful, but enough
> to scare the ARM ACPI developpers which end up with their own version
> of the square wheel. And some of the ramifications actually run deeper
> than initially expected.
> 
> This series adapts the irqdomain code to use 'struct fwnode_handle'
> instead of 'struct device_node' as the identifier for a domain
> (compatibility interfaces are of course added). It also introduces a
> generic IRQ specifier that firmware interfaces (DT or ACPI) can
> directly use to configure interrupts, and allow the ACPI GSI code to
> be plugged into this.
> 
> As examples, we convert the ARM GIC ACPI support to use irqdomains as
> originally intended, and rework the MSI code to also move away from
> using device nodes when using irqdomains.
> 
> Overall, this gives us a way to use irqdomains on both DT and ACPI
> enabled platforms, having very little changes made to the actual
> drivers (other than the probing infrastructure). Because we keep the
> flow of information between the various layers identical between ACPI
> and DT, we immediately benefit from the existing infrastructure.
> 
> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
> 
> Marc Zyngier (16):
>   irqdomain: Use an accessor for the of_node field
>   irqdomain: Convert irqdomain->of_node to fwnode
>   irqdomain: Allow irq domain lookup by fwnode
>   irqdomain: Introduce a firmware-specific IRQ specifier structure
>   irqchip: Convert all alloc/xlate users from of_node to fwnode
>   irqdomain: Introduce irq_create_fwspec_mapping
>   irqdomain: Introduce irq_domain_create_{linear,tree}
>   irqdomain: Add a fwnode_handle allocator
>   acpi/gsi: Always perform an irq domain lookup
>   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>   irqchip/gic: Get rid of gic_init_bases()
>   irqchip/gic: Switch ACPI support to stacked domains
>   irqchip/gic: Kill the xlate method
>   acpi/gsi: Cleanup acpi_register_gsi
>   irqdomain: Introduce irq_domain_create_hierarchy
>   irqdomain/msi: Use fwnode instead of of_node

I really like this one way better than the previous attempts and I
couldn't find any real issue when going through them with a fine comb.

I'd like to get that into 4.4, so I have to ask for the opinion of
ACPI folks. Having an ack on those patches would be nice.

Thanks,

	tglx

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

* Re: [PATCH 00/16] Divorcing irqdomain and device_node
  2015-10-11 21:01   ` Thomas Gleixner
@ 2015-10-12  2:40     ` Hanjun Guo
  -1 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  2:40 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: Jiang Liu, Jason Cooper, Rafael J. Wysocki, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Suravee Suthikulpanit, Graeme Gregory,
	Jake Oshins

On 10/12/2015 05:01 AM, Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>> [This patch series used to be called "Making the generic ACPI GSI
>> layer irqdomain aware", but as I've radically changed my approach to
>> this problem, I've decided to reset the counters...]
>>
>> The irqdomain code is not entierely ACPI friendly, as it has some
>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>> to scare the ARM ACPI developpers which end up with their own version
>> of the square wheel. And some of the ramifications actually run deeper
>> than initially expected.
>>
>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>> instead of 'struct device_node' as the identifier for a domain
>> (compatibility interfaces are of course added). It also introduces a
>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>> directly use to configure interrupts, and allow the ACPI GSI code to
>> be plugged into this.
>>
>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>> originally intended, and rework the MSI code to also move away from
>> using device nodes when using irqdomains.
>>
>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>> enabled platforms, having very little changes made to the actual
>> drivers (other than the probing infrastructure). Because we keep the
>> flow of information between the various layers identical between ACPI
>> and DT, we immediately benefit from the existing infrastructure.
>>
>> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
>>
>> Marc Zyngier (16):
>>    irqdomain: Use an accessor for the of_node field
>>    irqdomain: Convert irqdomain->of_node to fwnode
>>    irqdomain: Allow irq domain lookup by fwnode
>>    irqdomain: Introduce a firmware-specific IRQ specifier structure
>>    irqchip: Convert all alloc/xlate users from of_node to fwnode
>>    irqdomain: Introduce irq_create_fwspec_mapping
>>    irqdomain: Introduce irq_domain_create_{linear,tree}
>>    irqdomain: Add a fwnode_handle allocator
>>    acpi/gsi: Always perform an irq domain lookup
>>    acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>    irqchip/gic: Get rid of gic_init_bases()
>>    irqchip/gic: Switch ACPI support to stacked domains
>>    irqchip/gic: Kill the xlate method
>>    acpi/gsi: Cleanup acpi_register_gsi
>>    irqdomain: Introduce irq_domain_create_hierarchy
>>    irqdomain/msi: Use fwnode instead of of_node
>
> I really like this one way better than the previous attempts and I
> couldn't find any real issue when going through them with a fine comb.

Fully agree, this version removes the dependency on DT for ACPI.

>
> I'd like to get that into 4.4, so I have to ask for the opinion of
> ACPI folks. Having an ack on those patches would be nice.

I'm reviewing this patch set, and will have a test today.

Thanks
Hanjun

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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-12  2:40     ` Hanjun Guo
  0 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  2:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/12/2015 05:01 AM, Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>> [This patch series used to be called "Making the generic ACPI GSI
>> layer irqdomain aware", but as I've radically changed my approach to
>> this problem, I've decided to reset the counters...]
>>
>> The irqdomain code is not entierely ACPI friendly, as it has some
>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>> to scare the ARM ACPI developpers which end up with their own version
>> of the square wheel. And some of the ramifications actually run deeper
>> than initially expected.
>>
>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>> instead of 'struct device_node' as the identifier for a domain
>> (compatibility interfaces are of course added). It also introduces a
>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>> directly use to configure interrupts, and allow the ACPI GSI code to
>> be plugged into this.
>>
>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>> originally intended, and rework the MSI code to also move away from
>> using device nodes when using irqdomains.
>>
>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>> enabled platforms, having very little changes made to the actual
>> drivers (other than the probing infrastructure). Because we keep the
>> flow of information between the various layers identical between ACPI
>> and DT, we immediately benefit from the existing infrastructure.
>>
>> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
>>
>> Marc Zyngier (16):
>>    irqdomain: Use an accessor for the of_node field
>>    irqdomain: Convert irqdomain->of_node to fwnode
>>    irqdomain: Allow irq domain lookup by fwnode
>>    irqdomain: Introduce a firmware-specific IRQ specifier structure
>>    irqchip: Convert all alloc/xlate users from of_node to fwnode
>>    irqdomain: Introduce irq_create_fwspec_mapping
>>    irqdomain: Introduce irq_domain_create_{linear,tree}
>>    irqdomain: Add a fwnode_handle allocator
>>    acpi/gsi: Always perform an irq domain lookup
>>    acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>    irqchip/gic: Get rid of gic_init_bases()
>>    irqchip/gic: Switch ACPI support to stacked domains
>>    irqchip/gic: Kill the xlate method
>>    acpi/gsi: Cleanup acpi_register_gsi
>>    irqdomain: Introduce irq_domain_create_hierarchy
>>    irqdomain/msi: Use fwnode instead of of_node
>
> I really like this one way better than the previous attempts and I
> couldn't find any real issue when going through them with a fine comb.

Fully agree, this version removes the dependency on DT for ACPI.

>
> I'd like to get that into 4.4, so I have to ask for the opinion of
> ACPI folks. Having an ack on those patches would be nice.

I'm reviewing this patch set, and will have a test today.

Thanks
Hanjun

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

* Re: [PATCH 01/16] irqdomain: Use an accessor for the of_node field
  2015-10-06 17:36   ` Marc Zyngier
@ 2015-10-12  6:04     ` Hanjun Guo
  -1 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  6:04 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper,
	Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Suravee Suthikulpanit, Graeme Gregory,
	Jake Oshins

On 10/07/2015 01:36 AM, Marc Zyngier wrote:
> The struct irq_domain contains a "struct device_node *" field
> (of_node) that is almost the only link between the irqdomain
> and the device tree infrastructure.
>
> In order to prepare for the removal of that field, convert all
> users to use an accessor.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   arch/arm/mach-omap2/omap-wakeupgen.c          |  2 +-
>   arch/c6x/platforms/megamod-pic.c              |  2 +-
>   arch/mips/cavium-octeon/octeon-irq.c          |  4 ++--
>   arch/powerpc/platforms/cell/axon_msi.c        |  2 +-
>   arch/powerpc/platforms/cell/spider-pic.c      |  9 +++++---
>   arch/powerpc/platforms/pasemi/msi.c           |  6 ++++--
>   arch/powerpc/platforms/powernv/opal-irqchip.c |  2 +-
>   arch/powerpc/sysdev/ehv_pic.c                 |  3 ++-
>   arch/powerpc/sysdev/fsl_msi.c                 |  2 +-
>   arch/powerpc/sysdev/i8259.c                   |  3 ++-
>   arch/powerpc/sysdev/ipic.c                    |  3 ++-
>   arch/powerpc/sysdev/mpic.c                    |  3 ++-
>   arch/powerpc/sysdev/mpic_msi.c                |  2 +-
>   arch/powerpc/sysdev/qe_lib/qe_ic.c            |  3 ++-
>   drivers/gpio/gpio-sodaville.c                 |  2 +-
>   drivers/irqchip/exynos-combiner.c             |  2 +-
>   drivers/irqchip/irq-atmel-aic-common.c        |  2 +-
>   drivers/irqchip/irq-crossbar.c                |  4 ++--
>   drivers/irqchip/irq-gic-v2m.c                 |  2 +-
>   drivers/irqchip/irq-gic-v3-its.c              |  2 +-
>   drivers/irqchip/irq-gic-v3.c                  |  2 +-
>   drivers/irqchip/irq-gic.c                     |  2 +-
>   drivers/irqchip/irq-hip04.c                   |  2 +-
>   drivers/irqchip/irq-imx-gpcv2.c               |  2 +-
>   drivers/irqchip/irq-mtk-sysirq.c              |  2 +-
>   drivers/irqchip/irq-s3c24xx.c                 |  4 ++--
>   drivers/irqchip/irq-tegra.c                   |  4 ++--
>   drivers/irqchip/irq-vf610-mscm-ir.c           |  5 +++--
>   drivers/spmi/spmi-pmic-arb.c                  |  2 +-
>   include/linux/irqdomain.h                     |  5 +++++
>   kernel/irq/irqdomain.c                        | 30 +++++++++++++++++++--------
>   31 files changed, 74 insertions(+), 46 deletions(-)

Some missing files I noticed:
./arch/arm/mach-imx/gpc.c:	if (domain->of_node != controller)
./arch/arm/mach-imx/gpc.c:	parent_args.np = domain->parent->of_node;
./arch/arm/mach-exynos/suspend.c:	if (domain->of_node != controller)
./arch/arm/mach-exynos/suspend.c:	parent_args.np = domain->parent->of_node;

Thanks
Hanjun

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

* [PATCH 01/16] irqdomain: Use an accessor for the of_node field
@ 2015-10-12  6:04     ` Hanjun Guo
  0 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  6:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/07/2015 01:36 AM, Marc Zyngier wrote:
> The struct irq_domain contains a "struct device_node *" field
> (of_node) that is almost the only link between the irqdomain
> and the device tree infrastructure.
>
> In order to prepare for the removal of that field, convert all
> users to use an accessor.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   arch/arm/mach-omap2/omap-wakeupgen.c          |  2 +-
>   arch/c6x/platforms/megamod-pic.c              |  2 +-
>   arch/mips/cavium-octeon/octeon-irq.c          |  4 ++--
>   arch/powerpc/platforms/cell/axon_msi.c        |  2 +-
>   arch/powerpc/platforms/cell/spider-pic.c      |  9 +++++---
>   arch/powerpc/platforms/pasemi/msi.c           |  6 ++++--
>   arch/powerpc/platforms/powernv/opal-irqchip.c |  2 +-
>   arch/powerpc/sysdev/ehv_pic.c                 |  3 ++-
>   arch/powerpc/sysdev/fsl_msi.c                 |  2 +-
>   arch/powerpc/sysdev/i8259.c                   |  3 ++-
>   arch/powerpc/sysdev/ipic.c                    |  3 ++-
>   arch/powerpc/sysdev/mpic.c                    |  3 ++-
>   arch/powerpc/sysdev/mpic_msi.c                |  2 +-
>   arch/powerpc/sysdev/qe_lib/qe_ic.c            |  3 ++-
>   drivers/gpio/gpio-sodaville.c                 |  2 +-
>   drivers/irqchip/exynos-combiner.c             |  2 +-
>   drivers/irqchip/irq-atmel-aic-common.c        |  2 +-
>   drivers/irqchip/irq-crossbar.c                |  4 ++--
>   drivers/irqchip/irq-gic-v2m.c                 |  2 +-
>   drivers/irqchip/irq-gic-v3-its.c              |  2 +-
>   drivers/irqchip/irq-gic-v3.c                  |  2 +-
>   drivers/irqchip/irq-gic.c                     |  2 +-
>   drivers/irqchip/irq-hip04.c                   |  2 +-
>   drivers/irqchip/irq-imx-gpcv2.c               |  2 +-
>   drivers/irqchip/irq-mtk-sysirq.c              |  2 +-
>   drivers/irqchip/irq-s3c24xx.c                 |  4 ++--
>   drivers/irqchip/irq-tegra.c                   |  4 ++--
>   drivers/irqchip/irq-vf610-mscm-ir.c           |  5 +++--
>   drivers/spmi/spmi-pmic-arb.c                  |  2 +-
>   include/linux/irqdomain.h                     |  5 +++++
>   kernel/irq/irqdomain.c                        | 30 +++++++++++++++++++--------
>   31 files changed, 74 insertions(+), 46 deletions(-)

Some missing files I noticed:
./arch/arm/mach-imx/gpc.c:	if (domain->of_node != controller)
./arch/arm/mach-imx/gpc.c:	parent_args.np = domain->parent->of_node;
./arch/arm/mach-exynos/suspend.c:	if (domain->of_node != controller)
./arch/arm/mach-exynos/suspend.c:	parent_args.np = domain->parent->of_node;

Thanks
Hanjun

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

* Re: [PATCH 05/16] irqchip: Convert all alloc/xlate users from of_node to fwnode
  2015-10-06 17:36   ` Marc Zyngier
@ 2015-10-12  6:44     ` Hanjun Guo
  -1 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  6:44 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper,
	Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Suravee Suthikulpanit, Graeme Gregory,
	Jake Oshins

On 10/07/2015 01:36 AM, Marc Zyngier wrote:
> Since we now have a generic data structure to express an
> interrupt specifier, convert all hierarchical irqchips that
> are OF based to use a fwnode_handle as part of their alloc
> and xlate (which becomes translate) callbacks.
>
> As most of these drivers have dependencies (they exchange IRQ
> specifiers), change them all in a single, massive patch...
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   arch/arm/mach-exynos/suspend.c       | 55 ++++++++++++++++---------------
>   arch/arm/mach-imx/gpc.c              | 55 ++++++++++++++++---------------
>   arch/arm/mach-omap2/omap-wakeupgen.c | 55 ++++++++++++++++---------------
>   drivers/irqchip/irq-crossbar.c       | 62 ++++++++++++++++++----------------
>   drivers/irqchip/irq-gic-v2m.c        | 18 ++++++----
>   drivers/irqchip/irq-gic-v3-its.c     | 20 ++++++-----
>   drivers/irqchip/irq-gic-v3.c         | 49 +++++++++++++--------------
>   drivers/irqchip/irq-gic.c            | 33 ++++++++++++++++---
>   drivers/irqchip/irq-imx-gpcv2.c      | 64 ++++++++++++++++--------------------
>   drivers/irqchip/irq-mtk-sysirq.c     | 49 ++++++++++++++-------------
>   drivers/irqchip/irq-nvic.c           | 18 +++++++---
>   drivers/irqchip/irq-tegra.c          | 55 ++++++++++++++++---------------
>   drivers/irqchip/irq-vf610-mscm-ir.c  | 42 +++++++++++++++--------
>   13 files changed, 323 insertions(+), 252 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
> index e00eb39..5a7e47c 100644
> --- a/arch/arm/mach-exynos/suspend.c
> +++ b/arch/arm/mach-exynos/suspend.c
> @@ -177,54 +177,57 @@ static struct irq_chip exynos_pmu_chip = {
>   #endif
>   };
>
> -static int exynos_pmu_domain_xlate(struct irq_domain *domain,
> -				   struct device_node *controller,
> -				   const u32 *intspec,
> -				   unsigned int intsize,
> -				   unsigned long *out_hwirq,
> -				   unsigned int *out_type)
> +static int exynos_pmu_domain_translate(struct irq_domain *d,
> +				       struct irq_fwspec *fwspec,
> +				       unsigned long *hwirq,
> +				       unsigned int *type)
>   {
> -	if (domain->of_node != controller)
> -		return -EINVAL;	/* Shouldn't happen, really... */
> -	if (intsize != 3)
> -		return -EINVAL;	/* Not GIC compliant */
> -	if (intspec[0] != 0)
> -		return -EINVAL;	/* No PPI should point to this domain */
> +	if (is_of_node(fwspec->fwnode)) {
> +		if (fwspec->param_count != 3)
> +			return -EINVAL;
>
> -	*out_hwirq = intspec[1];
> -	*out_type = intspec[2];
> -	return 0;
> +		/* No PPI should point to this domain */
> +		if (fwspec->param[0] != 0)
> +			return -EINVAL;
> +
> +		*hwirq = fwspec->param[1];
> +		*type = fwspec->param[2];
> +		return 0;
> +	}
> +
> +	return -EINVAL;
>   }
>
>   static int exynos_pmu_domain_alloc(struct irq_domain *domain,
>   				   unsigned int virq,
>   				   unsigned int nr_irqs, void *data)
>   {
> -	struct of_phandle_args *args = data;
> -	struct of_phandle_args parent_args;
> +	struct irq_fwspec *fwspec = data;
> +	struct irq_fwspec parent_fwspec;
>   	irq_hw_number_t hwirq;
>   	int i;
>
> -	if (args->args_count != 3)
> +	if (fwspec->param_count != 3)
>   		return -EINVAL;	/* Not GIC compliant */
> -	if (args->args[0] != 0)
> +	if (fwspec->param[0] != 0)
>   		return -EINVAL;	/* No PPI should point to this domain */
>
> -	hwirq = args->args[1];
> +	hwirq = fwspec->param[1];
>
>   	for (i = 0; i < nr_irqs; i++)
>   		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
>   					      &exynos_pmu_chip, NULL);
>
> -	parent_args = *args;
> -	parent_args.np = domain->parent->of_node;

Hmm, here removes the of_node, but I think we still
need to convert it in the first patch, or will break
the git bisect.

Thanks
Hanjun

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

* [PATCH 05/16] irqchip: Convert all alloc/xlate users from of_node to fwnode
@ 2015-10-12  6:44     ` Hanjun Guo
  0 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  6:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/07/2015 01:36 AM, Marc Zyngier wrote:
> Since we now have a generic data structure to express an
> interrupt specifier, convert all hierarchical irqchips that
> are OF based to use a fwnode_handle as part of their alloc
> and xlate (which becomes translate) callbacks.
>
> As most of these drivers have dependencies (they exchange IRQ
> specifiers), change them all in a single, massive patch...
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   arch/arm/mach-exynos/suspend.c       | 55 ++++++++++++++++---------------
>   arch/arm/mach-imx/gpc.c              | 55 ++++++++++++++++---------------
>   arch/arm/mach-omap2/omap-wakeupgen.c | 55 ++++++++++++++++---------------
>   drivers/irqchip/irq-crossbar.c       | 62 ++++++++++++++++++----------------
>   drivers/irqchip/irq-gic-v2m.c        | 18 ++++++----
>   drivers/irqchip/irq-gic-v3-its.c     | 20 ++++++-----
>   drivers/irqchip/irq-gic-v3.c         | 49 +++++++++++++--------------
>   drivers/irqchip/irq-gic.c            | 33 ++++++++++++++++---
>   drivers/irqchip/irq-imx-gpcv2.c      | 64 ++++++++++++++++--------------------
>   drivers/irqchip/irq-mtk-sysirq.c     | 49 ++++++++++++++-------------
>   drivers/irqchip/irq-nvic.c           | 18 +++++++---
>   drivers/irqchip/irq-tegra.c          | 55 ++++++++++++++++---------------
>   drivers/irqchip/irq-vf610-mscm-ir.c  | 42 +++++++++++++++--------
>   13 files changed, 323 insertions(+), 252 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
> index e00eb39..5a7e47c 100644
> --- a/arch/arm/mach-exynos/suspend.c
> +++ b/arch/arm/mach-exynos/suspend.c
> @@ -177,54 +177,57 @@ static struct irq_chip exynos_pmu_chip = {
>   #endif
>   };
>
> -static int exynos_pmu_domain_xlate(struct irq_domain *domain,
> -				   struct device_node *controller,
> -				   const u32 *intspec,
> -				   unsigned int intsize,
> -				   unsigned long *out_hwirq,
> -				   unsigned int *out_type)
> +static int exynos_pmu_domain_translate(struct irq_domain *d,
> +				       struct irq_fwspec *fwspec,
> +				       unsigned long *hwirq,
> +				       unsigned int *type)
>   {
> -	if (domain->of_node != controller)
> -		return -EINVAL;	/* Shouldn't happen, really... */
> -	if (intsize != 3)
> -		return -EINVAL;	/* Not GIC compliant */
> -	if (intspec[0] != 0)
> -		return -EINVAL;	/* No PPI should point to this domain */
> +	if (is_of_node(fwspec->fwnode)) {
> +		if (fwspec->param_count != 3)
> +			return -EINVAL;
>
> -	*out_hwirq = intspec[1];
> -	*out_type = intspec[2];
> -	return 0;
> +		/* No PPI should point to this domain */
> +		if (fwspec->param[0] != 0)
> +			return -EINVAL;
> +
> +		*hwirq = fwspec->param[1];
> +		*type = fwspec->param[2];
> +		return 0;
> +	}
> +
> +	return -EINVAL;
>   }
>
>   static int exynos_pmu_domain_alloc(struct irq_domain *domain,
>   				   unsigned int virq,
>   				   unsigned int nr_irqs, void *data)
>   {
> -	struct of_phandle_args *args = data;
> -	struct of_phandle_args parent_args;
> +	struct irq_fwspec *fwspec = data;
> +	struct irq_fwspec parent_fwspec;
>   	irq_hw_number_t hwirq;
>   	int i;
>
> -	if (args->args_count != 3)
> +	if (fwspec->param_count != 3)
>   		return -EINVAL;	/* Not GIC compliant */
> -	if (args->args[0] != 0)
> +	if (fwspec->param[0] != 0)
>   		return -EINVAL;	/* No PPI should point to this domain */
>
> -	hwirq = args->args[1];
> +	hwirq = fwspec->param[1];
>
>   	for (i = 0; i < nr_irqs; i++)
>   		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
>   					      &exynos_pmu_chip, NULL);
>
> -	parent_args = *args;
> -	parent_args.np = domain->parent->of_node;

Hmm, here removes the of_node, but I think we still
need to convert it in the first patch, or will break
the git bisect.

Thanks
Hanjun

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

* Re: [PATCH 00/16] Divorcing irqdomain and device_node
  2015-10-12  2:40     ` Hanjun Guo
@ 2015-10-12  7:09       ` Hanjun Guo
  -1 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  7:09 UTC (permalink / raw)
  To: Thomas Gleixner, Marc Zyngier
  Cc: Jiang Liu, Jason Cooper, Rafael J. Wysocki, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Suravee Suthikulpanit, Graeme Gregory,
	Jake Oshins

On 10/12/2015 10:40 AM, Hanjun Guo wrote:
> On 10/12/2015 05:01 AM, Thomas Gleixner wrote:
>> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>>> [This patch series used to be called "Making the generic ACPI GSI
>>> layer irqdomain aware", but as I've radically changed my approach to
>>> this problem, I've decided to reset the counters...]
>>>
>>> The irqdomain code is not entierely ACPI friendly, as it has some
>>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>>> to scare the ARM ACPI developpers which end up with their own version
>>> of the square wheel. And some of the ramifications actually run deeper
>>> than initially expected.
>>>
>>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>>> instead of 'struct device_node' as the identifier for a domain
>>> (compatibility interfaces are of course added). It also introduces a
>>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>>> directly use to configure interrupts, and allow the ACPI GSI code to
>>> be plugged into this.
>>>
>>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>>> originally intended, and rework the MSI code to also move away from
>>> using device nodes when using irqdomains.
>>>
>>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>>> enabled platforms, having very little changes made to the actual
>>> drivers (other than the probing infrastructure). Because we keep the
>>> flow of information between the various layers identical between ACPI
>>> and DT, we immediately benefit from the existing infrastructure.
>>>
>>> This has been test-booted on Juno, is based on 4.3-rc4, and available
>>> at:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
>>> irq/irq-domain-fwnode-v1

I pulled, and I found that there is v2 :)

>>>
>>> Marc Zyngier (16):
>>>    irqdomain: Use an accessor for the of_node field
>>>    irqdomain: Convert irqdomain->of_node to fwnode
>>>    irqdomain: Allow irq domain lookup by fwnode
>>>    irqdomain: Introduce a firmware-specific IRQ specifier structure
>>>    irqchip: Convert all alloc/xlate users from of_node to fwnode
>>>    irqdomain: Introduce irq_create_fwspec_mapping
>>>    irqdomain: Introduce irq_domain_create_{linear,tree}
>>>    irqdomain: Add a fwnode_handle allocator
>>>    acpi/gsi: Always perform an irq domain lookup
>>>    acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>>    irqchip/gic: Get rid of gic_init_bases()
>>>    irqchip/gic: Switch ACPI support to stacked domains
>>>    irqchip/gic: Kill the xlate method
>>>    acpi/gsi: Cleanup acpi_register_gsi
>>>    irqdomain: Introduce irq_domain_create_hierarchy
>>>    irqdomain/msi: Use fwnode instead of of_node
>>
>> I really like this one way better than the previous attempts and I
>> couldn't find any real issue when going through them with a fine comb.
>
> Fully agree, this version removes the dependency on DT for ACPI.
>
>>
>> I'd like to get that into 4.4, so I have to ask for the opinion of
>> ACPI folks. Having an ack on those patches would be nice.
>
> I'm reviewing this patch set, and will have a test today.

I'm pretty fine with this patch set (except some comments for patch 1),
I will wait for your v2 to be sent out, then add reviews and acks.

Thanks
Hanjun

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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-12  7:09       ` Hanjun Guo
  0 siblings, 0 replies; 87+ messages in thread
From: Hanjun Guo @ 2015-10-12  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/12/2015 10:40 AM, Hanjun Guo wrote:
> On 10/12/2015 05:01 AM, Thomas Gleixner wrote:
>> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>>> [This patch series used to be called "Making the generic ACPI GSI
>>> layer irqdomain aware", but as I've radically changed my approach to
>>> this problem, I've decided to reset the counters...]
>>>
>>> The irqdomain code is not entierely ACPI friendly, as it has some
>>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>>> to scare the ARM ACPI developpers which end up with their own version
>>> of the square wheel. And some of the ramifications actually run deeper
>>> than initially expected.
>>>
>>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>>> instead of 'struct device_node' as the identifier for a domain
>>> (compatibility interfaces are of course added). It also introduces a
>>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>>> directly use to configure interrupts, and allow the ACPI GSI code to
>>> be plugged into this.
>>>
>>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>>> originally intended, and rework the MSI code to also move away from
>>> using device nodes when using irqdomains.
>>>
>>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>>> enabled platforms, having very little changes made to the actual
>>> drivers (other than the probing infrastructure). Because we keep the
>>> flow of information between the various layers identical between ACPI
>>> and DT, we immediately benefit from the existing infrastructure.
>>>
>>> This has been test-booted on Juno, is based on 4.3-rc4, and available
>>> at:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
>>> irq/irq-domain-fwnode-v1

I pulled, and I found that there is v2 :)

>>>
>>> Marc Zyngier (16):
>>>    irqdomain: Use an accessor for the of_node field
>>>    irqdomain: Convert irqdomain->of_node to fwnode
>>>    irqdomain: Allow irq domain lookup by fwnode
>>>    irqdomain: Introduce a firmware-specific IRQ specifier structure
>>>    irqchip: Convert all alloc/xlate users from of_node to fwnode
>>>    irqdomain: Introduce irq_create_fwspec_mapping
>>>    irqdomain: Introduce irq_domain_create_{linear,tree}
>>>    irqdomain: Add a fwnode_handle allocator
>>>    acpi/gsi: Always perform an irq domain lookup
>>>    acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>>    irqchip/gic: Get rid of gic_init_bases()
>>>    irqchip/gic: Switch ACPI support to stacked domains
>>>    irqchip/gic: Kill the xlate method
>>>    acpi/gsi: Cleanup acpi_register_gsi
>>>    irqdomain: Introduce irq_domain_create_hierarchy
>>>    irqdomain/msi: Use fwnode instead of of_node
>>
>> I really like this one way better than the previous attempts and I
>> couldn't find any real issue when going through them with a fine comb.
>
> Fully agree, this version removes the dependency on DT for ACPI.
>
>>
>> I'd like to get that into 4.4, so I have to ask for the opinion of
>> ACPI folks. Having an ack on those patches would be nice.
>
> I'm reviewing this patch set, and will have a test today.

I'm pretty fine with this patch set (except some comments for patch 1),
I will wait for your v2 to be sent out, then add reviews and acks.

Thanks
Hanjun

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

* Re: [PATCH 01/16] irqdomain: Use an accessor for the of_node field
  2015-10-12  6:04     ` Hanjun Guo
@ 2015-10-12  9:30       ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-12  9:30 UTC (permalink / raw)
  To: Hanjun Guo, Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Suravee Suthikulpanit, Graeme Gregory,
	Jake Oshins

On 12/10/15 07:04, Hanjun Guo wrote:
> On 10/07/2015 01:36 AM, Marc Zyngier wrote:
>> The struct irq_domain contains a "struct device_node *" field
>> (of_node) that is almost the only link between the irqdomain
>> and the device tree infrastructure.
>>
>> In order to prepare for the removal of that field, convert all
>> users to use an accessor.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   arch/arm/mach-omap2/omap-wakeupgen.c          |  2 +-
>>   arch/c6x/platforms/megamod-pic.c              |  2 +-
>>   arch/mips/cavium-octeon/octeon-irq.c          |  4 ++--
>>   arch/powerpc/platforms/cell/axon_msi.c        |  2 +-
>>   arch/powerpc/platforms/cell/spider-pic.c      |  9 +++++---
>>   arch/powerpc/platforms/pasemi/msi.c           |  6 ++++--
>>   arch/powerpc/platforms/powernv/opal-irqchip.c |  2 +-
>>   arch/powerpc/sysdev/ehv_pic.c                 |  3 ++-
>>   arch/powerpc/sysdev/fsl_msi.c                 |  2 +-
>>   arch/powerpc/sysdev/i8259.c                   |  3 ++-
>>   arch/powerpc/sysdev/ipic.c                    |  3 ++-
>>   arch/powerpc/sysdev/mpic.c                    |  3 ++-
>>   arch/powerpc/sysdev/mpic_msi.c                |  2 +-
>>   arch/powerpc/sysdev/qe_lib/qe_ic.c            |  3 ++-
>>   drivers/gpio/gpio-sodaville.c                 |  2 +-
>>   drivers/irqchip/exynos-combiner.c             |  2 +-
>>   drivers/irqchip/irq-atmel-aic-common.c        |  2 +-
>>   drivers/irqchip/irq-crossbar.c                |  4 ++--
>>   drivers/irqchip/irq-gic-v2m.c                 |  2 +-
>>   drivers/irqchip/irq-gic-v3-its.c              |  2 +-
>>   drivers/irqchip/irq-gic-v3.c                  |  2 +-
>>   drivers/irqchip/irq-gic.c                     |  2 +-
>>   drivers/irqchip/irq-hip04.c                   |  2 +-
>>   drivers/irqchip/irq-imx-gpcv2.c               |  2 +-
>>   drivers/irqchip/irq-mtk-sysirq.c              |  2 +-
>>   drivers/irqchip/irq-s3c24xx.c                 |  4 ++--
>>   drivers/irqchip/irq-tegra.c                   |  4 ++--
>>   drivers/irqchip/irq-vf610-mscm-ir.c           |  5 +++--
>>   drivers/spmi/spmi-pmic-arb.c                  |  2 +-
>>   include/linux/irqdomain.h                     |  5 +++++
>>   kernel/irq/irqdomain.c                        | 30 +++++++++++++++++++--------
>>   31 files changed, 74 insertions(+), 46 deletions(-)
> 
> Some missing files I noticed:
> ./arch/arm/mach-imx/gpc.c:	if (domain->of_node != controller)
> ./arch/arm/mach-imx/gpc.c:	parent_args.np = domain->parent->of_node;
> ./arch/arm/mach-exynos/suspend.c:	if (domain->of_node != controller)
> ./arch/arm/mach-exynos/suspend.c:	parent_args.np = domain->parent->of_node;

I've already caught them with v2 - 01.org doing its usual fine job!

Thanks anyway,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH 01/16] irqdomain: Use an accessor for the of_node field
@ 2015-10-12  9:30       ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-12  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/10/15 07:04, Hanjun Guo wrote:
> On 10/07/2015 01:36 AM, Marc Zyngier wrote:
>> The struct irq_domain contains a "struct device_node *" field
>> (of_node) that is almost the only link between the irqdomain
>> and the device tree infrastructure.
>>
>> In order to prepare for the removal of that field, convert all
>> users to use an accessor.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   arch/arm/mach-omap2/omap-wakeupgen.c          |  2 +-
>>   arch/c6x/platforms/megamod-pic.c              |  2 +-
>>   arch/mips/cavium-octeon/octeon-irq.c          |  4 ++--
>>   arch/powerpc/platforms/cell/axon_msi.c        |  2 +-
>>   arch/powerpc/platforms/cell/spider-pic.c      |  9 +++++---
>>   arch/powerpc/platforms/pasemi/msi.c           |  6 ++++--
>>   arch/powerpc/platforms/powernv/opal-irqchip.c |  2 +-
>>   arch/powerpc/sysdev/ehv_pic.c                 |  3 ++-
>>   arch/powerpc/sysdev/fsl_msi.c                 |  2 +-
>>   arch/powerpc/sysdev/i8259.c                   |  3 ++-
>>   arch/powerpc/sysdev/ipic.c                    |  3 ++-
>>   arch/powerpc/sysdev/mpic.c                    |  3 ++-
>>   arch/powerpc/sysdev/mpic_msi.c                |  2 +-
>>   arch/powerpc/sysdev/qe_lib/qe_ic.c            |  3 ++-
>>   drivers/gpio/gpio-sodaville.c                 |  2 +-
>>   drivers/irqchip/exynos-combiner.c             |  2 +-
>>   drivers/irqchip/irq-atmel-aic-common.c        |  2 +-
>>   drivers/irqchip/irq-crossbar.c                |  4 ++--
>>   drivers/irqchip/irq-gic-v2m.c                 |  2 +-
>>   drivers/irqchip/irq-gic-v3-its.c              |  2 +-
>>   drivers/irqchip/irq-gic-v3.c                  |  2 +-
>>   drivers/irqchip/irq-gic.c                     |  2 +-
>>   drivers/irqchip/irq-hip04.c                   |  2 +-
>>   drivers/irqchip/irq-imx-gpcv2.c               |  2 +-
>>   drivers/irqchip/irq-mtk-sysirq.c              |  2 +-
>>   drivers/irqchip/irq-s3c24xx.c                 |  4 ++--
>>   drivers/irqchip/irq-tegra.c                   |  4 ++--
>>   drivers/irqchip/irq-vf610-mscm-ir.c           |  5 +++--
>>   drivers/spmi/spmi-pmic-arb.c                  |  2 +-
>>   include/linux/irqdomain.h                     |  5 +++++
>>   kernel/irq/irqdomain.c                        | 30 +++++++++++++++++++--------
>>   31 files changed, 74 insertions(+), 46 deletions(-)
> 
> Some missing files I noticed:
> ./arch/arm/mach-imx/gpc.c:	if (domain->of_node != controller)
> ./arch/arm/mach-imx/gpc.c:	parent_args.np = domain->parent->of_node;
> ./arch/arm/mach-exynos/suspend.c:	if (domain->of_node != controller)
> ./arch/arm/mach-exynos/suspend.c:	parent_args.np = domain->parent->of_node;

I've already caught them with v2 - 01.org doing its usual fine job!

Thanks anyway,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 00/16] Divorcing irqdomain and device_node
  2015-10-11 21:01   ` Thomas Gleixner
@ 2015-10-12 10:31     ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-12 10:31 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jiang Liu, Jason Cooper, Rafael J. Wysocki, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On 11/10/15 22:01, Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>> [This patch series used to be called "Making the generic ACPI GSI
>> layer irqdomain aware", but as I've radically changed my approach to
>> this problem, I've decided to reset the counters...]
>>
>> The irqdomain code is not entierely ACPI friendly, as it has some
>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>> to scare the ARM ACPI developpers which end up with their own version
>> of the square wheel. And some of the ramifications actually run deeper
>> than initially expected.
>>
>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>> instead of 'struct device_node' as the identifier for a domain
>> (compatibility interfaces are of course added). It also introduces a
>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>> directly use to configure interrupts, and allow the ACPI GSI code to
>> be plugged into this.
>>
>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>> originally intended, and rework the MSI code to also move away from
>> using device nodes when using irqdomains.
>>
>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>> enabled platforms, having very little changes made to the actual
>> drivers (other than the probing infrastructure). Because we keep the
>> flow of information between the various layers identical between ACPI
>> and DT, we immediately benefit from the existing infrastructure.
>>
>> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
>>
>> Marc Zyngier (16):
>>   irqdomain: Use an accessor for the of_node field
>>   irqdomain: Convert irqdomain->of_node to fwnode
>>   irqdomain: Allow irq domain lookup by fwnode
>>   irqdomain: Introduce a firmware-specific IRQ specifier structure
>>   irqchip: Convert all alloc/xlate users from of_node to fwnode
>>   irqdomain: Introduce irq_create_fwspec_mapping
>>   irqdomain: Introduce irq_domain_create_{linear,tree}
>>   irqdomain: Add a fwnode_handle allocator
>>   acpi/gsi: Always perform an irq domain lookup
>>   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>   irqchip/gic: Get rid of gic_init_bases()
>>   irqchip/gic: Switch ACPI support to stacked domains
>>   irqchip/gic: Kill the xlate method
>>   acpi/gsi: Cleanup acpi_register_gsi
>>   irqdomain: Introduce irq_domain_create_hierarchy
>>   irqdomain/msi: Use fwnode instead of of_node
> 
> I really like this one way better than the previous attempts and I
> couldn't find any real issue when going through them with a fine comb.
> 
> I'd like to get that into 4.4, so I have to ask for the opinion of
> ACPI folks. Having an ack on those patches would be nice.

FWIW, I've rebased this on top of -rc5, with a couple of fixes to the
first patch (fixing missed of_node accessor conversions), but the series
is otherwise unchanged:

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
irq/irq-domain-fwnode-v2

I'd very much appreciate some feedback from the ACPI folks as well
(patch 8 is the potential point of contention, as it creates fwnodes
ex-nihilo).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-12 10:31     ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-12 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/10/15 22:01, Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>> [This patch series used to be called "Making the generic ACPI GSI
>> layer irqdomain aware", but as I've radically changed my approach to
>> this problem, I've decided to reset the counters...]
>>
>> The irqdomain code is not entierely ACPI friendly, as it has some
>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>> to scare the ARM ACPI developpers which end up with their own version
>> of the square wheel. And some of the ramifications actually run deeper
>> than initially expected.
>>
>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>> instead of 'struct device_node' as the identifier for a domain
>> (compatibility interfaces are of course added). It also introduces a
>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>> directly use to configure interrupts, and allow the ACPI GSI code to
>> be plugged into this.
>>
>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>> originally intended, and rework the MSI code to also move away from
>> using device nodes when using irqdomains.
>>
>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>> enabled platforms, having very little changes made to the actual
>> drivers (other than the probing infrastructure). Because we keep the
>> flow of information between the various layers identical between ACPI
>> and DT, we immediately benefit from the existing infrastructure.
>>
>> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
>>
>> Marc Zyngier (16):
>>   irqdomain: Use an accessor for the of_node field
>>   irqdomain: Convert irqdomain->of_node to fwnode
>>   irqdomain: Allow irq domain lookup by fwnode
>>   irqdomain: Introduce a firmware-specific IRQ specifier structure
>>   irqchip: Convert all alloc/xlate users from of_node to fwnode
>>   irqdomain: Introduce irq_create_fwspec_mapping
>>   irqdomain: Introduce irq_domain_create_{linear,tree}
>>   irqdomain: Add a fwnode_handle allocator
>>   acpi/gsi: Always perform an irq domain lookup
>>   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>   irqchip/gic: Get rid of gic_init_bases()
>>   irqchip/gic: Switch ACPI support to stacked domains
>>   irqchip/gic: Kill the xlate method
>>   acpi/gsi: Cleanup acpi_register_gsi
>>   irqdomain: Introduce irq_domain_create_hierarchy
>>   irqdomain/msi: Use fwnode instead of of_node
> 
> I really like this one way better than the previous attempts and I
> couldn't find any real issue when going through them with a fine comb.
> 
> I'd like to get that into 4.4, so I have to ask for the opinion of
> ACPI folks. Having an ack on those patches would be nice.

FWIW, I've rebased this on top of -rc5, with a couple of fixes to the
first patch (fixing missed of_node accessor conversions), but the series
is otherwise unchanged:

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
irq/irq-domain-fwnode-v2

I'd very much appreciate some feedback from the ACPI folks as well
(patch 8 is the potential point of contention, as it creates fwnodes
ex-nihilo).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
  2015-10-06 17:36   ` Marc Zyngier
  (?)
@ 2015-10-12 18:31     ` Suravee Suthikulpanit
  -1 siblings, 0 replies; 87+ messages in thread
From: Suravee Suthikulpanit @ 2015-10-12 18:31 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper,
	Rafael J. Wysocki
  Cc: Lorenzo Pieralisi, linux-kernel, Tomasz Nowicki, linux-acpi,
	Hanjun Guo, Jake Oshins, Graeme Gregory, linux-arm-kernel

[RESEND] Not sure if the email went out the first time.

Hi Marc,

On 10/6/15 12:36, Marc Zyngier wrote:
> So far, our irq domains are still looked up by device node.
> Let's change this and allow a domain to be looked up using
> a fwnode_handle pointer.
>
> The existing interfaces are preserved with a couple of helpers.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/linux/irqdomain.h | 11 +++++++++--
>   kernel/irq/irqdomain.c    | 14 ++++++--------
>   2 files changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 2f508f4..607c185 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>   					 irq_hw_number_t first_hwirq,
>   					 const struct irq_domain_ops *ops,
>   					 void *host_data);
> -extern struct irq_domain *irq_find_matching_host(struct device_node *node,
> -						 enum irq_domain_bus_token bus_token);
> +extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> +						   enum irq_domain_bus_token bus_token);
>   extern void irq_set_default_host(struct irq_domain *host);
>
> +static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
> +							enum irq_domain_bus_token bus_token)
> +{
> +	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
> +					bus_token);
> +}
> +
>   static inline struct irq_domain *irq_find_host(struct device_node *node)
>   {
>   	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 1aee5c1..10b6105 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>   EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
>
>   /**
> - * irq_find_matching_host() - Locates a domain for a given device node
> - * @node: device-tree node of the interrupt controller
> + * irq_find_matching_fwnode() - Locates a domain for a given fwnode
> + * @fwnode: FW descriptor of the interrupt controller
>    * @bus_token: domain-specific data
>    */
> -struct irq_domain *irq_find_matching_host(struct device_node *node,
> -					  enum irq_domain_bus_token bus_token)
> +struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> +					    enum irq_domain_bus_token bus_token)
>   {
>   	struct irq_domain *h, *found = NULL;
>   	int rc;
> @@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
>   	 */
>   	mutex_lock(&irq_domain_mutex);
>   	list_for_each_entry(h, &irq_domain_list, link) {
> -		struct device_node *of_node;
> -		of_node = irq_domain_get_of_node(h);
>   		if (h->ops->match)
> -			rc = h->ops->match(h, node, bus_token);
> +			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
>   		else
> -			rc = ((of_node != NULL) && (of_node == node) &&
> +			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
>   			      ((bus_token == DOMAIN_BUS_ANY) ||
>   			       (h->bus_token == bus_token)));
>
>

In the kernel/irq/irq_domain.c, shouldn't you also change the export 
symbol from:

     EXPORT_SYMBOL_GPL(irq_find_matching_host);

to:

     EXPORT_SYMBOL_GPL(irq_find_matching_fwnode);

at the end of this function as well?

Thanks,
Suravee

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

* Re: [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
@ 2015-10-12 18:31     ` Suravee Suthikulpanit
  0 siblings, 0 replies; 87+ messages in thread
From: Suravee Suthikulpanit @ 2015-10-12 18:31 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper,
	Rafael J. Wysocki
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Graeme Gregory, Jake Oshins

[RESEND] Not sure if the email went out the first time.

Hi Marc,

On 10/6/15 12:36, Marc Zyngier wrote:
> So far, our irq domains are still looked up by device node.
> Let's change this and allow a domain to be looked up using
> a fwnode_handle pointer.
>
> The existing interfaces are preserved with a couple of helpers.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/linux/irqdomain.h | 11 +++++++++--
>   kernel/irq/irqdomain.c    | 14 ++++++--------
>   2 files changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 2f508f4..607c185 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>   					 irq_hw_number_t first_hwirq,
>   					 const struct irq_domain_ops *ops,
>   					 void *host_data);
> -extern struct irq_domain *irq_find_matching_host(struct device_node *node,
> -						 enum irq_domain_bus_token bus_token);
> +extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> +						   enum irq_domain_bus_token bus_token);
>   extern void irq_set_default_host(struct irq_domain *host);
>
> +static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
> +							enum irq_domain_bus_token bus_token)
> +{
> +	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
> +					bus_token);
> +}
> +
>   static inline struct irq_domain *irq_find_host(struct device_node *node)
>   {
>   	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 1aee5c1..10b6105 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>   EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
>
>   /**
> - * irq_find_matching_host() - Locates a domain for a given device node
> - * @node: device-tree node of the interrupt controller
> + * irq_find_matching_fwnode() - Locates a domain for a given fwnode
> + * @fwnode: FW descriptor of the interrupt controller
>    * @bus_token: domain-specific data
>    */
> -struct irq_domain *irq_find_matching_host(struct device_node *node,
> -					  enum irq_domain_bus_token bus_token)
> +struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> +					    enum irq_domain_bus_token bus_token)
>   {
>   	struct irq_domain *h, *found = NULL;
>   	int rc;
> @@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
>   	 */
>   	mutex_lock(&irq_domain_mutex);
>   	list_for_each_entry(h, &irq_domain_list, link) {
> -		struct device_node *of_node;
> -		of_node = irq_domain_get_of_node(h);
>   		if (h->ops->match)
> -			rc = h->ops->match(h, node, bus_token);
> +			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
>   		else
> -			rc = ((of_node != NULL) && (of_node == node) &&
> +			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
>   			      ((bus_token == DOMAIN_BUS_ANY) ||
>   			       (h->bus_token == bus_token)));
>
>

In the kernel/irq/irq_domain.c, shouldn't you also change the export 
symbol from:

     EXPORT_SYMBOL_GPL(irq_find_matching_host);

to:

     EXPORT_SYMBOL_GPL(irq_find_matching_fwnode);

at the end of this function as well?

Thanks,
Suravee



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

* [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
@ 2015-10-12 18:31     ` Suravee Suthikulpanit
  0 siblings, 0 replies; 87+ messages in thread
From: Suravee Suthikulpanit @ 2015-10-12 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

[RESEND] Not sure if the email went out the first time.

Hi Marc,

On 10/6/15 12:36, Marc Zyngier wrote:
> So far, our irq domains are still looked up by device node.
> Let's change this and allow a domain to be looked up using
> a fwnode_handle pointer.
>
> The existing interfaces are preserved with a couple of helpers.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/linux/irqdomain.h | 11 +++++++++--
>   kernel/irq/irqdomain.c    | 14 ++++++--------
>   2 files changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 2f508f4..607c185 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>   					 irq_hw_number_t first_hwirq,
>   					 const struct irq_domain_ops *ops,
>   					 void *host_data);
> -extern struct irq_domain *irq_find_matching_host(struct device_node *node,
> -						 enum irq_domain_bus_token bus_token);
> +extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> +						   enum irq_domain_bus_token bus_token);
>   extern void irq_set_default_host(struct irq_domain *host);
>
> +static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
> +							enum irq_domain_bus_token bus_token)
> +{
> +	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
> +					bus_token);
> +}
> +
>   static inline struct irq_domain *irq_find_host(struct device_node *node)
>   {
>   	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 1aee5c1..10b6105 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>   EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
>
>   /**
> - * irq_find_matching_host() - Locates a domain for a given device node
> - * @node: device-tree node of the interrupt controller
> + * irq_find_matching_fwnode() - Locates a domain for a given fwnode
> + * @fwnode: FW descriptor of the interrupt controller
>    * @bus_token: domain-specific data
>    */
> -struct irq_domain *irq_find_matching_host(struct device_node *node,
> -					  enum irq_domain_bus_token bus_token)
> +struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> +					    enum irq_domain_bus_token bus_token)
>   {
>   	struct irq_domain *h, *found = NULL;
>   	int rc;
> @@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
>   	 */
>   	mutex_lock(&irq_domain_mutex);
>   	list_for_each_entry(h, &irq_domain_list, link) {
> -		struct device_node *of_node;
> -		of_node = irq_domain_get_of_node(h);
>   		if (h->ops->match)
> -			rc = h->ops->match(h, node, bus_token);
> +			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
>   		else
> -			rc = ((of_node != NULL) && (of_node == node) &&
> +			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
>   			      ((bus_token == DOMAIN_BUS_ANY) ||
>   			       (h->bus_token == bus_token)));
>
>

In the kernel/irq/irq_domain.c, shouldn't you also change the export 
symbol from:

     EXPORT_SYMBOL_GPL(irq_find_matching_host);

to:

     EXPORT_SYMBOL_GPL(irq_find_matching_fwnode);

at the end of this function as well?

Thanks,
Suravee

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

* Re: [PATCH 08/16] irqdomain: Add a fwnode_handle allocator
  2015-10-06 17:36   ` Marc Zyngier
@ 2015-10-12 20:32     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:32 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Thomas Gleixner, Jiang Liu, Jason Cooper, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On Tuesday, October 06, 2015 06:36:21 PM Marc Zyngier wrote:
> In order to be able to reference an irqdomain from ACPI, we need
> to be able to create an identifier, which is usually a struct
> device_node.
> 
> This device node does't really fit the ACPI infrastructure, so
> we cunningly allocate a new structure containing a fwnode_handle,
> and return that.
> 
> This structure doesn't really point to a device (interrupt
> controllers are not "real" devices in Linux), but as we cannot
> really deny that they exist, we create them with a new fwnode_type
> (FWNODE_IRQCHIP).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

This is fine by me:

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

[Side note: One of the patches in my linux-next branch will conflict with
the change in enum fwnode_type, but that shouldn't be a big deal.] 

> ---
>  include/linux/fwnode.h    |  1 +
>  include/linux/irqdomain.h |  2 ++
>  kernel/irq/irqdomain.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 54 insertions(+)
> 
> diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
> index 0408545..37ec668 100644
> --- a/include/linux/fwnode.h
> +++ b/include/linux/fwnode.h
> @@ -17,6 +17,7 @@ enum fwnode_type {
>  	FWNODE_OF,
>  	FWNODE_ACPI,
>  	FWNODE_PDATA,
> +	FWNODE_IRQCHIP,
>  };
>  
>  struct fwnode_handle {
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 995d4c5..949caa7 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
>  }
>  
>  #ifdef CONFIG_IRQ_DOMAIN
> +struct fwnode_handle *irq_domain_alloc_fwnode(void *data);
> +void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
>  struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
>  				    irq_hw_number_t hwirq_max, int direct_max,
>  				    const struct irq_domain_ops *ops,
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index ea62f67..6fbecae 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
>  				  irq_hw_number_t hwirq, int node);
>  static void irq_domain_check_hierarchy(struct irq_domain *domain);
>  
> +struct irqchip_fwid {
> +	struct fwnode_handle fwnode;
> +	char *name;
> +	void *data;
> +};
> +
> +/**
> + * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
> + *                           identifying an irq domain
> + * @data: optional user-provided data
> + *
> + * Allocate a struct device_node, and return a poiner to the embedded
> + * fwnode_handle (or NULL on failure).
> + */
> +struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
> +{
> +	struct irqchip_fwid *fwid;
> +	char *name;
> +
> +	fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
> +	name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
> +
> +	if (!fwid || !name) {
> +		kfree(fwid);
> +		kfree(name);
> +		return NULL;
> +	}
> +
> +	fwid->name = name;
> +	fwid->data = data;
> +	fwid->fwnode.type = FWNODE_IRQCHIP;
> +	return &fwid->fwnode;
> +}
> +
> +/**
> + * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
> + *
> + * Free a fwnode_handle allocated with irq_domain_alloc_fwnode.
> + */
> +void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
> +{
> +	struct irqchip_fwid *fwid;
> +
> +	if (WARN_ON(fwnode->type != FWNODE_IRQCHIP))
> +		return;
> +
> +	fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
> +	kfree(fwid->name);
> +	kfree(fwid);
> +}
> +
>  /**
>   * __irq_domain_add() - Allocate a new irq_domain data structure
>   * @of_node: optional device-tree node of the interrupt controller
> 


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

* [PATCH 08/16] irqdomain: Add a fwnode_handle allocator
@ 2015-10-12 20:32     ` Rafael J. Wysocki
  0 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, October 06, 2015 06:36:21 PM Marc Zyngier wrote:
> In order to be able to reference an irqdomain from ACPI, we need
> to be able to create an identifier, which is usually a struct
> device_node.
> 
> This device node does't really fit the ACPI infrastructure, so
> we cunningly allocate a new structure containing a fwnode_handle,
> and return that.
> 
> This structure doesn't really point to a device (interrupt
> controllers are not "real" devices in Linux), but as we cannot
> really deny that they exist, we create them with a new fwnode_type
> (FWNODE_IRQCHIP).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

This is fine by me:

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

[Side note: One of the patches in my linux-next branch will conflict with
the change in enum fwnode_type, but that shouldn't be a big deal.] 

> ---
>  include/linux/fwnode.h    |  1 +
>  include/linux/irqdomain.h |  2 ++
>  kernel/irq/irqdomain.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 54 insertions(+)
> 
> diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
> index 0408545..37ec668 100644
> --- a/include/linux/fwnode.h
> +++ b/include/linux/fwnode.h
> @@ -17,6 +17,7 @@ enum fwnode_type {
>  	FWNODE_OF,
>  	FWNODE_ACPI,
>  	FWNODE_PDATA,
> +	FWNODE_IRQCHIP,
>  };
>  
>  struct fwnode_handle {
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 995d4c5..949caa7 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
>  }
>  
>  #ifdef CONFIG_IRQ_DOMAIN
> +struct fwnode_handle *irq_domain_alloc_fwnode(void *data);
> +void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
>  struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
>  				    irq_hw_number_t hwirq_max, int direct_max,
>  				    const struct irq_domain_ops *ops,
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index ea62f67..6fbecae 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
>  				  irq_hw_number_t hwirq, int node);
>  static void irq_domain_check_hierarchy(struct irq_domain *domain);
>  
> +struct irqchip_fwid {
> +	struct fwnode_handle fwnode;
> +	char *name;
> +	void *data;
> +};
> +
> +/**
> + * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
> + *                           identifying an irq domain
> + * @data: optional user-provided data
> + *
> + * Allocate a struct device_node, and return a poiner to the embedded
> + * fwnode_handle (or NULL on failure).
> + */
> +struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
> +{
> +	struct irqchip_fwid *fwid;
> +	char *name;
> +
> +	fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
> +	name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
> +
> +	if (!fwid || !name) {
> +		kfree(fwid);
> +		kfree(name);
> +		return NULL;
> +	}
> +
> +	fwid->name = name;
> +	fwid->data = data;
> +	fwid->fwnode.type = FWNODE_IRQCHIP;
> +	return &fwid->fwnode;
> +}
> +
> +/**
> + * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
> + *
> + * Free a fwnode_handle allocated with irq_domain_alloc_fwnode.
> + */
> +void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
> +{
> +	struct irqchip_fwid *fwid;
> +
> +	if (WARN_ON(fwnode->type != FWNODE_IRQCHIP))
> +		return;
> +
> +	fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
> +	kfree(fwid->name);
> +	kfree(fwid);
> +}
> +
>  /**
>   * __irq_domain_add() - Allocate a new irq_domain data structure
>   * @of_node: optional device-tree node of the interrupt controller
> 

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

* Re: [PATCH 09/16] acpi/gsi: Always perform an irq domain lookup
  2015-10-06 17:36   ` Marc Zyngier
@ 2015-10-12 20:34     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:34 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Thomas Gleixner, Jiang Liu, Jason Cooper, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On Tuesday, October 06, 2015 06:36:22 PM Marc Zyngier wrote:
> Instead of directly passing NULL to the various irq_domain functions,
> start by looking up the domain with a domain identifier..
> 
> As this identifier is permanently set to NULL, the lookup function will
> return the same value (no domain found) and the default will be used,
> preserving the current behaviour.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> ---
>  drivers/acpi/gsi.c | 26 +++++++++++++-------------
>  1 file changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
> index 38208f2..2c39fe1 100644
> --- a/drivers/acpi/gsi.c
> +++ b/drivers/acpi/gsi.c
> @@ -11,9 +11,12 @@
>  #include <linux/acpi.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
> +#include <linux/of.h>
>  
>  enum acpi_irq_model_id acpi_irq_model;
>  
> +static struct fwnode_handle *acpi_gsi_domain_id;
> +
>  static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
>  {
>  	switch (polarity) {
> @@ -45,12 +48,10 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
>   */
>  int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
>  {
> -	/*
> -	 * Only default domain is supported at present, always find
> -	 * the mapping corresponding to default domain by passing NULL
> -	 * as irq_domain parameter
> -	 */
> -	*irq = irq_find_mapping(NULL, gsi);
> +	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> +							DOMAIN_BUS_ANY);
> +
> +	*irq = irq_find_mapping(d, gsi);
>  	/*
>  	 * *irq == 0 means no mapping, that should
>  	 * be reported as a failure
> @@ -74,13 +75,10 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
>  {
>  	unsigned int irq;
>  	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
> +	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> +							DOMAIN_BUS_ANY);
>  
> -	/*
> -	 * There is no way at present to look-up the IRQ domain on ACPI,
> -	 * hence always create mapping referring to the default domain
> -	 * by passing NULL as irq_domain parameter
> -	 */
> -	irq = irq_create_mapping(NULL, gsi);
> +	irq = irq_create_mapping(d, gsi);
>  	if (!irq)
>  		return -EINVAL;
>  
> @@ -98,7 +96,9 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
>   */
>  void acpi_unregister_gsi(u32 gsi)
>  {
> -	int irq = irq_find_mapping(NULL, gsi);
> +	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> +							DOMAIN_BUS_ANY);
> +	int irq = irq_find_mapping(d, gsi);
>  
>  	irq_dispose_mapping(irq);
>  }
> 


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

* [PATCH 09/16] acpi/gsi: Always perform an irq domain lookup
@ 2015-10-12 20:34     ` Rafael J. Wysocki
  0 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, October 06, 2015 06:36:22 PM Marc Zyngier wrote:
> Instead of directly passing NULL to the various irq_domain functions,
> start by looking up the domain with a domain identifier..
> 
> As this identifier is permanently set to NULL, the lookup function will
> return the same value (no domain found) and the default will be used,
> preserving the current behaviour.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> ---
>  drivers/acpi/gsi.c | 26 +++++++++++++-------------
>  1 file changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
> index 38208f2..2c39fe1 100644
> --- a/drivers/acpi/gsi.c
> +++ b/drivers/acpi/gsi.c
> @@ -11,9 +11,12 @@
>  #include <linux/acpi.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
> +#include <linux/of.h>
>  
>  enum acpi_irq_model_id acpi_irq_model;
>  
> +static struct fwnode_handle *acpi_gsi_domain_id;
> +
>  static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
>  {
>  	switch (polarity) {
> @@ -45,12 +48,10 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
>   */
>  int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
>  {
> -	/*
> -	 * Only default domain is supported at present, always find
> -	 * the mapping corresponding to default domain by passing NULL
> -	 * as irq_domain parameter
> -	 */
> -	*irq = irq_find_mapping(NULL, gsi);
> +	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> +							DOMAIN_BUS_ANY);
> +
> +	*irq = irq_find_mapping(d, gsi);
>  	/*
>  	 * *irq == 0 means no mapping, that should
>  	 * be reported as a failure
> @@ -74,13 +75,10 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
>  {
>  	unsigned int irq;
>  	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
> +	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> +							DOMAIN_BUS_ANY);
>  
> -	/*
> -	 * There is no way at present to look-up the IRQ domain on ACPI,
> -	 * hence always create mapping referring to the default domain
> -	 * by passing NULL as irq_domain parameter
> -	 */
> -	irq = irq_create_mapping(NULL, gsi);
> +	irq = irq_create_mapping(d, gsi);
>  	if (!irq)
>  		return -EINVAL;
>  
> @@ -98,7 +96,9 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
>   */
>  void acpi_unregister_gsi(u32 gsi)
>  {
> -	int irq = irq_find_mapping(NULL, gsi);
> +	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> +							DOMAIN_BUS_ANY);
> +	int irq = irq_find_mapping(d, gsi);
>  
>  	irq_dispose_mapping(irq);
>  }
> 

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

* Re: [PATCH 10/16] acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
  2015-10-06 17:36   ` Marc Zyngier
@ 2015-10-12 20:36     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:36 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Thomas Gleixner, Jiang Liu, Jason Cooper, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On Tuesday, October 06, 2015 06:36:23 PM Marc Zyngier wrote:
> In order to start embrassing irqdomains at the GSI level, introduce
> a new initializer:
> 
> void acpi_set_irq_model(enum acpi_irq_model_id model,
> 			struct fwnode_handle *fwnode);
> 
> where:
> - model is the value assigned to acpi_irq_model
> - fwnode is the identifier for the irqdomain mapping
>   GSI interrupts
> 
> As nobody calls this code yet, the current code is (mostly)
> left in place.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> 
> Conflicts:
> 	include/linux/acpi.h
> ---
>  drivers/acpi/gsi.c   | 32 +++++++++++++++++++++++++++-----
>  include/linux/acpi.h |  3 +++
>  2 files changed, 30 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
> index 2c39fe1..202a8fe 100644
> --- a/drivers/acpi/gsi.c
> +++ b/drivers/acpi/gsi.c
> @@ -75,12 +75,21 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
>  {
>  	unsigned int irq;
>  	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
> -	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> -							DOMAIN_BUS_ANY);
>  
> -	irq = irq_create_mapping(d, gsi);
> -	if (!irq)
> -		return -EINVAL;
> +	if (acpi_gsi_domain_id) {
> +		struct irq_fwspec fwspec;
> +
> +		fwspec.fwnode = acpi_gsi_domain_id;
> +		fwspec.param[0] = gsi;
> +		fwspec.param[1] = irq_type;
> +		fwspec.param_count = 2;
> +
> +		return irq_create_fwspec_mapping(&fwspec);
> +	} else {
> +		irq = irq_create_mapping(NULL, gsi);
> +		if (!irq)
> +			return -EINVAL;
> +	}
>  
>  	/* Set irq type if specified and different than the current one */
>  	if (irq_type != IRQ_TYPE_NONE &&
> @@ -103,3 +112,16 @@ void acpi_unregister_gsi(u32 gsi)
>  	irq_dispose_mapping(irq);
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> +
> +/**
> + * acpi_set_irq_model - Setup the GSI irqdomain information
> + * @model: the value assigned to acpi_irq_model
> + * @fwnode: the irq_domain identifier for mapping and looking up
> + *          GSI interrupts
> + */
> +void __init acpi_set_irq_model(enum acpi_irq_model_id model,
> +			       struct fwnode_handle *fwnode)
> +{
> +	acpi_irq_model = model;
> +	acpi_gsi_domain_id = fwnode;
> +}
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 43856d1..d863e12 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -201,6 +201,9 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
>  
> +void acpi_set_irq_model(enum acpi_irq_model_id model,
> +			struct fwnode_handle *fwnode);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
>  #else
> 


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

* [PATCH 10/16] acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
@ 2015-10-12 20:36     ` Rafael J. Wysocki
  0 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, October 06, 2015 06:36:23 PM Marc Zyngier wrote:
> In order to start embrassing irqdomains at the GSI level, introduce
> a new initializer:
> 
> void acpi_set_irq_model(enum acpi_irq_model_id model,
> 			struct fwnode_handle *fwnode);
> 
> where:
> - model is the value assigned to acpi_irq_model
> - fwnode is the identifier for the irqdomain mapping
>   GSI interrupts
> 
> As nobody calls this code yet, the current code is (mostly)
> left in place.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> 
> Conflicts:
> 	include/linux/acpi.h
> ---
>  drivers/acpi/gsi.c   | 32 +++++++++++++++++++++++++++-----
>  include/linux/acpi.h |  3 +++
>  2 files changed, 30 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
> index 2c39fe1..202a8fe 100644
> --- a/drivers/acpi/gsi.c
> +++ b/drivers/acpi/gsi.c
> @@ -75,12 +75,21 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
>  {
>  	unsigned int irq;
>  	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
> -	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> -							DOMAIN_BUS_ANY);
>  
> -	irq = irq_create_mapping(d, gsi);
> -	if (!irq)
> -		return -EINVAL;
> +	if (acpi_gsi_domain_id) {
> +		struct irq_fwspec fwspec;
> +
> +		fwspec.fwnode = acpi_gsi_domain_id;
> +		fwspec.param[0] = gsi;
> +		fwspec.param[1] = irq_type;
> +		fwspec.param_count = 2;
> +
> +		return irq_create_fwspec_mapping(&fwspec);
> +	} else {
> +		irq = irq_create_mapping(NULL, gsi);
> +		if (!irq)
> +			return -EINVAL;
> +	}
>  
>  	/* Set irq type if specified and different than the current one */
>  	if (irq_type != IRQ_TYPE_NONE &&
> @@ -103,3 +112,16 @@ void acpi_unregister_gsi(u32 gsi)
>  	irq_dispose_mapping(irq);
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> +
> +/**
> + * acpi_set_irq_model - Setup the GSI irqdomain information
> + * @model: the value assigned to acpi_irq_model
> + * @fwnode: the irq_domain identifier for mapping and looking up
> + *          GSI interrupts
> + */
> +void __init acpi_set_irq_model(enum acpi_irq_model_id model,
> +			       struct fwnode_handle *fwnode)
> +{
> +	acpi_irq_model = model;
> +	acpi_gsi_domain_id = fwnode;
> +}
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 43856d1..d863e12 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -201,6 +201,9 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
>  
> +void acpi_set_irq_model(enum acpi_irq_model_id model,
> +			struct fwnode_handle *fwnode);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
>  #else
> 

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

* Re: [PATCH 14/16] acpi/gsi: Cleanup acpi_register_gsi
  2015-10-06 17:36   ` Marc Zyngier
@ 2015-10-12 20:37     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:37 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Thomas Gleixner, Jiang Liu, Jason Cooper, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On Tuesday, October 06, 2015 06:36:27 PM Marc Zyngier wrote:
> As the only user of drivers/acpi/gsi.c is now using acpi_set_irq_model
> to set acpi_gsi_descriptor_populate to something meaningful, we can
> always rely on that information to be present (its absence is an error),
> and guarantee that new interrupt controllers will use this API.
> 
> Take this opportunity to cleanup acpi_register_gsi.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> ---
>  drivers/acpi/gsi.c | 30 ++++++++++--------------------
>  1 file changed, 10 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
> index 202a8fe..fa4585a 100644
> --- a/drivers/acpi/gsi.c
> +++ b/drivers/acpi/gsi.c
> @@ -73,29 +73,19 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
>  int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
>  		      int polarity)
>  {
> -	unsigned int irq;
> -	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
> +	struct irq_fwspec fwspec;
>  
> -	if (acpi_gsi_domain_id) {
> -		struct irq_fwspec fwspec;
> -
> -		fwspec.fwnode = acpi_gsi_domain_id;
> -		fwspec.param[0] = gsi;
> -		fwspec.param[1] = irq_type;
> -		fwspec.param_count = 2;
> -
> -		return irq_create_fwspec_mapping(&fwspec);
> -	} else {
> -		irq = irq_create_mapping(NULL, gsi);
> -		if (!irq)
> -			return -EINVAL;
> +	if (WARN_ON(!acpi_gsi_domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");
> +		return -EINVAL;
>  	}
>  
> -	/* Set irq type if specified and different than the current one */
> -	if (irq_type != IRQ_TYPE_NONE &&
> -		irq_type != irq_get_trigger_type(irq))
> -		irq_set_irq_type(irq, irq_type);
> -	return irq;
> +	fwspec.fwnode = acpi_gsi_domain_id;
> +	fwspec.param[0] = gsi;
> +	fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
>  }
>  EXPORT_SYMBOL_GPL(acpi_register_gsi);

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

* [PATCH 14/16] acpi/gsi: Cleanup acpi_register_gsi
@ 2015-10-12 20:37     ` Rafael J. Wysocki
  0 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, October 06, 2015 06:36:27 PM Marc Zyngier wrote:
> As the only user of drivers/acpi/gsi.c is now using acpi_set_irq_model
> to set acpi_gsi_descriptor_populate to something meaningful, we can
> always rely on that information to be present (its absence is an error),
> and guarantee that new interrupt controllers will use this API.
> 
> Take this opportunity to cleanup acpi_register_gsi.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> ---
>  drivers/acpi/gsi.c | 30 ++++++++++--------------------
>  1 file changed, 10 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
> index 202a8fe..fa4585a 100644
> --- a/drivers/acpi/gsi.c
> +++ b/drivers/acpi/gsi.c
> @@ -73,29 +73,19 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
>  int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
>  		      int polarity)
>  {
> -	unsigned int irq;
> -	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
> +	struct irq_fwspec fwspec;
>  
> -	if (acpi_gsi_domain_id) {
> -		struct irq_fwspec fwspec;
> -
> -		fwspec.fwnode = acpi_gsi_domain_id;
> -		fwspec.param[0] = gsi;
> -		fwspec.param[1] = irq_type;
> -		fwspec.param_count = 2;
> -
> -		return irq_create_fwspec_mapping(&fwspec);
> -	} else {
> -		irq = irq_create_mapping(NULL, gsi);
> -		if (!irq)
> -			return -EINVAL;
> +	if (WARN_ON(!acpi_gsi_domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");
> +		return -EINVAL;
>  	}
>  
> -	/* Set irq type if specified and different than the current one */
> -	if (irq_type != IRQ_TYPE_NONE &&
> -		irq_type != irq_get_trigger_type(irq))
> -		irq_set_irq_type(irq, irq_type);
> -	return irq;
> +	fwspec.fwnode = acpi_gsi_domain_id;
> +	fwspec.param[0] = gsi;
> +	fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
>  }
>  EXPORT_SYMBOL_GPL(acpi_register_gsi);

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

* Re: [PATCH 00/16] Divorcing irqdomain and device_node
  2015-10-11 21:01   ` Thomas Gleixner
@ 2015-10-12 20:38     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:38 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Marc Zyngier, Jiang Liu, Jason Cooper, linux-acpi,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Suravee Suthikulpanit,
	Graeme Gregory, Jake Oshins

On Sunday, October 11, 2015 11:01:17 PM Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
> > [This patch series used to be called "Making the generic ACPI GSI
> > layer irqdomain aware", but as I've radically changed my approach to
> > this problem, I've decided to reset the counters...]
> > 
> > The irqdomain code is not entierely ACPI friendly, as it has some
> > built-in knowledge of the device-tree. Nothing too harmful, but enough
> > to scare the ARM ACPI developpers which end up with their own version
> > of the square wheel. And some of the ramifications actually run deeper
> > than initially expected.
> > 
> > This series adapts the irqdomain code to use 'struct fwnode_handle'
> > instead of 'struct device_node' as the identifier for a domain
> > (compatibility interfaces are of course added). It also introduces a
> > generic IRQ specifier that firmware interfaces (DT or ACPI) can
> > directly use to configure interrupts, and allow the ACPI GSI code to
> > be plugged into this.
> > 
> > As examples, we convert the ARM GIC ACPI support to use irqdomains as
> > originally intended, and rework the MSI code to also move away from
> > using device nodes when using irqdomains.
> > 
> > Overall, this gives us a way to use irqdomains on both DT and ACPI
> > enabled platforms, having very little changes made to the actual
> > drivers (other than the probing infrastructure). Because we keep the
> > flow of information between the various layers identical between ACPI
> > and DT, we immediately benefit from the existing infrastructure.
> > 
> > This has been test-booted on Juno, is based on 4.3-rc4, and available at:
> > 
> > git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
> > 
> > Marc Zyngier (16):
> >   irqdomain: Use an accessor for the of_node field
> >   irqdomain: Convert irqdomain->of_node to fwnode
> >   irqdomain: Allow irq domain lookup by fwnode
> >   irqdomain: Introduce a firmware-specific IRQ specifier structure
> >   irqchip: Convert all alloc/xlate users from of_node to fwnode
> >   irqdomain: Introduce irq_create_fwspec_mapping
> >   irqdomain: Introduce irq_domain_create_{linear,tree}
> >   irqdomain: Add a fwnode_handle allocator
> >   acpi/gsi: Always perform an irq domain lookup
> >   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
> >   irqchip/gic: Get rid of gic_init_bases()
> >   irqchip/gic: Switch ACPI support to stacked domains
> >   irqchip/gic: Kill the xlate method
> >   acpi/gsi: Cleanup acpi_register_gsi
> >   irqdomain: Introduce irq_domain_create_hierarchy
> >   irqdomain/msi: Use fwnode instead of of_node
> 
> I really like this one way better than the previous attempts and I
> couldn't find any real issue when going through them with a fine comb.
> 
> I'd like to get that into 4.4, so I have to ask for the opinion of
> ACPI folks. Having an ack on those patches would be nice.

I've ACKed the generic ones, please let me know if I missed any of them.

The rest seems to be ARM-specific ...

Thanks,
Rafael

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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-12 20:38     ` Rafael J. Wysocki
  0 siblings, 0 replies; 87+ messages in thread
From: Rafael J. Wysocki @ 2015-10-12 20:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday, October 11, 2015 11:01:17 PM Thomas Gleixner wrote:
> On Tue, 6 Oct 2015, Marc Zyngier wrote:
> > [This patch series used to be called "Making the generic ACPI GSI
> > layer irqdomain aware", but as I've radically changed my approach to
> > this problem, I've decided to reset the counters...]
> > 
> > The irqdomain code is not entierely ACPI friendly, as it has some
> > built-in knowledge of the device-tree. Nothing too harmful, but enough
> > to scare the ARM ACPI developpers which end up with their own version
> > of the square wheel. And some of the ramifications actually run deeper
> > than initially expected.
> > 
> > This series adapts the irqdomain code to use 'struct fwnode_handle'
> > instead of 'struct device_node' as the identifier for a domain
> > (compatibility interfaces are of course added). It also introduces a
> > generic IRQ specifier that firmware interfaces (DT or ACPI) can
> > directly use to configure interrupts, and allow the ACPI GSI code to
> > be plugged into this.
> > 
> > As examples, we convert the ARM GIC ACPI support to use irqdomains as
> > originally intended, and rework the MSI code to also move away from
> > using device nodes when using irqdomains.
> > 
> > Overall, this gives us a way to use irqdomains on both DT and ACPI
> > enabled platforms, having very little changes made to the actual
> > drivers (other than the probing infrastructure). Because we keep the
> > flow of information between the various layers identical between ACPI
> > and DT, we immediately benefit from the existing infrastructure.
> > 
> > This has been test-booted on Juno, is based on 4.3-rc4, and available at:
> > 
> > git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
> > 
> > Marc Zyngier (16):
> >   irqdomain: Use an accessor for the of_node field
> >   irqdomain: Convert irqdomain->of_node to fwnode
> >   irqdomain: Allow irq domain lookup by fwnode
> >   irqdomain: Introduce a firmware-specific IRQ specifier structure
> >   irqchip: Convert all alloc/xlate users from of_node to fwnode
> >   irqdomain: Introduce irq_create_fwspec_mapping
> >   irqdomain: Introduce irq_domain_create_{linear,tree}
> >   irqdomain: Add a fwnode_handle allocator
> >   acpi/gsi: Always perform an irq domain lookup
> >   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
> >   irqchip/gic: Get rid of gic_init_bases()
> >   irqchip/gic: Switch ACPI support to stacked domains
> >   irqchip/gic: Kill the xlate method
> >   acpi/gsi: Cleanup acpi_register_gsi
> >   irqdomain: Introduce irq_domain_create_hierarchy
> >   irqdomain/msi: Use fwnode instead of of_node
> 
> I really like this one way better than the previous attempts and I
> couldn't find any real issue when going through them with a fine comb.
> 
> I'd like to get that into 4.4, so I have to ask for the opinion of
> ACPI folks. Having an ack on those patches would be nice.

I've ACKed the generic ones, please let me know if I missed any of them.

The rest seems to be ARM-specific ...

Thanks,
Rafael

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

* Re: [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
  2015-10-12 18:31     ` Suravee Suthikulpanit
  (?)
@ 2015-10-13  7:35       ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-13  7:35 UTC (permalink / raw)
  To: Suravee Suthikulpanit
  Cc: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki,
	linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Graeme Gregory, Jake Oshins

On Mon, 12 Oct 2015 13:31:09 -0500
Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> wrote:

Hi Suravee,

> [RESEND] Not sure if the email went out the first time.
> 
> Hi Marc,
> 
> On 10/6/15 12:36, Marc Zyngier wrote:
> > So far, our irq domains are still looked up by device node.
> > Let's change this and allow a domain to be looked up using
> > a fwnode_handle pointer.
> >
> > The existing interfaces are preserved with a couple of helpers.
> >
> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> > ---
> >   include/linux/irqdomain.h | 11 +++++++++--
> >   kernel/irq/irqdomain.c    | 14 ++++++--------
> >   2 files changed, 15 insertions(+), 10 deletions(-)
> >
> > diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> > index 2f508f4..607c185 100644
> > --- a/include/linux/irqdomain.h
> > +++ b/include/linux/irqdomain.h
> > @@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> >   					 irq_hw_number_t first_hwirq,
> >   					 const struct irq_domain_ops *ops,
> >   					 void *host_data);
> > -extern struct irq_domain *irq_find_matching_host(struct device_node *node,
> > -						 enum irq_domain_bus_token bus_token);
> > +extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> > +						   enum irq_domain_bus_token bus_token);
> >   extern void irq_set_default_host(struct irq_domain *host);
> >
> > +static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
> > +							enum irq_domain_bus_token bus_token)
> > +{
> > +	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
> > +					bus_token);
> > +}
> > +
> >   static inline struct irq_domain *irq_find_host(struct device_node *node)
> >   {
> >   	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> > index 1aee5c1..10b6105 100644
> > --- a/kernel/irq/irqdomain.c
> > +++ b/kernel/irq/irqdomain.c
> > @@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> >   EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
> >
> >   /**
> > - * irq_find_matching_host() - Locates a domain for a given device node
> > - * @node: device-tree node of the interrupt controller
> > + * irq_find_matching_fwnode() - Locates a domain for a given fwnode
> > + * @fwnode: FW descriptor of the interrupt controller
> >    * @bus_token: domain-specific data
> >    */
> > -struct irq_domain *irq_find_matching_host(struct device_node *node,
> > -					  enum irq_domain_bus_token bus_token)
> > +struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> > +					    enum irq_domain_bus_token bus_token)
> >   {
> >   	struct irq_domain *h, *found = NULL;
> >   	int rc;
> > @@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
> >   	 */
> >   	mutex_lock(&irq_domain_mutex);
> >   	list_for_each_entry(h, &irq_domain_list, link) {
> > -		struct device_node *of_node;
> > -		of_node = irq_domain_get_of_node(h);
> >   		if (h->ops->match)
> > -			rc = h->ops->match(h, node, bus_token);
> > +			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
> >   		else
> > -			rc = ((of_node != NULL) && (of_node == node) &&
> > +			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
> >   			      ((bus_token == DOMAIN_BUS_ANY) ||
> >   			       (h->bus_token == bus_token)));
> >
> >
> 
> In the kernel/irq/irq_domain.c, shouldn't you also change the export 
> symbol from:
> 
>      EXPORT_SYMBOL_GPL(irq_find_matching_host);
> 
> to:
> 
>      EXPORT_SYMBOL_GPL(irq_find_matching_fwnode);
> 
> at the end of this function as well?

Well spotted! I'll update the v2 branch.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
@ 2015-10-13  7:35       ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-13  7:35 UTC (permalink / raw)
  To: Suravee Suthikulpanit
  Cc: Thomas Gleixner, Jiang Liu, Jason Cooper, Rafael J. Wysocki,
	linux-acpi, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi,
	Tomasz Nowicki, Hanjun Guo, Graeme Gregory, Jake Oshins

On Mon, 12 Oct 2015 13:31:09 -0500
Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> wrote:

Hi Suravee,

> [RESEND] Not sure if the email went out the first time.
> 
> Hi Marc,
> 
> On 10/6/15 12:36, Marc Zyngier wrote:
> > So far, our irq domains are still looked up by device node.
> > Let's change this and allow a domain to be looked up using
> > a fwnode_handle pointer.
> >
> > The existing interfaces are preserved with a couple of helpers.
> >
> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> > ---
> >   include/linux/irqdomain.h | 11 +++++++++--
> >   kernel/irq/irqdomain.c    | 14 ++++++--------
> >   2 files changed, 15 insertions(+), 10 deletions(-)
> >
> > diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> > index 2f508f4..607c185 100644
> > --- a/include/linux/irqdomain.h
> > +++ b/include/linux/irqdomain.h
> > @@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> >   					 irq_hw_number_t first_hwirq,
> >   					 const struct irq_domain_ops *ops,
> >   					 void *host_data);
> > -extern struct irq_domain *irq_find_matching_host(struct device_node *node,
> > -						 enum irq_domain_bus_token bus_token);
> > +extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> > +						   enum irq_domain_bus_token bus_token);
> >   extern void irq_set_default_host(struct irq_domain *host);
> >
> > +static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
> > +							enum irq_domain_bus_token bus_token)
> > +{
> > +	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
> > +					bus_token);
> > +}
> > +
> >   static inline struct irq_domain *irq_find_host(struct device_node *node)
> >   {
> >   	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> > index 1aee5c1..10b6105 100644
> > --- a/kernel/irq/irqdomain.c
> > +++ b/kernel/irq/irqdomain.c
> > @@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> >   EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
> >
> >   /**
> > - * irq_find_matching_host() - Locates a domain for a given device node
> > - * @node: device-tree node of the interrupt controller
> > + * irq_find_matching_fwnode() - Locates a domain for a given fwnode
> > + * @fwnode: FW descriptor of the interrupt controller
> >    * @bus_token: domain-specific data
> >    */
> > -struct irq_domain *irq_find_matching_host(struct device_node *node,
> > -					  enum irq_domain_bus_token bus_token)
> > +struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> > +					    enum irq_domain_bus_token bus_token)
> >   {
> >   	struct irq_domain *h, *found = NULL;
> >   	int rc;
> > @@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
> >   	 */
> >   	mutex_lock(&irq_domain_mutex);
> >   	list_for_each_entry(h, &irq_domain_list, link) {
> > -		struct device_node *of_node;
> > -		of_node = irq_domain_get_of_node(h);
> >   		if (h->ops->match)
> > -			rc = h->ops->match(h, node, bus_token);
> > +			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
> >   		else
> > -			rc = ((of_node != NULL) && (of_node == node) &&
> > +			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
> >   			      ((bus_token == DOMAIN_BUS_ANY) ||
> >   			       (h->bus_token == bus_token)));
> >
> >
> 
> In the kernel/irq/irq_domain.c, shouldn't you also change the export 
> symbol from:
> 
>      EXPORT_SYMBOL_GPL(irq_find_matching_host);
> 
> to:
> 
>      EXPORT_SYMBOL_GPL(irq_find_matching_fwnode);
> 
> at the end of this function as well?

Well spotted! I'll update the v2 branch.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode
@ 2015-10-13  7:35       ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-13  7:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 12 Oct 2015 13:31:09 -0500
Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> wrote:

Hi Suravee,

> [RESEND] Not sure if the email went out the first time.
> 
> Hi Marc,
> 
> On 10/6/15 12:36, Marc Zyngier wrote:
> > So far, our irq domains are still looked up by device node.
> > Let's change this and allow a domain to be looked up using
> > a fwnode_handle pointer.
> >
> > The existing interfaces are preserved with a couple of helpers.
> >
> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> > ---
> >   include/linux/irqdomain.h | 11 +++++++++--
> >   kernel/irq/irqdomain.c    | 14 ++++++--------
> >   2 files changed, 15 insertions(+), 10 deletions(-)
> >
> > diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> > index 2f508f4..607c185 100644
> > --- a/include/linux/irqdomain.h
> > +++ b/include/linux/irqdomain.h
> > @@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> >   					 irq_hw_number_t first_hwirq,
> >   					 const struct irq_domain_ops *ops,
> >   					 void *host_data);
> > -extern struct irq_domain *irq_find_matching_host(struct device_node *node,
> > -						 enum irq_domain_bus_token bus_token);
> > +extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> > +						   enum irq_domain_bus_token bus_token);
> >   extern void irq_set_default_host(struct irq_domain *host);
> >
> > +static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
> > +							enum irq_domain_bus_token bus_token)
> > +{
> > +	return irq_find_matching_fwnode(node ? &node->fwnode : NULL,
> > +					bus_token);
> > +}
> > +
> >   static inline struct irq_domain *irq_find_host(struct device_node *node)
> >   {
> >   	return irq_find_matching_host(node, DOMAIN_BUS_ANY);
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> > index 1aee5c1..10b6105 100644
> > --- a/kernel/irq/irqdomain.c
> > +++ b/kernel/irq/irqdomain.c
> > @@ -191,12 +191,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> >   EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
> >
> >   /**
> > - * irq_find_matching_host() - Locates a domain for a given device node
> > - * @node: device-tree node of the interrupt controller
> > + * irq_find_matching_fwnode() - Locates a domain for a given fwnode
> > + * @fwnode: FW descriptor of the interrupt controller
> >    * @bus_token: domain-specific data
> >    */
> > -struct irq_domain *irq_find_matching_host(struct device_node *node,
> > -					  enum irq_domain_bus_token bus_token)
> > +struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
> > +					    enum irq_domain_bus_token bus_token)
> >   {
> >   	struct irq_domain *h, *found = NULL;
> >   	int rc;
> > @@ -212,12 +212,10 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,
> >   	 */
> >   	mutex_lock(&irq_domain_mutex);
> >   	list_for_each_entry(h, &irq_domain_list, link) {
> > -		struct device_node *of_node;
> > -		of_node = irq_domain_get_of_node(h);
> >   		if (h->ops->match)
> > -			rc = h->ops->match(h, node, bus_token);
> > +			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
> >   		else
> > -			rc = ((of_node != NULL) && (of_node == node) &&
> > +			rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
> >   			      ((bus_token == DOMAIN_BUS_ANY) ||
> >   			       (h->bus_token == bus_token)));
> >
> >
> 
> In the kernel/irq/irq_domain.c, shouldn't you also change the export 
> symbol from:
> 
>      EXPORT_SYMBOL_GPL(irq_find_matching_host);
> 
> to:
> 
>      EXPORT_SYMBOL_GPL(irq_find_matching_fwnode);
> 
> at the end of this function as well?

Well spotted! I'll update the v2 branch.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH 00/16] Divorcing irqdomain and device_node
  2015-10-12 20:38     ` Rafael J. Wysocki
@ 2015-10-13  8:24       ` Marc Zyngier
  -1 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-13  8:24 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner
  Cc: Jiang Liu, Jason Cooper, linux-acpi, linux-arm-kernel,
	linux-kernel, Lorenzo Pieralisi, Tomasz Nowicki, Hanjun Guo,
	Suravee Suthikulpanit, Graeme Gregory, Jake Oshins

On 12/10/15 21:38, Rafael J. Wysocki wrote:
> On Sunday, October 11, 2015 11:01:17 PM Thomas Gleixner wrote:
>> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>>> [This patch series used to be called "Making the generic ACPI GSI
>>> layer irqdomain aware", but as I've radically changed my approach to
>>> this problem, I've decided to reset the counters...]
>>>
>>> The irqdomain code is not entierely ACPI friendly, as it has some
>>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>>> to scare the ARM ACPI developpers which end up with their own version
>>> of the square wheel. And some of the ramifications actually run deeper
>>> than initially expected.
>>>
>>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>>> instead of 'struct device_node' as the identifier for a domain
>>> (compatibility interfaces are of course added). It also introduces a
>>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>>> directly use to configure interrupts, and allow the ACPI GSI code to
>>> be plugged into this.
>>>
>>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>>> originally intended, and rework the MSI code to also move away from
>>> using device nodes when using irqdomains.
>>>
>>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>>> enabled platforms, having very little changes made to the actual
>>> drivers (other than the probing infrastructure). Because we keep the
>>> flow of information between the various layers identical between ACPI
>>> and DT, we immediately benefit from the existing infrastructure.
>>>
>>> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
>>>
>>> Marc Zyngier (16):
>>>   irqdomain: Use an accessor for the of_node field
>>>   irqdomain: Convert irqdomain->of_node to fwnode
>>>   irqdomain: Allow irq domain lookup by fwnode
>>>   irqdomain: Introduce a firmware-specific IRQ specifier structure
>>>   irqchip: Convert all alloc/xlate users from of_node to fwnode
>>>   irqdomain: Introduce irq_create_fwspec_mapping
>>>   irqdomain: Introduce irq_domain_create_{linear,tree}
>>>   irqdomain: Add a fwnode_handle allocator
>>>   acpi/gsi: Always perform an irq domain lookup
>>>   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>>   irqchip/gic: Get rid of gic_init_bases()
>>>   irqchip/gic: Switch ACPI support to stacked domains
>>>   irqchip/gic: Kill the xlate method
>>>   acpi/gsi: Cleanup acpi_register_gsi
>>>   irqdomain: Introduce irq_domain_create_hierarchy
>>>   irqdomain/msi: Use fwnode instead of of_node
>>
>> I really like this one way better than the previous attempts and I
>> couldn't find any real issue when going through them with a fine comb.
>>
>> I'd like to get that into 4.4, so I have to ask for the opinion of
>> ACPI folks. Having an ack on those patches would be nice.
> 
> I've ACKed the generic ones, please let me know if I missed any of them.
> 
> The rest seems to be ARM-specific ...

Thanks a lot Rafael.

I'll repost the series today with a couple of fixes so that Thomas can
stick it into -next.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH 00/16] Divorcing irqdomain and device_node
@ 2015-10-13  8:24       ` Marc Zyngier
  0 siblings, 0 replies; 87+ messages in thread
From: Marc Zyngier @ 2015-10-13  8:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/10/15 21:38, Rafael J. Wysocki wrote:
> On Sunday, October 11, 2015 11:01:17 PM Thomas Gleixner wrote:
>> On Tue, 6 Oct 2015, Marc Zyngier wrote:
>>> [This patch series used to be called "Making the generic ACPI GSI
>>> layer irqdomain aware", but as I've radically changed my approach to
>>> this problem, I've decided to reset the counters...]
>>>
>>> The irqdomain code is not entierely ACPI friendly, as it has some
>>> built-in knowledge of the device-tree. Nothing too harmful, but enough
>>> to scare the ARM ACPI developpers which end up with their own version
>>> of the square wheel. And some of the ramifications actually run deeper
>>> than initially expected.
>>>
>>> This series adapts the irqdomain code to use 'struct fwnode_handle'
>>> instead of 'struct device_node' as the identifier for a domain
>>> (compatibility interfaces are of course added). It also introduces a
>>> generic IRQ specifier that firmware interfaces (DT or ACPI) can
>>> directly use to configure interrupts, and allow the ACPI GSI code to
>>> be plugged into this.
>>>
>>> As examples, we convert the ARM GIC ACPI support to use irqdomains as
>>> originally intended, and rework the MSI code to also move away from
>>> using device nodes when using irqdomains.
>>>
>>> Overall, this gives us a way to use irqdomains on both DT and ACPI
>>> enabled platforms, having very little changes made to the actual
>>> drivers (other than the probing infrastructure). Because we keep the
>>> flow of information between the various layers identical between ACPI
>>> and DT, we immediately benefit from the existing infrastructure.
>>>
>>> This has been test-booted on Juno, is based on 4.3-rc4, and available at:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/irq-domain-fwnode-v1
>>>
>>> Marc Zyngier (16):
>>>   irqdomain: Use an accessor for the of_node field
>>>   irqdomain: Convert irqdomain->of_node to fwnode
>>>   irqdomain: Allow irq domain lookup by fwnode
>>>   irqdomain: Introduce a firmware-specific IRQ specifier structure
>>>   irqchip: Convert all alloc/xlate users from of_node to fwnode
>>>   irqdomain: Introduce irq_create_fwspec_mapping
>>>   irqdomain: Introduce irq_domain_create_{linear,tree}
>>>   irqdomain: Add a fwnode_handle allocator
>>>   acpi/gsi: Always perform an irq domain lookup
>>>   acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer
>>>   irqchip/gic: Get rid of gic_init_bases()
>>>   irqchip/gic: Switch ACPI support to stacked domains
>>>   irqchip/gic: Kill the xlate method
>>>   acpi/gsi: Cleanup acpi_register_gsi
>>>   irqdomain: Introduce irq_domain_create_hierarchy
>>>   irqdomain/msi: Use fwnode instead of of_node
>>
>> I really like this one way better than the previous attempts and I
>> couldn't find any real issue when going through them with a fine comb.
>>
>> I'd like to get that into 4.4, so I have to ask for the opinion of
>> ACPI folks. Having an ack on those patches would be nice.
> 
> I've ACKed the generic ones, please let me know if I missed any of them.
> 
> The rest seems to be ARM-specific ...

Thanks a lot Rafael.

I'll repost the series today with a couple of fixes so that Thomas can
stick it into -next.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

end of thread, other threads:[~2015-10-13  8:24 UTC | newest]

Thread overview: 87+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-06 17:36 [PATCH 00/16] Divorcing irqdomain and device_node Marc Zyngier
2015-10-06 17:36 ` Marc Zyngier
2015-10-06 17:36 ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 01/16] irqdomain: Use an accessor for the of_node field Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-09 14:24   ` Thomas Gleixner
2015-10-09 14:24     ` Thomas Gleixner
2015-10-09 14:31     ` Marc Zyngier
2015-10-09 14:31       ` Marc Zyngier
2015-10-12  6:04   ` Hanjun Guo
2015-10-12  6:04     ` Hanjun Guo
2015-10-12  9:30     ` Marc Zyngier
2015-10-12  9:30       ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 02/16] irqdomain: Convert irqdomain->of_node to fwnode Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 03/16] irqdomain: Allow irq domain lookup by fwnode Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-12 18:31   ` Suravee Suthikulpanit
2015-10-12 18:31     ` Suravee Suthikulpanit
2015-10-12 18:31     ` Suravee Suthikulpanit
2015-10-13  7:35     ` Marc Zyngier
2015-10-13  7:35       ` Marc Zyngier
2015-10-13  7:35       ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 04/16] irqdomain: Introduce a firmware-specific IRQ specifier structure Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 05/16] irqchip: Convert all alloc/xlate users from of_node to fwnode Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-12  6:44   ` Hanjun Guo
2015-10-12  6:44     ` Hanjun Guo
2015-10-06 17:36 ` [PATCH 06/16] irqdomain: Introduce irq_create_fwspec_mapping Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 07/16] irqdomain: Introduce irq_domain_create_{linear,tree} Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 08/16] irqdomain: Add a fwnode_handle allocator Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-12 20:32   ` Rafael J. Wysocki
2015-10-12 20:32     ` Rafael J. Wysocki
2015-10-06 17:36 ` [PATCH 09/16] acpi/gsi: Always perform an irq domain lookup Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-12 20:34   ` Rafael J. Wysocki
2015-10-12 20:34     ` Rafael J. Wysocki
2015-10-06 17:36 ` [PATCH 10/16] acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-12 20:36   ` Rafael J. Wysocki
2015-10-12 20:36     ` Rafael J. Wysocki
2015-10-06 17:36 ` [PATCH 11/16] irqchip/gic: Get rid of gic_init_bases() Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 12/16] irqchip/gic: Switch ACPI support to stacked domains Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 13/16] irqchip/gic: Kill the xlate method Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 14/16] acpi/gsi: Cleanup acpi_register_gsi Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-12 20:37   ` Rafael J. Wysocki
2015-10-12 20:37     ` Rafael J. Wysocki
2015-10-06 17:36 ` [PATCH 15/16] irqdomain: Introduce irq_domain_create_hierarchy Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36 ` [PATCH 16/16] irqdomain/msi: Use fwnode instead of of_node Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-06 17:36   ` Marc Zyngier
2015-10-11 21:01 ` [PATCH 00/16] Divorcing irqdomain and device_node Thomas Gleixner
2015-10-11 21:01   ` Thomas Gleixner
2015-10-12  2:40   ` Hanjun Guo
2015-10-12  2:40     ` Hanjun Guo
2015-10-12  7:09     ` Hanjun Guo
2015-10-12  7:09       ` Hanjun Guo
2015-10-12 10:31   ` Marc Zyngier
2015-10-12 10:31     ` Marc Zyngier
2015-10-12 20:38   ` Rafael J. Wysocki
2015-10-12 20:38     ` Rafael J. Wysocki
2015-10-13  8:24     ` Marc Zyngier
2015-10-13  8:24       ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.