diff mbox

[RFC,13/14] irq_domain: Remove 'new' irq_domain in favour of the ppc one

Message ID 1326313337-24603-14-git-send-email-grant.likely@secretlab.ca (mailing list archive)
State Superseded
Headers show

Commit Message

Grant Likely Jan. 11, 2012, 8:22 p.m. UTC
This patch removes the simplistic implementation of irq_domains and enables
the powerpc infrastructure for all irq_domain users.  The powerpc
infrastructure includes support for complex mappings between Linux and
hardware irq numbers, and can manage allocation of irq_descs.

This patch also converts the few users of irq_domain_add()/irq_domain_del()
to call irq_domain_add_legacy() instead.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/arm/common/gic.c               |   83 +++++++-----------
 arch/arm/common/vic.c               |   16 +---
 arch/arm/include/asm/hardware/gic.h |    4 +-
 arch/arm/include/asm/hardware/vic.h |    2 +
 arch/arm/mach-exynos/common.c       |    2 +-
 arch/arm/mach-versatile/core.c      |    5 +-
 drivers/mfd/twl-core.c              |   12 +--
 include/linux/irqdomain.h           |   42 +---------
 kernel/irq/irqdomain.c              |  161 +++--------------------------------
 9 files changed, 64 insertions(+), 263 deletions(-)

Comments

Rob Herring Jan. 11, 2012, 9:15 p.m. UTC | #1
Grant,

On 01/11/2012 02:22 PM, Grant Likely wrote:
> This patch removes the simplistic implementation of irq_domains and enables
> the powerpc infrastructure for all irq_domain users.  The powerpc
> infrastructure includes support for complex mappings between Linux and
> hardware irq numbers, and can manage allocation of irq_descs.
> 
> This patch also converts the few users of irq_domain_add()/irq_domain_del()
> to call irq_domain_add_legacy() instead.

So what is the non-legacy way? Legacy implies we don't want to do it
that way. I guess until we remove all non-DT platforms with GIC we are
stuck with legacy. That seems like it could be a ways out until we get
there.

Rob

