Re: [RFC 08/10] irqdomain: Refactor irq_domain_associate_many()

2013-06-18 Thread Grant Likely
On Tue, Jun 18, 2013 at 4:09 AM, Mike Qiu  wrote:
> 于 2013/6/10 8:49, Grant Likely 写道:
>
>> Originally, irq_domain_associate_many() was designed to unwind the
>> mapped irqs on a failure of any individual association. However, that
>> proved to be a problem with certain IRQ controllers. Some of them only
>> support a subset of irqs, and will fail when attempting to map a
>> reserved IRQ. In those cases we want to map as many IRQs as possible, so
>> instead it is better for irq_domain_associate_many() to make a
>> best-effort attempt to map irqs, but not fail if any or all of them
>> don't succeed. If a caller really cares about how many irqs got
>> associated, then it should instead go back and check that all of the
>> irqs is cares about were mapped.
>>
>> The original design open-coded the individual association code into the
>> body of irq_domain_associate_many(), but with no longer needing to
>> unwind associations, the code becomes simpler to split out
>> irq_domain_associate() to contain the bulk of the logic, and
>> irq_domain_associate_many() to be a simple loop wrapper.
>>
>> This patch also adds a new error check to the associate path to make
>> sure it isn't called for an irq larger than the controller can handle,
>> and adds locking so that the irq_domain_mutex is held while setting up a
>> new association.
>>
>> Signed-off-by: Grant Likely 
[...]
>> -int irq_domain_associate_many(struct irq_domain *domain, unsigned int
>> irq_base,
>> - irq_hw_number_t hwirq_base, int count)
>> +int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
>> +irq_hw_number_t hwirq)
>>   {
>> -   unsigned int virq = irq_base;
>> -   irq_hw_number_t hwirq = hwirq_base;
>> -   int i, ret;>> +   struct irq_data *irq_data = 
>> irq_get_irq_data(virq);
>> +   int ret;
>>
>> -   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);
>> +   if (WARN(hwirq >= domain->hwirq_max,
>> +"error: hwirq 0x%x is too large for %s\n", (int)hwirq,
>> domain->name))
>> +   return -EINVAL;
>> +   if (WARN(!irq_data, "error: virq%i is not allocated", virq))
>> +   return -EINVAL;
>> +   if (WARN(irq_data->domain, "error: virq%i is already associated",
>> virq))
>> +   return -EINVAL;
>
>
> Hi Grant,
>
> I have a qestion here, assume that we have three hwirqs and alloc three
> virqs, for first irq, it check irq_data
> and irq_data->domain pass, but the second is failed, then this code do
> nothing with failed( in
>
> irq_domain_associate_many()) and continue to associated the third one.
>
>
> This should be very dangours, even though I have no idea of when this could
> happen.

Define what you mean by "dangerous". You are correct that it is a bad
situation, and the kernel will complain very loudly if it happens.
However, the users of irq_domain_associate_many() are usually irq
controllers using a legacy domain that needs to be set up during early
boot. If the IRQ controller setup fails and gets unwound, then it is
very likely that there will be no output at all from the kernel. This
has actually been a problem on a number of platforms and it is a big
part of why this irqdomain refactoring series wasn't merged 6 months
ago.

I think it is better to relax the behaviour of
irq_domain_associate_many() so that if something fails, then at least
it can limp along and try to get at least some of the irqs associated.
That way we can find and fix problematic platforms rather than failing
silently.

Also, I don't see anything particularly dangerous about this behaviour
other than having some of the hwirqs not being associated with a virq.
The code protects against this path and if an irq controller receives
an IRQ on a unassociated hwirq, then the kernel will also log that as
an error.

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


Re: [RFC 08/10] irqdomain: Refactor irq_domain_associate_many()