> 
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
>  arch/arm/common/gic.c               |   83 +++++++-----------
>  arch/arm/common/vic.c               |   16 +---
>  arch/arm/include/asm/hardware/gic.h |    4 +-
>  arch/arm/include/asm/hardware/vic.h |    2 +
>  arch/arm/mach-exynos/common.c       |    2 +-
>  arch/arm/mach-versatile/core.c      |    5 +-
>  drivers/mfd/twl-core.c              |   12 +--
>  include/linux/irqdomain.h           |   42 +---------
>  kernel/irq/irqdomain.c              |  161 +++--------------------------------
>  9 files changed, 64 insertions(+), 263 deletions(-)
> 
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 156bc03..d839168 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -50,7 +50,6 @@ union gic_base {
>  };
>  
>  struct gic_chip_data {
> -	unsigned int irq_offset;
>  	union gic_base dist_base;
>  	union gic_base cpu_base;
>  #ifdef CONFIG_CPU_PM
> @@ -60,9 +59,7 @@ struct gic_chip_data {
>  	u32 __percpu *saved_ppi_enable;
>  	u32 __percpu *saved_ppi_conf;
>  #endif
> -#ifdef CONFIG_IRQ_DOMAIN
> -	struct irq_domain domain;
> -#endif
> +	struct irq_domain *domain;
>  	unsigned int gic_irqs;
>  #ifdef CONFIG_GIC_NON_BANKED
>  	void __iomem *(*get_base)(union gic_base *);
> @@ -281,7 +278,7 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
>  		irqnr = irqstat & ~0x1c00;
>  
>  		if (likely(irqnr > 15 && irqnr < 1021)) {
> -			irqnr = irq_domain_to_irq(&gic->domain, irqnr);
> +			irqnr = irq_find_mapping(gic->domain, irqnr);
>  			handle_IRQ(irqnr, regs);
>  			continue;
>  		}
> @@ -313,8 +310,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
>  	if (gic_irq == 1023)
>  		goto out;
>  
> -	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
> -	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
> +	cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
> +	if (unlikely(gic_irq < 32 || gic_irq > 1020))
>  		do_bad_IRQ(cascade_irq, desc);
>  	else
>  		generic_handle_irq(cascade_irq);
> @@ -347,10 +344,9 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>  
>  static void __init gic_dist_init(struct gic_chip_data *gic)
>  {
> -	unsigned int i, irq;
> +	unsigned int i;
>  	u32 cpumask;
>  	unsigned int gic_irqs = gic->gic_irqs;
> -	struct irq_domain *domain = &gic->domain;
>  	void __iomem *base = gic_data_dist_base(gic);
>  	u32 cpu = 0;
>  
> @@ -389,23 +385,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
>  	for (i = 32; i < gic_irqs; i += 32)
>  		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
>  
> -	/*
> -	 * Setup the Linux IRQ subsystem.
> -	 */
> -	irq_domain_for_each_irq(domain, i, irq) {
> -		if (i < 32) {
> -			irq_set_percpu_devid(irq);
> -			irq_set_chip_and_handler(irq, &gic_chip,
> -						 handle_percpu_devid_irq);
> -			set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
> -		} else {
> -			irq_set_chip_and_handler(irq, &gic_chip,
> -						 handle_fasteoi_irq);
> -			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
> -		}
> -		irq_set_chip_data(irq, gic);
> -	}
> -
>  	writel_relaxed(1, base + GIC_DIST_CTRL);
>  }
>  
> @@ -621,7 +600,23 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
>  }
>  #endif
>  
> -#ifdef CONFIG_OF
> +static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
> +				irq_hw_number_t hw)
> +{
> +	if (hw < 32) {
> +		irq_set_percpu_devid(irq);
> +		irq_set_chip_and_handler(irq, &gic_chip,
> +					 handle_percpu_devid_irq);
> +		set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
> +	} else {
> +		irq_set_chip_and_handler(irq, &gic_chip,
> +					 handle_fasteoi_irq);
> +		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
> +	}
> +	irq_set_chip_data(irq, d->host_data);
> +	return 0;
> +}
> +
>  static int gic_irq_domain_xlate(struct irq_domain *d,
>  				struct device_node *controller,
>  				const u32 *intspec, unsigned int intsize,
> @@ -642,26 +637,23 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
>  	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
>  	return 0;
>  }
> -#endif
>  
>  struct irq_domain_ops gic_irq_domain_ops = {
> -#ifdef CONFIG_OF
> +	.map = gic_irq_domain_map,
>  	.xlate = gic_irq_domain_xlate,
> -#endif
>  };
>  
>  void __init gic_init_bases(unsigned int gic_nr, int irq_start,
>  			   void __iomem *dist_base, void __iomem *cpu_base,
> -			   u32 percpu_offset)
> +			   u32 percpu_offset, struct device_node *node)
>  {
> +	irq_hw_number_t hwirq_base;
>  	struct gic_chip_data *gic;
> -	struct irq_domain *domain;
>  	int gic_irqs;
>  
>  	BUG_ON(gic_nr >= MAX_GIC_NR);
>  
>  	gic = &gic_data[gic_nr];
> -	domain = &gic->domain;
>  #ifdef CONFIG_GIC_NON_BANKED
>  	if (percpu_offset) { /* Frankein-GIC without banked registers... */
>  		unsigned int cpu;
> @@ -697,10 +689,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
>  	 * For primary GICs, skip over SGIs.
>  	 * For secondary GICs, skip over PPIs, too.
>  	 */
> -	domain->hwirq_base = 32;
> +	hwirq_base = 32;
>  	if (gic_nr == 0) {
>  		if ((irq_start & 31) > 0) {
> -			domain->hwirq_base = 16;
> +			hwirq_base = 16;
>  			if (irq_start != -1)
>  				irq_start = (irq_start & ~31) + 16;
>  		}
> @@ -716,17 +708,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
>  		gic_irqs = 1020;
>  	gic->gic_irqs = gic_irqs;
>  
> -	domain->nr_irq = gic_irqs - domain->hwirq_base;
> -	domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
> -					   numa_node_id());
> -	if (IS_ERR_VALUE(domain->irq_base)) {
> -		WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
> -		     irq_start);
> -		domain->irq_base = irq_start;
> -	}
> -	domain->host_data = gic;
> -	domain->ops = &gic_irq_domain_ops;
> -	irq_domain_add(domain);
> +	gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_start,
> +					    hwirq_base, &gic_irq_domain_ops);
> +	if (WARN_ON(!gic->domain))
> +		return;
> +	gic->domain->host_data = gic;
>  
>  	gic_chip.flags |= gic_arch_extn.flags;
>  	gic_dist_init(gic);
> @@ -771,7 +757,6 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)
>  	void __iomem *dist_base;
>  	u32 percpu_offset;
>  	int irq;
> -	struct irq_domain *domain = &gic_data[gic_cnt].domain;
>  
>  	if (WARN_ON(!node))
>  		return -ENODEV;
> @@ -785,9 +770,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)
>  	if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
>  		percpu_offset = 0;
>  
> -	domain->of_node = of_node_get(node);
> -
> -	gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset);
> +	gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
>  
>  	if (parent) {
>  		irq = irq_of_parse_and_map(node, 0);
> diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
> index dcb004a..b9b1827 100644
> --- a/arch/arm/common/vic.c
> +++ b/arch/arm/common/vic.c
> @@ -56,7 +56,7 @@ struct vic_device {
>  	u32		int_enable;
>  	u32		soft_int;
>  	u32		protect;
> -	struct irq_domain domain;
> +	struct irq_domain *domain;
>  };
>  
>  /* we cannot allocate memory when VICs are initially registered */
> @@ -192,14 +192,8 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
>  	v->resume_sources = resume_sources;
>  	v->irq = irq;
>  	vic_id++;
> -
> -	v->domain.irq_base = irq;
> -	v->domain.nr_irq = 32;
> -#ifdef CONFIG_OF_IRQ
> -	v->domain.of_node = of_node_get(node);
> -#endif /* CONFIG_OF */
> -	v->domain.ops = &irq_domain_simple_ops;
> -	irq_domain_add(&v->domain);
> +	v->domain = irq_domain_add_legacy(node, 32, irq, 0,
> +					  &irq_domain_simple_ops);
>  }
>  
>  static void vic_ack_irq(struct irq_data *d)
> @@ -348,7 +342,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
>  	vic_register(base, irq_start, 0, node);
>  }
>  
> -static void __init __vic_init(void __iomem *base, unsigned int irq_start,
> +void __init __vic_init(void __iomem *base, unsigned int irq_start,
>  			      u32 vic_sources, u32 resume_sources,
>  			      struct device_node *node)
>  {
> @@ -444,7 +438,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
>  	stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
>  	while (stat) {
>  		irq = ffs(stat) - 1;
> -		handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
> +		handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
>  		stat &= ~(1 << irq);
>  		handled = 1;
>  	}
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index 4bdfe00..4b1ce6c 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -39,7 +39,7 @@ struct device_node;
>  extern struct irq_chip gic_arch_extn;
>  
>  void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
> -		    u32 offset);
> +		    u32 offset, struct device_node *);
>  int gic_of_init(struct device_node *node, struct device_node *parent);
>  void gic_secondary_init(unsigned int);
>  void gic_handle_irq(struct pt_regs *regs);
> @@ -49,7 +49,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
>  static inline void gic_init(unsigned int nr, int start,
>  			    void __iomem *dist , void __iomem *cpu)
>  {
> -	gic_init_bases(nr, start, dist, cpu, 0);
> +	gic_init_bases(nr, start, dist, cpu, 0, NULL);
>  }
>  
>  #endif
> diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
> index f42ebd6..e14af1a 100644
> --- a/arch/arm/include/asm/hardware/vic.h
> +++ b/arch/arm/include/asm/hardware/vic.h
> @@ -47,6 +47,8 @@
>  struct device_node;
>  struct pt_regs;
>  
> +void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources,
> +		u32 resume_sources, struct device_node *node);
>  void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
>  int vic_of_init(struct device_node *node, struct device_node *parent);
>  void vic_handle_irq(struct pt_regs *regs);
> diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
> index 0f22997..b0cf428 100644
> --- a/arch/arm/mach-exynos/common.c
> +++ b/arch/arm/mach-exynos/common.c
> @@ -399,7 +399,7 @@ void __init exynos4_init_irq(void)
>  	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
>  
>  	if (!of_have_populated_dt())
> -		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset);
> +		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL);
>  #ifdef CONFIG_OF
>  	else
>  		of_irq_init(exynos4_dt_irq_match);
> diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
> index 02b7b93..e924f15 100644
> --- a/arch/arm/mach-versatile/core.c
> +++ b/arch/arm/mach-versatile/core.c
> @@ -98,8 +98,9 @@ static const struct of_device_id sic_of_match[] __initconst = {
>  
>  void __init versatile_init_irq(void)
>  {
> -	vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
> -	irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START);
> +	__vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0,
> +			of_find_matching_node_by_address(NULL, vic_of_match,
> +							 VERSATILE_VIC_BASE));
>  
>  	writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
>  
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index e04e04dd..aab236f 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -263,8 +263,6 @@ struct twl_client {
>  
>  static struct twl_client twl_modules[TWL_NUM_SLAVES];
>  
> -static struct irq_domain domain;
> -
>  /* mapping the module id to slave id and base address */
>  struct twl_mapping {
>  	unsigned char sid;	/* Slave ID */
> @@ -1225,14 +1223,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  
>  	pdata->irq_base = status;
>  	pdata->irq_end = pdata->irq_base + nr_irqs;
> -
> -	domain.irq_base = pdata->irq_base;
> -	domain.nr_irq = nr_irqs;
> -#ifdef CONFIG_OF_IRQ
> -	domain.of_node = of_node_get(node);
> -	domain.ops = &irq_domain_simple_ops;
> -#endif
> -	irq_domain_add(&domain);
> +	irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0,
> +			      &irq_domain_simple_ops);
>  
>  	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
>  		dev_dbg(&client->dev, "can't talk I2C?\n");
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 6fb3531..7c25e7c 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -116,20 +116,15 @@ struct irq_domain {
>  	void *host_data;
>  	irq_hw_number_t inval_irq;
>  
> -	unsigned int irq_base;
> -	unsigned int nr_irq;
> -	unsigned int hwirq_base;
> -
>  	/* Optional device node pointer */
>  	struct device_node *of_node;
>  };
>  
>  #ifdef CONFIG_IRQ_DOMAIN
> -#ifdef CONFIG_PPC
>  struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>  					 unsigned int size,
>  					 unsigned int first_irq,
> -					 unsigned int first_hwirq,
> +					 irq_hw_number_t first_hwirq,
>  					 struct irq_domain_ops *ops);
>  struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
>  					 unsigned int size,
> @@ -146,9 +141,8 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
>  				struct device_node *of_node,
>  				struct irq_domain_ops *ops)
>  {
> -	return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS-1, 1, 1, ops);
> +	return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops);
>  }
> -
>  extern struct irq_domain *irq_find_host(struct device_node *node);
>  extern void irq_set_default_host(struct irq_domain *host);
>  extern void irq_set_virq_count(unsigned int count);
> @@ -167,38 +161,7 @@ extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host,
>  extern unsigned int irq_linear_revmap(struct irq_domain *host,
>  				      irq_hw_number_t hwirq);
>  
> -#else /* CONFIG_PPC */
> -
> -/**
> - * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
> - *
> - * Returns the linux irq number associated with a hardware irq.  By default,
> - * the mapping is irq == domain->irq_base + hwirq, but this mapping can
> - * be overridden if the irq_domain implements a .to_irq() hook.
> - */
> -static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
> -					     unsigned long hwirq)
> -{
> -	if (d->ops->to_irq)
> -		return d->ops->to_irq(d, hwirq);
> -	if (WARN_ON(hwirq < d->hwirq_base))
> -		return 0;
> -	return d->irq_base + hwirq - d->hwirq_base;
> -}
> -
> -#define irq_domain_for_each_hwirq(d, hw) \
> -	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
> -
> -#define irq_domain_for_each_irq(d, hw, irq) \
> -	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
> -	     hw < d->hwirq_base + d->nr_irq; \
> -	     hw++, irq = irq_domain_to_irq(d, hw))
> -
> -extern void irq_domain_add(struct irq_domain *domain);
> -extern void irq_domain_del(struct irq_domain *domain);
> -
>  extern struct irq_domain_ops irq_domain_simple_ops;
> -
>  #if defined(CONFIG_OF_IRQ)
>  extern void irq_domain_add_simple(struct device_node *controller, int irq_base);
>  extern void irq_domain_generate_simple(const struct of_device_id *match,
> @@ -207,7 +170,6 @@ extern void irq_domain_generate_simple(const struct of_device_id *match,
>  static inline void irq_domain_generate_simple(const struct of_device_id *match,
>  					u64 phys_base, unsigned int irq_start) { }
>  #endif /* !CONFIG_OF_IRQ */
> -#endif /* !CONFIG_PPC */
>  #endif /* CONFIG_IRQ_DOMAIN */
>  
>  #endif /* _LINUX_IRQDOMAIN_H */
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index d4759d0..b90a32e 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -11,7 +11,6 @@
>  static LIST_HEAD(irq_domain_list);
>  static DEFINE_MUTEX(irq_domain_mutex);
>  
> -#ifdef CONFIG_PPC
>  static DEFINE_MUTEX(revmap_trees_mutex);
>  static unsigned int irq_virq_count = NR_IRQS;
>  static struct irq_domain *irq_default_domain;
> @@ -79,7 +78,7 @@ static struct irq_domain *irq_domain_add(struct device_node *of_node,
>  struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>  					 unsigned int size,
>  					 unsigned int first_irq,
> -					 unsigned int first_hwirq,
> +					 irq_hw_number_t first_hwirq,
>  					 struct irq_domain_ops *ops)
>  {
>  	struct irq_domain *domain;
> @@ -661,124 +660,11 @@ static int __init irq_debugfs_init(void)
>  __initcall(irq_debugfs_init);
>  #endif /* CONFIG_VIRQ_DEBUG */
>  
> -#else /* CONFIG_PPC */
> -
> -/**
> - * irq_domain_add() - Register an irq_domain
> - * @domain: ptr to initialized irq_domain structure
> - *
> - * Registers an irq_domain structure.  The irq_domain must at a minimum be
> - * initialized with an ops structure pointer, and either a ->to_irq hook or
> - * a valid irq_base value.  Everything else is optional.
> - */
> -void irq_domain_add(struct irq_domain *domain)
> -{
> -	struct irq_data *d;
> -	int hwirq, irq;
> -
> -	/*
> -	 * This assumes that the irq_domain owner has already allocated
> -	 * the irq_descs.  This block will be removed when support for dynamic
> -	 * allocation of irq_descs is added to irq_domain.
> -	 */
> -	irq_domain_for_each_irq(domain, hwirq, irq) {
> -		d = irq_get_irq_data(irq);
> -		if (!d) {
> -			WARN(1, "error: assigning domain to non existant irq_desc");
> -			return;
> -		}
> -		if (d->domain) {
> -			/* things are broken; just report, don't clean up */
> -			WARN(1, "error: irq_desc already assigned to a domain");
> -			return;
> -		}
> -		d->domain = domain;
> -		d->hwirq = hwirq;
> -	}
> -
> -	mutex_lock(&irq_domain_mutex);
> -	list_add(&domain->link, &irq_domain_list);
> -	mutex_unlock(&irq_domain_mutex);
> -}
> -
> -/**
> - * irq_domain_del() - Unregister an irq_domain
> - * @domain: ptr to registered irq_domain.
> - */
> -void irq_domain_del(struct irq_domain *domain)
> -{
> -	struct irq_data *d;
> -	int hwirq, irq;
> -
> -	mutex_lock(&irq_domain_mutex);
> -	list_del(&domain->link);
> -	mutex_unlock(&irq_domain_mutex);
> -
> -	/* Clear the irq_domain assignments */
> -	irq_domain_for_each_irq(domain, hwirq, irq) {
> -		d = irq_get_irq_data(irq);
> -		d->domain = NULL;
> -	}
> -}
> -
> -#if defined(CONFIG_OF_IRQ)
> -/**
> - * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
> - *
> - * Used by the device tree interrupt mapping code to translate a device tree
> - * interrupt specifier to a valid linux irq number.  Returns either a valid
> - * linux IRQ number or 0.
> - *
> - * When the caller no longer need the irq number returned by this function it
> - * should arrange to call irq_dispose_mapping().
> - */
> -unsigned int irq_create_of_mapping(struct device_node *controller,
> -				   const u32 *intspec, unsigned int intsize)
> +int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
> +			  irq_hw_number_t hwirq)
>  {
> -	struct irq_domain *domain;
> -	unsigned long hwirq;
> -	unsigned int irq, type;
> -	int rc = -EINVAL;
> -
> -	/* Find a domain which can translate the irq spec */
> -	mutex_lock(&irq_domain_mutex);
> -	list_for_each_entry(domain, &irq_domain_list, link) {
> -		if (!domain->ops->xlate)
> -			continue;
> -		rc = domain->ops->xlate(domain, controller,
> -					intspec, intsize, &hwirq, &type);
> -		if (rc == 0)
> -			break;
> -	}
> -	mutex_unlock(&irq_domain_mutex);
> -
> -	if (rc != 0)
> -		return 0;
> -
> -	irq = irq_domain_to_irq(domain, hwirq);
> -	if (type != IRQ_TYPE_NONE)
> -		irq_set_irq_type(irq, type);
> -	pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
> -		 controller->full_name, (int)hwirq, irq, type);
> -	return irq;
> -}
> -EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> -
> -/**
> - * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
> - * @irq: linux irq number to be discarded
> - *
> - * Calling this function indicates the caller no longer needs a reference to
> - * the linux irq number returned by a prior call to irq_create_of_mapping().
> - */
> -void irq_dispose_mapping(unsigned int irq)
> -{
> -	/*
> -	 * nothing yet; will be filled when support for dynamic allocation of
> -	 * irq_descs is added to irq_domain
> -	 */
> +	return 0;
>  }
> -EXPORT_SYMBOL_GPL(irq_dispose_mapping);
>  
>  int irq_domain_simple_xlate(struct irq_domain *d,
>  			    struct device_node *controller,
> @@ -789,10 +675,6 @@ int irq_domain_simple_xlate(struct irq_domain *d,
>  		return -EINVAL;
>  	if (intsize < 1)
>  		return -EINVAL;
> -	if (d->nr_irq && ((intspec[0] < d->hwirq_base) ||
> -	    (intspec[0] >= d->hwirq_base + d->nr_irq)))
> -		return -EINVAL;
> -
>  	*out_hwirq = intspec[0];
>  	*out_type = IRQ_TYPE_NONE;
>  	if (intsize > 1)
> @@ -800,23 +682,17 @@ int irq_domain_simple_xlate(struct irq_domain *d,
>  	return 0;
>  }
>  
> -/**
> - * irq_domain_create_simple() - Set up a 'simple' translation range
> - */
> +struct irq_domain_ops irq_domain_simple_ops = {
> +	.map = irq_domain_simple_map,
> +	.xlate = irq_domain_simple_xlate,
> +};
> +EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
> +
> +#ifdef CONFIG_OF_IRQ
>  void irq_domain_add_simple(struct device_node *controller, int irq_base)
>  {
> -	struct irq_domain *domain;
> -
> -	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
> -	if (!domain) {
> -		WARN_ON(1);
> -		return;
> -	}
> -
> -	domain->irq_base = irq_base;
> -	domain->of_node = of_node_get(controller);
> -	domain->ops = &irq_domain_simple_ops;
> -	irq_domain_add(domain);
> +	irq_domain_add_legacy(controller, 32, irq_base, 0,
> +			      &irq_domain_simple_ops);
>  }
>  EXPORT_SYMBOL_GPL(irq_domain_add_simple);
>  
> @@ -831,13 +707,4 @@ void irq_domain_generate_simple(const struct of_device_id *match,
>  		irq_domain_add_simple(node, irq_start);
>  }
>  EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
> -#endif /* CONFIG_OF_IRQ */
> -
> -struct irq_domain_ops irq_domain_simple_ops = {
> -#ifdef CONFIG_OF_IRQ
> -	.xlate = irq_domain_simple_xlate,
> -#endif /* CONFIG_OF_IRQ */
> -};
> -EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
> -
> -#endif /* !CONFIG_PPC */
> +#endif
Grant Likely Jan. 11, 2012, 9:27 p.m. UTC | #2
On Wed, Jan 11, 2012 at 2:15 PM, Rob Herring <robherring2@gmail.com> wrote:
> Grant,
>
> On 01/11/2012 02:22 PM, Grant Likely wrote:
>> This patch removes the simplistic implementation of irq_domains and enables
>> the powerpc infrastructure for all irq_domain users.  The powerpc
>> infrastructure includes support for complex mappings between Linux and
>> hardware irq numbers, and can manage allocation of irq_descs.
>>
>> This patch also converts the few users of irq_domain_add()/irq_domain_del()
>> to call irq_domain_add_legacy() instead.
>
> So what is the non-legacy way? Legacy implies we don't want to do it
> that way. I guess until we remove all non-DT platforms with GIC we are
> stuck with legacy. That seems like it could be a ways out until we get
> there.

Non-legacy is letting the irq_domain manage the irq_desc allocations.
Some of the controllers will be easy to convert, some will be more
difficult.  The primary thing that really blocks getting away from the
legacy method is anything that expects hardcoded #defined irq numbers.
 The goal is to convert all users over to the linear revmap method.

g.
Rob Herring Jan. 13, 2012, 12:31 a.m. UTC | #3
Adding lakml...

On 01/11/2012 03:27 PM, Grant Likely wrote:
> On Wed, Jan 11, 2012 at 2:15 PM, Rob Herring <robherring2@gmail.com> wrote:
>> Grant,
>>
>> On 01/11/2012 02:22 PM, Grant Likely wrote:
>>> This patch removes the simplistic implementation of irq_domains and enables
>>> the powerpc infrastructure for all irq_domain users.  The powerpc
>>> infrastructure includes support for complex mappings between Linux and
>>> hardware irq numbers, and can manage allocation of irq_descs.
>>>
>>> This patch also converts the few users of irq_domain_add()/irq_domain_del()
>>> to call irq_domain_add_legacy() instead.
>>
>> So what is the non-legacy way? Legacy implies we don't want to do it
>> that way. I guess until we remove all non-DT platforms with GIC we are
>> stuck with legacy. That seems like it could be a ways out until we get
>> there.
> 
> Non-legacy is letting the irq_domain manage the irq_desc allocations.
> Some of the controllers will be easy to convert, some will be more
> difficult.  The primary thing that really blocks getting away from the
> legacy method is anything that expects hardcoded #defined irq numbers.
>  The goal is to convert all users over to the linear revmap method.
> 

So I gave this a spin on highbank. I ran into a couple problems.

I had to revert "irqdesc: Consolidate irq reservation logic" which is in
your branch, but not this series. irq_alloc_desc_from was returning -EEXIST.

The GIC code did not work which I think is specific to using gic_of_init
which makes irq_start = -1. With that it still doesn't work. It dies in
gic_set_type... I've found one problem which I'll reply inline to, but I
think this is a dead end path anyway.

You have removed the irq_alloc_descs call from the GIC which is a step
backwards. Several of the ARM DT enabled platforms are at the point they
can fully support dynamic virq base for each irqchip. I changed the
domain from legacy to linear and got things working. The issue with
linear is for SPARSE_IRQ. The default behavior on ARM for SPARSE_IRQ is
all nr_irqs are allocated at boot time before any controller is
initialized. The only platform with a GIC and requiring SPARSE_IRQ is
shmobile, but it is also the only one that calls irq_alloc_desc
functions for it's interrupts. So I think we are okay there. The problem
occurs when enabling SPARSE_IRQ for a non-DT platform with a GIC and
with irqchips that don't call irq_alloc_desc for their irqs. IMHO, this
should be an okay trade-off. There's no advantage to enabling SPARSE_IRQ
on ARM for platforms that don't require it. All the platforms with a GIC
have active work to convert to DT (except shmobile which I think is
okay), so it's a temporary issue.

Rob
Grant Likely Jan. 13, 2012, 12:47 a.m. UTC | #4
On Thu, Jan 12, 2012 at 5:31 PM, Rob Herring <robherring2@gmail.com> wrote:
> Adding lakml...
>
> On 01/11/2012 03:27 PM, Grant Likely wrote:
>> On Wed, Jan 11, 2012 at 2:15 PM, Rob Herring <robherring2@gmail.com> wrote:
>>> Grant,
>>>
>>> On 01/11/2012 02:22 PM, Grant Likely wrote:
>>>> This patch removes the simplistic implementation of irq_domains and enables
>>>> the powerpc infrastructure for all irq_domain users.  The powerpc
>>>> infrastructure includes support for complex mappings between Linux and
>>>> hardware irq numbers, and can manage allocation of irq_descs.
>>>>
>>>> This patch also converts the few users of irq_domain_add()/irq_domain_del()
>>>> to call irq_domain_add_legacy() instead.
>>>
>>> So what is the non-legacy way? Legacy implies we don't want to do it
>>> that way. I guess until we remove all non-DT platforms with GIC we are
>>> stuck with legacy. That seems like it could be a ways out until we get
>>> there.
>>
>> Non-legacy is letting the irq_domain manage the irq_desc allocations.
>> Some of the controllers will be easy to convert, some will be more
>> difficult.  The primary thing that really blocks getting away from the
>> legacy method is anything that expects hardcoded #defined irq numbers.
>>  The goal is to convert all users over to the linear revmap method.
>>
>
> So I gave this a spin on highbank. I ran into a couple problems.
>
> I had to revert "irqdesc: Consolidate irq reservation logic" which is in
> your branch, but not this series. irq_alloc_desc_from was returning -EEXIST.

Hmmm... I thought I sorted that out.  Thanks for letting me know.

>
> The GIC code did not work which I think is specific to using gic_of_init
> which makes irq_start = -1. With that it still doesn't work. It dies in
> gic_set_type... I've found one problem which I'll reply inline to, but I
> think this is a dead end path anyway.

Haha, I'm not surprised.  That last patch was only compile tested on
platforms using the gic.  I'm not surprised that I flubbed it.

> You have removed the irq_alloc_descs call from the GIC which is a step
> backwards. Several of the ARM DT enabled platforms are at the point they
> can fully support dynamic virq base for each irqchip. I changed the
> domain from legacy to linear and got things working.
> The issue with

I hadn't actually intended to remove the irq_alloc_descs in this
patch.  That was a leftover hunk from when I was playing with going
straight to irq_domain_add_linear().  For this specific patch, I'll
put the alloc back in and test it that way.  A follow-on patch can do
a proper conversion to the linear revmap.

> linear is for SPARSE_IRQ. The default behavior on ARM for SPARSE_IRQ is
> all nr_irqs are allocated at boot time before any controller is
> initialized. The only platform with a GIC and requiring SPARSE_IRQ is
> shmobile, but it is also the only one that calls irq_alloc_desc
> functions for it's interrupts. So I think we are okay there. The problem
> occurs when enabling SPARSE_IRQ for a non-DT platform with a GIC and
> with irqchips that don't call irq_alloc_desc for their irqs. IMHO, this
> should be an okay trade-off. There's no advantage to enabling SPARSE_IRQ
> on ARM for platforms that don't require it. All the platforms with a GIC
> have active work to convert to DT (except shmobile which I think is
> okay), so it's a temporary issue.

Actually, I believe Thomas' long term goal is to always enable
SPARSE_IRQ and remove the option entirely, so it should still be
properly resolved. I'll take a look next week if I don't get to it
tomorrow.  I need to resurrect my vexpress qemu test environment so I
can test the permutations.

g.
Rob Herring Jan. 13, 2012, 12:53 a.m. UTC | #5
On 01/12/2012 06:47 PM, Grant Likely wrote:
> On Thu, Jan 12, 2012 at 5:31 PM, Rob Herring <robherring2@gmail.com> wrote:
>> Adding lakml...
>>
>> On 01/11/2012 03:27 PM, Grant Likely wrote:
>>> On Wed, Jan 11, 2012 at 2:15 PM, Rob Herring <robherring2@gmail.com> wrote:
>>>> Grant,
>>>>
>>>> On 01/11/2012 02:22 PM, Grant Likely wrote:
>>>>> This patch removes the simplistic implementation of irq_domains and enables
>>>>> the powerpc infrastructure for all irq_domain users.  The powerpc
>>>>> infrastructure includes support for complex mappings between Linux and
>>>>> hardware irq numbers, and can manage allocation of irq_descs.
>>>>>
>>>>> This patch also converts the few users of irq_domain_add()/irq_domain_del()
>>>>> to call irq_domain_add_legacy() instead.
>>>>
>>>> So what is the non-legacy way? Legacy implies we don't want to do it
>>>> that way. I guess until we remove all non-DT platforms with GIC we are
>>>> stuck with legacy. That seems like it could be a ways out until we get
>>>> there.
>>>
>>> Non-legacy is letting the irq_domain manage the irq_desc allocations.
>>> Some of the controllers will be easy to convert, some will be more
>>> difficult.  The primary thing that really blocks getting away from the
>>> legacy method is anything that expects hardcoded #defined irq numbers.
>>>  The goal is to convert all users over to the linear revmap method.
>>>
>>
>> So I gave this a spin on highbank. I ran into a couple problems.
>>
>> I had to revert "irqdesc: Consolidate irq reservation logic" which is in
>> your branch, but not this series. irq_alloc_desc_from was returning -EEXIST.
> 
> Hmmm... I thought I sorted that out.  Thanks for letting me know.
> 
>>
>> The GIC code did not work which I think is specific to using gic_of_init
>> which makes irq_start = -1. With that it still doesn't work. It dies in
>> gic_set_type... I've found one problem which I'll reply inline to, but I
>> think this is a dead end path anyway.
> 
> Haha, I'm not surprised.  That last patch was only compile tested on
> platforms using the gic.  I'm not surprised that I flubbed it.
> 
>> You have removed the irq_alloc_descs call from the GIC which is a step
>> backwards. Several of the ARM DT enabled platforms are at the point they
>> can fully support dynamic virq base for each irqchip. I changed the
>> domain from legacy to linear and got things working.
>> The issue with
> 
> I hadn't actually intended to remove the irq_alloc_descs in this
> patch.  That was a leftover hunk from when I was playing with going
> straight to irq_domain_add_linear().  For this specific patch, I'll
> put the alloc back in and test it that way.  A follow-on patch can do
> a proper conversion to the linear revmap.
> 
>> linear is for SPARSE_IRQ. The default behavior on ARM for SPARSE_IRQ is
>> all nr_irqs are allocated at boot time before any controller is
>> initialized. The only platform with a GIC and requiring SPARSE_IRQ is
>> shmobile, but it is also the only one that calls irq_alloc_desc
>> functions for it's interrupts. So I think we are okay there. The problem
>> occurs when enabling SPARSE_IRQ for a non-DT platform with a GIC and
>> with irqchips that don't call irq_alloc_desc for their irqs. IMHO, this
>> should be an okay trade-off. There's no advantage to enabling SPARSE_IRQ
>> on ARM for platforms that don't require it. All the platforms with a GIC
>> have active work to convert to DT (except shmobile which I think is
>> okay), so it's a temporary issue.
> 
> Actually, I believe Thomas' long term goal is to always enable
> SPARSE_IRQ and remove the option entirely, so it should still be
> properly resolved. I'll take a look next week if I don't get to it
> tomorrow.  I need to resurrect my vexpress qemu test environment so I
> can test the permutations.
> 

Agreed. I think that is the path to the removing include of mach/irqs.h
as well, and I have a patch series to do just that when SPARSE_IRQ is
enabled. It also has the problem of breaking platforms which don't NEED
to enable SPARSE_IRQ. I'll try to get it sent out soon.

Rob
Michael Bohan Jan. 17, 2012, 2:43 a.m. UTC | #6
On 1/12/2012 4:31 PM, Rob Herring wrote:
> You have removed the irq_alloc_descs call from the GIC which is a step
> backwards. Several of the ARM DT enabled platforms are at the point they
> can fully support dynamic virq base for each irqchip. I changed the
> domain from legacy to linear and got things working. The issue with
> linear is for SPARSE_IRQ. The default behavior on ARM for SPARSE_IRQ is
> all nr_irqs are allocated at boot time before any controller is
> initialized. The only platform with a GIC and requiring SPARSE_IRQ is
> shmobile, but it is also the only one that calls irq_alloc_desc
> functions for it's interrupts. So I think we are okay there. The problem
> occurs when enabling SPARSE_IRQ for a non-DT platform with a GIC and
> with irqchips that don't call irq_alloc_desc for their irqs. IMHO, this
> should be an okay trade-off. There's no advantage to enabling SPARSE_IRQ
> on ARM for platforms that don't require it. All the platforms with a GIC
> have active work to convert to DT (except shmobile which I think is
> okay), so it's a temporary issue.

I thought I would chime in here since this is very relevant to what 
we're doing on arm-msm. We are using Device Tree with the GIC. We also 
have several other interrupt chips, including one for a device that 
supports up to 32768 sparsely populated interrupts. Hence we are using 
SPARSE_IRQ to only allocate irq_descs on demand for this device.

To support this, I had to modify irq_domain_add() to not 'register' the 
domain. Eg. simply add the domain to the list, but do not initialize the 
hwirq values in the irq_data structure. This is because our irq_descs 
are allocated later based on Device Tree topology. This information is 
not available during of_irq_init().

But then I was left with the problem of managing irq_bases for multiple 
chip drivers. The problem with irq_alloc_desc() is that it doesn't allow 
you to allocate a range without allocating its corresponding resources. 
Meaning, I'd like to reserve a chunk of virqs, but not utilize any 
resources for them until I know they're necessary. This is where 
irq_domains comes in.

In order to support this properly, I decided it made sense to add a new 
API called irq_domain_find_free_range(). This walks the irq domains 
list, now sorted by domain->irq_base, to find the first available range 
of the size specified. Thus every irq chip then only needs to know the 
worst case number of interrupts it could ever support. The framework 
takes care of finding the specific virq base. And all of this 
information is available at of_irq_init() time. This all assumes that 
every chip driver registers with irq_domains.

I was planning on sending these patches out, but it seems like with 
Grant's patches, they may no longer be up to date. I was curious if any 
thought was given to supporting configurations like this the one I 
mentioned with the advent of these patches. I am happy to help test if 
you can steer me in the right direction.

Thanks,
Mike
Benjamin Herrenschmidt Jan. 17, 2012, 3:42 a.m. UTC | #7
On Mon, 2012-01-16 at 18:43 -0800, Michael Bohan wrote:
> 
> I was planning on sending these patches out, but it seems like with 
> Grant's patches, they may no longer be up to date. I was curious if any 
> thought was given to supporting configurations like this the one I 
> mentioned with the advent of these patches. I am happy to help test if 
> you can steer me in the right direction.

I haven't had a chance to look in detail at what Grant is doing in his
latest series, but the ppc domain scheme that he's basing it on has the
concept of sparse interrupt domains.

For these, we use a radix tree for the reverse map (we do not rely on a
linear range) and we "allocate" linux IRQ numbers on-demand as we create
mapping for individual HW interrupts.

Cheers,
Ben.
Grant Likely Jan. 18, 2012, 12:28 a.m. UTC | #8
On Mon, Jan 16, 2012 at 8:42 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Mon, 2012-01-16 at 18:43 -0800, Michael Bohan wrote:
>>
>> I was planning on sending these patches out, but it seems like with
>> Grant's patches, they may no longer be up to date. I was curious if any
>> thought was given to supporting configurations like this the one I
>> mentioned with the advent of these patches. I am happy to help test if
>> you can steer me in the right direction.
>
> I haven't had a chance to look in detail at what Grant is doing in his
> latest series, but the ppc domain scheme that he's basing it on has the
> concept of sparse interrupt domains.
>
> For these, we use a radix tree for the reverse map (we do not rely on a
> linear range) and we "allocate" linux IRQ numbers on-demand as we create
> mapping for individual HW interrupts.

My latest patches are primarily a direct port of the ppc code to be
generic for all architectures, and it does pretty much what you want.
As Ben suggests, you should look at the radix revmap code.  Use the
irq_domain_add_tree() function for creating the irq_domain, and there
is no need to even pre-allocate the number of hwirqs that you want to
support.  It uses a radix tree to manage arbitrary mappings from hwirq
number to linux numbers.

The other option is the linear map which maintains a static array with
one entry per hwirq number.  Use irq_domain_add_linear() to create one
and pass in the maximum number of hwirqs supported by the controller.
It will allocate an array of irq_desc* so that irq_descs can be
allocated dynamically.

It is also important to note that for both these revmaps, the actual
virq number is irrelevant.  The irq_domain is entirely responsible for
allocation and management.  There will be no need for a 'chunk of
virqs' assigned to an irq controller.

BTW: Ben, if you can carve out some time, I'd appreciate a look over
my series and make sure you're okay with it.  Once it's had some
testing by arm and ppc folks, I want to get it into linux-next.

g.
Benjamin Herrenschmidt Jan. 18, 2012, 2:16 a.m. UTC | #9
On Tue, 2012-01-17 at 17:28 -0700, Grant Likely wrote:
> BTW: Ben, if you can carve out some time, I'd appreciate a look over
> my series and make sure you're okay with it.  Once it's had some
> testing by arm and ppc folks, I want to get it into linux-next.

I intend to do so but not while I'm at LCA :-)

Cheers,
Ben.
Grant Likely Jan. 18, 2012, 6:50 a.m. UTC | #10
On Jan 17, 2012 7:17 PM, "Benjamin Herrenschmidt" <benh@kernel.crashing.org>
wrote:
>
> On Tue, 2012-01-17 at 17:28 -0700, Grant Likely wrote:
> > BTW: Ben, if you can carve out some time, I'd appreciate a look over
> > my series and make sure you're okay with it.  Once it's had some
> > testing by arm and ppc folks, I want to get it into linux-next.
>
> I intend to do so but not while I'm at LCA :-)

Pish... slacker.

:-p

No problem, enjoy LCA. One of these years I need to make it over there.

g.
diff mbox

Patch

diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 156bc03..d839168 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -50,7 +50,6 @@  union gic_base {
 };
 
 struct gic_chip_data {
-	unsigned int irq_offset;
 	union gic_base dist_base;
 	union gic_base cpu_base;
 #ifdef CONFIG_CPU_PM
@@ -60,9 +59,7 @@  struct gic_chip_data {
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
-#ifdef CONFIG_IRQ_DOMAIN
-	struct irq_domain domain;
-#endif
+	struct irq_domain *domain;
 	unsigned int gic_irqs;
 #ifdef CONFIG_GIC_NON_BANKED
 	void __iomem *(*get_base)(union gic_base *);
@@ -281,7 +278,7 @@  asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 		irqnr = irqstat & ~0x1c00;
 
 		if (likely(irqnr > 15 && irqnr < 1021)) {
-			irqnr = irq_domain_to_irq(&gic->domain, irqnr);
+			irqnr = irq_find_mapping(gic->domain, irqnr);
 			handle_IRQ(irqnr, regs);
 			continue;
 		}
@@ -313,8 +310,8 @@  static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	if (gic_irq == 1023)
 		goto out;
 
-	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
-	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
+	cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
+	if (unlikely(gic_irq < 32 || gic_irq > 1020))
 		do_bad_IRQ(cascade_irq, desc);
 	else
 		generic_handle_irq(cascade_irq);
@@ -347,10 +344,9 @@  void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 
 static void __init gic_dist_init(struct gic_chip_data *gic)
 {
-	unsigned int i, irq;
+	unsigned int i;
 	u32 cpumask;
 	unsigned int gic_irqs = gic->gic_irqs;
-	struct irq_domain *domain = &gic->domain;
 	void __iomem *base = gic_data_dist_base(gic);
 	u32 cpu = 0;
 
@@ -389,23 +385,6 @@  static void __init gic_dist_init(struct gic_chip_data *gic)
 	for (i = 32; i < gic_irqs; i += 32)
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
-	/*
-	 * Setup the Linux IRQ subsystem.
-	 */
-	irq_domain_for_each_irq(domain, i, irq) {
-		if (i < 32) {
-			irq_set_percpu_devid(irq);
-			irq_set_chip_and_handler(irq, &gic_chip,
-						 handle_percpu_devid_irq);
-			set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
-		} else {
-			irq_set_chip_and_handler(irq, &gic_chip,
-						 handle_fasteoi_irq);
-			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-		}
-		irq_set_chip_data(irq, gic);
-	}
-
 	writel_relaxed(1, base + GIC_DIST_CTRL);
 }
 
@@ -621,7 +600,23 @@  static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
-#ifdef CONFIG_OF
+static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				irq_hw_number_t hw)
+{
+	if (hw < 32) {
+		irq_set_percpu_devid(irq);
+		irq_set_chip_and_handler(irq, &gic_chip,
+					 handle_percpu_devid_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+	} else {
+		irq_set_chip_and_handler(irq, &gic_chip,
+					 handle_fasteoi_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+	irq_set_chip_data(irq, d->host_data);
+	return 0;
+}
+
 static int gic_irq_domain_xlate(struct irq_domain *d,
 				struct device_node *controller,
 				const u32 *intspec, unsigned int intsize,
@@ -642,26 +637,23 @@  static int gic_irq_domain_xlate(struct irq_domain *d,
 	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
 	return 0;
 }
-#endif
 
 struct irq_domain_ops gic_irq_domain_ops = {
-#ifdef CONFIG_OF
+	.map = gic_irq_domain_map,
 	.xlate = gic_irq_domain_xlate,
-#endif
 };
 
 void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 			   void __iomem *dist_base, void __iomem *cpu_base,
-			   u32 percpu_offset)
+			   u32 percpu_offset, struct device_node *node)
 {
+	irq_hw_number_t hwirq_base;
 	struct gic_chip_data *gic;
-	struct irq_domain *domain;
 	int gic_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
-	domain = &gic->domain;
 #ifdef CONFIG_GIC_NON_BANKED
 	if (percpu_offset) { /* Frankein-GIC without banked registers... */
 		unsigned int cpu;
@@ -697,10 +689,10 @@  void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 	 * For primary GICs, skip over SGIs.
 	 * For secondary GICs, skip over PPIs, too.
 	 */
-	domain->hwirq_base = 32;
+	hwirq_base = 32;
 	if (gic_nr == 0) {
 		if ((irq_start & 31) > 0) {
-			domain->hwirq_base = 16;
+			hwirq_base = 16;
 			if (irq_start != -1)
 				irq_start = (irq_start & ~31) + 16;
 		}
@@ -716,17 +708,11 @@  void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	domain->nr_irq = gic_irqs - domain->hwirq_base;
-	domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
-					   numa_node_id());
-	if (IS_ERR_VALUE(domain->irq_base)) {
-		WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
-		     irq_start);
-		domain->irq_base = irq_start;
-	}
-	domain->host_data = gic;
-	domain->ops = &gic_irq_domain_ops;
-	irq_domain_add(domain);
+	gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_start,
+					    hwirq_base, &gic_irq_domain_ops);
+	if (WARN_ON(!gic->domain))
+		return;
+	gic->domain->host_data = gic;
 
 	gic_chip.flags |= gic_arch_extn.flags;
 	gic_dist_init(gic);
@@ -771,7 +757,6 @@  int __init gic_of_init(struct device_node *node, struct device_node *parent)
 	void __iomem *dist_base;
 	u32 percpu_offset;
 	int irq;
-	struct irq_domain *domain = &gic_data[gic_cnt].domain;
 
 	if (WARN_ON(!node))
 		return -ENODEV;
@@ -785,9 +770,7 @@  int __init gic_of_init(struct device_node *node, struct device_node *parent)
 	if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
 		percpu_offset = 0;
 
-	domain->of_node = of_node_get(node);
-
-	gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset);
+	gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
 
 	if (parent) {
 		irq = irq_of_parse_and_map(node, 0);
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index dcb004a..b9b1827 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -56,7 +56,7 @@  struct vic_device {
 	u32		int_enable;
 	u32		soft_int;
 	u32		protect;
-	struct irq_domain domain;
+	struct irq_domain *domain;
 };
 
 /* we cannot allocate memory when VICs are initially registered */
@@ -192,14 +192,8 @@  static void __init vic_register(void __iomem *base, unsigned int irq,
 	v->resume_sources = resume_sources;
 	v->irq = irq;
 	vic_id++;
-
-	v->domain.irq_base = irq;
-	v->domain.nr_irq = 32;
-#ifdef CONFIG_OF_IRQ
-	v->domain.of_node = of_node_get(node);
-#endif /* CONFIG_OF */
-	v->domain.ops = &irq_domain_simple_ops;
-	irq_domain_add(&v->domain);
+	v->domain = irq_domain_add_legacy(node, 32, irq, 0,
+					  &irq_domain_simple_ops);
 }
 
 static void vic_ack_irq(struct irq_data *d)
@@ -348,7 +342,7 @@  static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
 	vic_register(base, irq_start, 0, node);
 }
 
-static void __init __vic_init(void __iomem *base, unsigned int irq_start,
+void __init __vic_init(void __iomem *base, unsigned int irq_start,
 			      u32 vic_sources, u32 resume_sources,
 			      struct device_node *node)
 {
@@ -444,7 +438,7 @@  static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
 	stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
 	while (stat) {
 		irq = ffs(stat) - 1;
-		handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
+		handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
 		stat &= ~(1 << irq);
 		handled = 1;
 	}
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 4bdfe00..4b1ce6c 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -39,7 +39,7 @@  struct device_node;
 extern struct irq_chip gic_arch_extn;
 
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
-		    u32 offset);
+		    u32 offset, struct device_node *);
 int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
 void gic_handle_irq(struct pt_regs *regs);
@@ -49,7 +49,7 @@  void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 static inline void gic_init(unsigned int nr, int start,
 			    void __iomem *dist , void __iomem *cpu)
 {
-	gic_init_bases(nr, start, dist, cpu, 0);
+	gic_init_bases(nr, start, dist, cpu, 0, NULL);
 }
 
 #endif
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index f42ebd6..e14af1a 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -47,6 +47,8 @@ 
 struct device_node;
 struct pt_regs;
 
+void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources,
+		u32 resume_sources, struct device_node *node);
 void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
 int vic_of_init(struct device_node *node, struct device_node *parent);
 void vic_handle_irq(struct pt_regs *regs);
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 0f22997..b0cf428 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -399,7 +399,7 @@  void __init exynos4_init_irq(void)
 	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
 
 	if (!of_have_populated_dt())
-		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset);
+		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL);
 #ifdef CONFIG_OF
 	else
 		of_irq_init(exynos4_dt_irq_match);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 02b7b93..e924f15 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -98,8 +98,9 @@  static const struct of_device_id sic_of_match[] __initconst = {
 
 void __init versatile_init_irq(void)
 {
-	vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
-	irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START);
+	__vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0,
+			of_find_matching_node_by_address(NULL, vic_of_match,
+							 VERSATILE_VIC_BASE));
 
 	writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e04e04dd..aab236f 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -263,8 +263,6 @@  struct twl_client {
 
 static struct twl_client twl_modules[TWL_NUM_SLAVES];
 
-static struct irq_domain domain;
-
 /* mapping the module id to slave id and base address */
 struct twl_mapping {
 	unsigned char sid;	/* Slave ID */
@@ -1225,14 +1223,8 @@  twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	pdata->irq_base = status;
 	pdata->irq_end = pdata->irq_base + nr_irqs;
-
-	domain.irq_base = pdata->irq_base;
-	domain.nr_irq = nr_irqs;
-#ifdef CONFIG_OF_IRQ
-	domain.of_node = of_node_get(node);
-	domain.ops = &irq_domain_simple_ops;
-#endif
-	irq_domain_add(&domain);
+	irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0,
+			      &irq_domain_simple_ops);
 
 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
 		dev_dbg(&client->dev, "can't talk I2C?\n");
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 6fb3531..7c25e7c 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -116,20 +116,15 @@  struct irq_domain {
 	void *host_data;
 	irq_hw_number_t inval_irq;
 
-	unsigned int irq_base;
-	unsigned int nr_irq;
-	unsigned int hwirq_base;
-
 	/* Optional device node pointer */
 	struct device_node *of_node;
 };
 
 #ifdef CONFIG_IRQ_DOMAIN
-#ifdef CONFIG_PPC
 struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 unsigned int size,
 					 unsigned int first_irq,
-					 unsigned int first_hwirq,
+					 irq_hw_number_t first_hwirq,
 					 struct irq_domain_ops *ops);
 struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
 					 unsigned int size,
@@ -146,9 +141,8 @@  static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
 				struct irq_domain_ops *ops)
 {
-	return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS-1, 1, 1, ops);
+	return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops);
 }
-
 extern struct irq_domain *irq_find_host(struct device_node *node);
 extern void irq_set_default_host(struct irq_domain *host);
 extern void irq_set_virq_count(unsigned int count);
@@ -167,38 +161,7 @@  extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host,
 extern unsigned int irq_linear_revmap(struct irq_domain *host,
 				      irq_hw_number_t hwirq);
 
-#else /* CONFIG_PPC */
-
-/**
- * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
- *
- * Returns the linux irq number associated with a hardware irq.  By default,
- * the mapping is irq == domain->irq_base + hwirq, but this mapping can
- * be overridden if the irq_domain implements a .to_irq() hook.
- */
-static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
-					     unsigned long hwirq)
-{
-	if (d->ops->to_irq)
-		return d->ops->to_irq(d, hwirq);
-	if (WARN_ON(hwirq < d->hwirq_base))
-		return 0;
-	return d->irq_base + hwirq - d->hwirq_base;
-}
-
-#define irq_domain_for_each_hwirq(d, hw) \
-	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
-
-#define irq_domain_for_each_irq(d, hw, irq) \
-	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
-	     hw < d->hwirq_base + d->nr_irq; \
-	     hw++, irq = irq_domain_to_irq(d, hw))
-
-extern void irq_domain_add(struct irq_domain *domain);
-extern void irq_domain_del(struct irq_domain *domain);
-
 extern struct irq_domain_ops irq_domain_simple_ops;