2013-06-18 Thread Grant Likely
On Tue, Jun 18, 2013 at 4:09 AM, Mike Qiu qiud...@linux.vnet.ibm.com wrote:
 于 2013/6/10 8:49, Grant Likely 写道:

 Originally, irq_domain_associate_many() was designed to unwind the
 mapped irqs on a failure of any individual association. However, that
 proved to be a problem with certain IRQ controllers. Some of them only
 support a subset of irqs, and will fail when attempting to map a
 reserved IRQ. In those cases we want to map as many IRQs as possible, so
 instead it is better for irq_domain_associate_many() to make a
 best-effort attempt to map irqs, but not fail if any or all of them
 don't succeed. If a caller really cares about how many irqs got
 associated, then it should instead go back and check that all of the
 irqs is cares about were mapped.

 The original design open-coded the individual association code into the
 body of irq_domain_associate_many(), but with no longer needing to
 unwind associations, the code becomes simpler to split out
 irq_domain_associate() to contain the bulk of the logic, and
 irq_domain_associate_many() to be a simple loop wrapper.

 This patch also adds a new error check to the associate path to make
 sure it isn't called for an irq larger than the controller can handle,
 and adds locking so that the irq_domain_mutex is held while setting up a
 new association.

 Signed-off-by: Grant Likely grant.lik...@linaro.org
[...]
 -int irq_domain_associate_many(struct irq_domain *domain, unsigned int
 irq_base,
 - irq_hw_number_t hwirq_base, int count)
 +int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
 +irq_hw_number_t hwirq)
   {
 -   unsigned int virq = irq_base;
 -   irq_hw_number_t hwirq = hwirq_base;
 -   int i, ret; +   struct irq_data *irq_data = 
 irq_get_irq_data(virq);
 +   int ret;

 -   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);
 +   if (WARN(hwirq = domain-hwirq_max,
 +error: hwirq 0x%x is too large for %s\n, (int)hwirq,
 domain-name))
 +   return -EINVAL;
 +   if (WARN(!irq_data, error: virq%i is not allocated, virq))
 +   return -EINVAL;
 +   if (WARN(irq_data-domain, error: virq%i is already associated,
 virq))
 +   return -EINVAL;


 Hi Grant,

 I have a qestion here, assume that we have three hwirqs and alloc three
 virqs, for first irq, it check irq_data
 and irq_data-domain pass, but the second is failed, then this code do
 nothing with failed( in

 irq_domain_associate_many()) and continue to associated the third one.


 This should be very dangours, even though I have no idea of when this could
 happen.

Define what you mean by dangerous. You are correct that it is a bad
situation, and the kernel will complain very loudly if it happens.
However, the users of irq_domain_associate_many() are usually irq
controllers using a legacy domain that needs to be set up during early
boot. If the IRQ controller setup fails and gets unwound, then it is
very likely that there will be no output at all from the kernel. This
has actually been a problem on a number of platforms and it is a big
part of why this irqdomain refactoring series wasn't merged 6 months
ago.

I think it is better to relax the behaviour of
irq_domain_associate_many() so that if something fails, then at least
it can limp along and try to get at least some of the irqs associated.
That way we can find and fix problematic platforms rather than failing
silently.

Also, I don't see anything particularly dangerous about this behaviour
other than having some of the hwirqs not being associated with a virq.
The code protects against this path and if an irq controller receives
an IRQ on a unassociated hwirq, then the kernel will also log that as
an error.

g.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC 08/10] irqdomain: Refactor irq_domain_associate_many()

2013-06-17 Thread Mike Qiu

于 2013/6/10 8:49, Grant Likely 写道:

Originally, irq_domain_associate_many() was designed to unwind the
mapped irqs on a failure of any individual association. However, that
proved to be a problem with certain IRQ controllers. Some of them only
support a subset of irqs, and will fail when attempting to map a
reserved IRQ. In those cases we want to map as many IRQs as possible, so
instead it is better for irq_domain_associate_many() to make a
best-effort attempt to map irqs, but not fail if any or all of them
don't succeed. If a caller really cares about how many irqs got
associated, then it should instead go back and check that all of the
irqs is cares about were mapped.

The original design open-coded the individual association code into the
body of irq_domain_associate_many(), but with no longer needing to
unwind associations, the code becomes simpler to split out
irq_domain_associate() to contain the bulk of the logic, and
irq_domain_associate_many() to be a simple loop wrapper.

This patch also adds a new error check to the associate path to make
sure it isn't called for an irq larger than the controller can handle,
and adds locking so that the irq_domain_mutex is held while setting up a
new association.

Signed-off-by: Grant Likely 
---
  include/linux/irqdomain.h |  22 +++---
  kernel/irq/irqdomain.c| 185 +++---
  2 files changed, 101 insertions(+), 106 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index fd4b26f..f9e8e06 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -103,6 +103,7 @@ struct irq_domain {
struct irq_domain_chip_generic *gc;

/* reverse map data. The linear map gets appended to the irq_domain */
+   irq_hw_number_t hwirq_max;
unsigned int revmap_direct_max_irq;
unsigned int revmap_size;
struct radix_tree_root revmap_tree;
@@ -110,8 +111,8 @@ struct irq_domain {
  };

  #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+   irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
void *host_data);
  struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
@@ -140,14 +141,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, 0, ops, host_data);
+   return __irq_domain_add(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, ops, host_data);
+   return __irq_domain_add(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,
@@ -166,14 +167,11 @@ static inline struct irq_domain 
*irq_domain_add_tree(struct device_node *of_node

  extern void irq_domain_remove(struct irq_domain *host);

-extern int irq_domain_associate_many(struct irq_domain *domain,
-unsigned int irq_base,
-irq_hw_number_t hwirq_base, int count);
-static inline int irq_domain_associate(struct irq_domain *domain, unsigned int 
irq,
-   irq_hw_number_t hwirq)
-{
-   return irq_domain_associate_many(domain, irq, hwirq, 1);
-}
+extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
+   irq_hw_number_t hwirq);
+extern void irq_domain_associate_many(struct irq_domain *domain,
+ unsigned int irq_base,
+ irq_hw_number_t hwirq_base, int count);

  extern unsigned int irq_create_mapping(struct irq_domain *host,
   irq_hw_number_t hwirq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 280b804..80e9249 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -35,8 +35,8 @@ static struct irq_domain *irq_default_domain;
   * register allocated irq_domain with irq_domain_register().  Returns pointer
   * to IRQ domain, or NULL on failure.
   */
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain *__irq_domain_add(struct 

Re: [RFC 08/10] irqdomain: Refactor irq_domain_associate_many()

2013-06-17 Thread Mike Qiu

于 2013/6/10 8:49, Grant Likely 写道:

Originally, irq_domain_associate_many() was designed to unwind the
mapped irqs on a failure of any individual association. However, that
proved to be a problem with certain IRQ controllers. Some of them only
support a subset of irqs, and will fail when attempting to map a
reserved IRQ. In those cases we want to map as many IRQs as possible, so
instead it is better for irq_domain_associate_many() to make a
best-effort attempt to map irqs, but not fail if any or all of them
don't succeed. If a caller really cares about how many irqs got
associated, then it should instead go back and check that all of the
irqs is cares about were mapped.

The original design open-coded the individual association code into the
body of irq_domain_associate_many(), but with no longer needing to
unwind associations, the code becomes simpler to split out
irq_domain_associate() to contain the bulk of the logic, and
irq_domain_associate_many() to be a simple loop wrapper.

This patch also adds a new error check to the associate path to make
sure it isn't called for an irq larger than the controller can handle,
and adds locking so that the irq_domain_mutex is held while setting up a
new association.

Signed-off-by: Grant Likely grant.lik...@linaro.org
---
  include/linux/irqdomain.h |  22 +++---
  kernel/irq/irqdomain.c| 185 +++---
  2 files changed, 101 insertions(+), 106 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index fd4b26f..f9e8e06 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -103,6 +103,7 @@ struct irq_domain {
struct irq_domain_chip_generic *gc;

/* reverse map data. The linear map gets appended to the irq_domain */
+   irq_hw_number_t hwirq_max;
unsigned int revmap_direct_max_irq;
unsigned int revmap_size;
struct radix_tree_root revmap_tree;
@@ -110,8 +111,8 @@ struct irq_domain {
  };

  #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+   irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
void *host_data);
  struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
@@ -140,14 +141,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, 0, ops, host_data);
+   return __irq_domain_add(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, ops, host_data);
+   return __irq_domain_add(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,
@@ -166,14 +167,11 @@ static inline struct irq_domain 
*irq_domain_add_tree(struct device_node *of_node

  extern void irq_domain_remove(struct irq_domain *host);

-extern int irq_domain_associate_many(struct irq_domain *domain,
-unsigned int irq_base,
-irq_hw_number_t hwirq_base, int count);
-static inline int irq_domain_associate(struct irq_domain *domain, unsigned int 
irq,
-   irq_hw_number_t hwirq)
-{
-   return irq_domain_associate_many(domain, irq, hwirq, 1);
-}
+extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
+   irq_hw_number_t hwirq);
+extern void irq_domain_associate_many(struct irq_domain *domain,
+ unsigned int irq_base,
+ irq_hw_number_t hwirq_base, int count);

  extern unsigned int irq_create_mapping(struct irq_domain *host,
   irq_hw_number_t hwirq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 280b804..80e9249 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -35,8 +35,8 @@ static struct irq_domain *irq_default_domain;
   * register allocated irq_domain with irq_domain_register().  Returns pointer
   * to IRQ domain, or NULL on failure.
   */
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain 

[RFC 08/10] irqdomain: Refactor irq_domain_associate_many()

2013-06-09 Thread Grant Likely
Originally, irq_domain_associate_many() was designed to unwind the
mapped irqs on a failure of any individual association. However, that
proved to be a problem with certain IRQ controllers. Some of them only
support a subset of irqs, and will fail when attempting to map a
reserved IRQ. In those cases we want to map as many IRQs as possible, so
instead it is better for irq_domain_associate_many() to make a
best-effort attempt to map irqs, but not fail if any or all of them
don't succeed. If a caller really cares about how many irqs got
associated, then it should instead go back and check that all of the
irqs is cares about were mapped.

The original design open-coded the individual association code into the
body of irq_domain_associate_many(), but with no longer needing to
unwind associations, the code becomes simpler to split out
irq_domain_associate() to contain the bulk of the logic, and
irq_domain_associate_many() to be a simple loop wrapper.

This patch also adds a new error check to the associate path to make
sure it isn't called for an irq larger than the controller can handle,
and adds locking so that the irq_domain_mutex is held while setting up a
new association.

Signed-off-by: Grant Likely 
---
 include/linux/irqdomain.h |  22 +++---
 kernel/irq/irqdomain.c| 185 +++---
 2 files changed, 101 insertions(+), 106 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index fd4b26f..f9e8e06 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -103,6 +103,7 @@ struct irq_domain {
struct irq_domain_chip_generic *gc;
 
/* reverse map data. The linear map gets appended to the irq_domain */
+   irq_hw_number_t hwirq_max;
unsigned int revmap_direct_max_irq;
unsigned int revmap_size;
struct radix_tree_root revmap_tree;
@@ -110,8 +111,8 @@ struct irq_domain {
 };
 
 #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+   irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
void *host_data);
 struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
@@ -140,14 +141,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, 0, ops, host_data);
+   return __irq_domain_add(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, ops, host_data);
+   return __irq_domain_add(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,
@@ -166,14 +167,11 @@ static inline struct irq_domain 
*irq_domain_add_tree(struct device_node *of_node
 
 extern void irq_domain_remove(struct irq_domain *host);
 
-extern int irq_domain_associate_many(struct irq_domain *domain,
-unsigned int irq_base,
-irq_hw_number_t hwirq_base, int count);
-static inline int irq_domain_associate(struct irq_domain *domain, unsigned int 
irq,
-   irq_hw_number_t hwirq)
-{
-   return irq_domain_associate_many(domain, irq, hwirq, 1);
-}
+extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
+   irq_hw_number_t hwirq);
+extern void irq_domain_associate_many(struct irq_domain *domain,
+ unsigned int irq_base,
+ irq_hw_number_t hwirq_base, int count);
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
   irq_hw_number_t hwirq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 280b804..80e9249 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -35,8 +35,8 @@ static struct irq_domain *irq_default_domain;
  * register allocated irq_domain with irq_domain_register().  Returns pointer
  * to IRQ domain, or NULL on failure.
  */
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+

[RFC 08/10] irqdomain: Refactor irq_domain_associate_many()

2013-06-09 Thread Grant Likely
Originally, irq_domain_associate_many() was designed to unwind the
mapped irqs on a failure of any individual association. However, that
proved to be a problem with certain IRQ controllers. Some of them only
support a subset of irqs, and will fail when attempting to map a
reserved IRQ. In those cases we want to map as many IRQs as possible, so
instead it is better for irq_domain_associate_many() to make a
best-effort attempt to map irqs, but not fail if any or all of them
don't succeed. If a caller really cares about how many irqs got
associated, then it should instead go back and check that all of the
irqs is cares about were mapped.

The original design open-coded the individual association code into the
body of irq_domain_associate_many(), but with no longer needing to
unwind associations, the code becomes simpler to split out
irq_domain_associate() to contain the bulk of the logic, and
irq_domain_associate_many() to be a simple loop wrapper.

This patch also adds a new error check to the associate path to make
sure it isn't called for an irq larger than the controller can handle,
and adds locking so that the irq_domain_mutex is held while setting up a
new association.

Signed-off-by: Grant Likely grant.lik...@linaro.org
---
 include/linux/irqdomain.h |  22 +++---
 kernel/irq/irqdomain.c| 185 +++---
 2 files changed, 101 insertions(+), 106 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index fd4b26f..f9e8e06 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -103,6 +103,7 @@ struct irq_domain {
struct irq_domain_chip_generic *gc;
 
/* reverse map data. The linear map gets appended to the irq_domain */
+   irq_hw_number_t hwirq_max;
unsigned int revmap_direct_max_irq;
unsigned int revmap_size;
struct radix_tree_root revmap_tree;
@@ -110,8 +111,8 @@ struct irq_domain {
 };
 
 #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+   irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
void *host_data);
 struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
@@ -140,14 +141,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, 0, ops, host_data);
+   return __irq_domain_add(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, ops, host_data);
+   return __irq_domain_add(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,
@@ -166,14 +167,11 @@ static inline struct irq_domain 
*irq_domain_add_tree(struct device_node *of_node
 
 extern void irq_domain_remove(struct irq_domain *host);
 
-extern int irq_domain_associate_many(struct irq_domain *domain,
-unsigned int irq_base,
-irq_hw_number_t hwirq_base, int count);
-static inline int irq_domain_associate(struct irq_domain *domain, unsigned int 
irq,
-   irq_hw_number_t hwirq)
-{
-   return irq_domain_associate_many(domain, irq, hwirq, 1);
-}
+extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
+   irq_hw_number_t hwirq);
+extern void irq_domain_associate_many(struct irq_domain *domain,
+ unsigned int irq_base,
+ irq_hw_number_t hwirq_base, int count);
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
   irq_hw_number_t hwirq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 280b804..80e9249 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -35,8 +35,8 @@ static struct irq_domain *irq_default_domain;
  * register allocated irq_domain with irq_domain_register().  Returns pointer
  * to IRQ domain, or NULL on failure.
  */
-struct irq_domain *__irq_domain_add(struct device_node *of_node,
-   int size, int direct_max,
+struct irq_domain *__irq_domain_add(struct device_node *of_node, int