-
 #if defined(CONFIG_OF_IRQ)
 extern void irq_domain_add_simple(struct device_node *controller, int irq_base);
 extern void irq_domain_generate_simple(const struct of_device_id *match,
@@ -207,7 +170,6 @@  extern void irq_domain_generate_simple(const struct of_device_id *match,
 static inline void irq_domain_generate_simple(const struct of_device_id *match,
 					u64 phys_base, unsigned int irq_start) { }
 #endif /* !CONFIG_OF_IRQ */
-#endif /* !CONFIG_PPC */
 #endif /* CONFIG_IRQ_DOMAIN */
 
 #endif /* _LINUX_IRQDOMAIN_H */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index d4759d0..b90a32e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -11,7 +11,6 @@ 
 static LIST_HEAD(irq_domain_list);
 static DEFINE_MUTEX(irq_domain_mutex);
 
-#ifdef CONFIG_PPC
 static DEFINE_MUTEX(revmap_trees_mutex);
 static unsigned int irq_virq_count = NR_IRQS;
 static struct irq_domain *irq_default_domain;
@@ -79,7 +78,7 @@  static struct irq_domain *irq_domain_add(struct device_node *of_node,
 struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 unsigned int size,
 					 unsigned int first_irq,
-					 unsigned int first_hwirq,
+					 irq_hw_number_t first_hwirq,
 					 struct irq_domain_ops *ops)
 {
 	struct irq_domain *domain;
@@ -661,124 +660,11 @@  static int __init irq_debugfs_init(void)
 __initcall(irq_debugfs_init);
 #endif /* CONFIG_VIRQ_DEBUG */
 
-#else /* CONFIG_PPC */
-
-/**
- * irq_domain_add() - Register an irq_domain
- * @domain: ptr to initialized irq_domain structure
- *
- * Registers an irq_domain structure.  The irq_domain must at a minimum be
- * initialized with an ops structure pointer, and either a ->to_irq hook or
- * a valid irq_base value.  Everything else is optional.
- */
-void irq_domain_add(struct irq_domain *domain)
-{
-	struct irq_data *d;
-	int hwirq, irq;
-
-	/*
-	 * This assumes that the irq_domain owner has already allocated
-	 * the irq_descs.  This block will be removed when support for dynamic
-	 * allocation of irq_descs is added to irq_domain.
-	 */
-	irq_domain_for_each_irq(domain, hwirq, irq) {
-		d = irq_get_irq_data(irq);
-		if (!d) {
-			WARN(1, "error: assigning domain to non existant irq_desc");
-			return;
-		}
-		if (d->domain) {
-			/* things are broken; just report, don't clean up */
-			WARN(1, "error: irq_desc already assigned to a domain");
-			return;
-		}
-		d->domain = domain;
-		d->hwirq = hwirq;
-	}
-
-	mutex_lock(&irq_domain_mutex);
-	list_add(&domain->link, &irq_domain_list);
-	mutex_unlock(&irq_domain_mutex);
-}
-
-/**
- * irq_domain_del() - Unregister an irq_domain
- * @domain: ptr to registered irq_domain.
- */
-void irq_domain_del(struct irq_domain *domain)
-{
-	struct irq_data *d;
-	int hwirq, irq;
-
-	mutex_lock(&irq_domain_mutex);
-	list_del(&domain->link);
-	mutex_unlock(&irq_domain_mutex);
-
-	/* Clear the irq_domain assignments */
-	irq_domain_for_each_irq(domain, hwirq, irq) {
-		d = irq_get_irq_data(irq);
-		d->domain = NULL;
-	}
-}
-
-#if defined(CONFIG_OF_IRQ)
-/**
- * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
- *
- * Used by the device tree interrupt mapping code to translate a device tree
- * interrupt specifier to a valid linux irq number.  Returns either a valid
- * linux IRQ number or 0.
- *
- * When the caller no longer need the irq number returned by this function it
- * should arrange to call irq_dispose_mapping().
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
+int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
+			  irq_hw_number_t hwirq)
 {
-	struct irq_domain *domain;
-	unsigned long hwirq;
-	unsigned int irq, type;
-	int rc = -EINVAL;
-
-	/* Find a domain which can translate the irq spec */
-	mutex_lock(&irq_domain_mutex);
-	list_for_each_entry(domain, &irq_domain_list, link) {
-		if (!domain->ops->xlate)
-			continue;
-		rc = domain->ops->xlate(domain, controller,
-					intspec, intsize, &hwirq, &type);
-		if (rc == 0)
-			break;
-	}
-	mutex_unlock(&irq_domain_mutex);
-
-	if (rc != 0)
-		return 0;
-
-	irq = irq_domain_to_irq(domain, hwirq);
-	if (type != IRQ_TYPE_NONE)
-		irq_set_irq_type(irq, type);
-	pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
-		 controller->full_name, (int)hwirq, irq, type);
-	return irq;
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-
-/**
- * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
- * @irq: linux irq number to be discarded
- *
- * Calling this function indicates the caller no longer needs a reference to
- * the linux irq number returned by a prior call to irq_create_of_mapping().
- */
-void irq_dispose_mapping(unsigned int irq)
-{
-	/*
-	 * nothing yet; will be filled when support for dynamic allocation of
-	 * irq_descs is added to irq_domain
-	 */
+	return 0;
 }
-EXPORT_SYMBOL_GPL(irq_dispose_mapping);
 
 int irq_domain_simple_xlate(struct irq_domain *d,
 			    struct device_node *controller,
@@ -789,10 +675,6 @@  int irq_domain_simple_xlate(struct irq_domain *d,
 		return -EINVAL;
 	if (intsize < 1)
 		return -EINVAL;
-	if (d->nr_irq && ((intspec[0] < d->hwirq_base) ||
-	    (intspec[0] >= d->hwirq_base + d->nr_irq)))
-		return -EINVAL;
-
 	*out_hwirq = intspec[0];
 	*out_type = IRQ_TYPE_NONE;
 	if (intsize > 1)
@@ -800,23 +682,17 @@  int irq_domain_simple_xlate(struct irq_domain *d,
 	return 0;
 }
 
-/**
- * irq_domain_create_simple() - Set up a 'simple' translation range
- */
+struct irq_domain_ops irq_domain_simple_ops = {
+	.map = irq_domain_simple_map,
+	.xlate = irq_domain_simple_xlate,
+};
+EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
+
+#ifdef CONFIG_OF_IRQ
 void irq_domain_add_simple(struct device_node *controller, int irq_base)
 {
-	struct irq_domain *domain;
-
-	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
-	if (!domain) {
-		WARN_ON(1);
-		return;
-	}
-
-	domain->irq_base = irq_base;
-	domain->of_node = of_node_get(controller);
-	domain->ops = &irq_domain_simple_ops;
-	irq_domain_add(domain);
+	irq_domain_add_legacy(controller, 32, irq_base, 0,
+			      &irq_domain_simple_ops);
 }
 EXPORT_SYMBOL_GPL(irq_domain_add_simple);
 
@@ -831,13 +707,4 @@  void irq_domain_generate_simple(const struct of_device_id *match,
 		irq_domain_add_simple(node, irq_start);
 }
 EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
-#endif /* CONFIG_OF_IRQ */
-
-struct irq_domain_ops irq_domain_simple_ops = {
-#ifdef CONFIG_OF_IRQ
-	.xlate = irq_domain_simple_xlate,
-#endif /* CONFIG_OF_IRQ */
-};
-EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
-
-#endif /* !CONFIG_PPC */
+#endif