All of lore.kernel.org
 help / color / mirror / Atom feed
* irq_domain fixes for v3.4-rc2
@ 2012-04-11 23:18 Grant Likely
  2012-04-11 23:18 ` [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers Grant Likely
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Grant Likely @ 2012-04-11 23:18 UTC (permalink / raw)
  To: linux-kernel

Hi Ben,

Here are the fixes I'm proposing for the irq_domain issues seen on
powermac.  I had originally only intended to remove the
irq_virq_count, but I already had the hint and slow path removal
patches written and reviewed, and removing them reduces the number of
failure paths, and simplifies the code quite a bit.

I've pushed this out to the following branch for testing:

git://git.secretlab.ca/git/linux-2.6 irqdomain/test

It has been boot tested on ARM, but not powerpc.  This series of three
patches applies on top of the existing irqdomain/merge branch on my
git server:

git://git.secretlab.ca/git/linux-2.6 irqdomain/merge

Can you test on your powermac?

Thanks,
g.


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

* [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers
  2012-04-11 23:18 irq_domain fixes for v3.4-rc2 Grant Likely
@ 2012-04-11 23:18 ` Grant Likely
  2012-04-11 23:44   ` Benjamin Herrenschmidt
  2012-04-11 23:18 ` [PATCH 2/3] irq_domain: eliminate slow-path revmap lookups Grant Likely
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Grant Likely @ 2012-04-11 23:18 UTC (permalink / raw)
  To: linux-kernel
  Cc: Grant Likely, Benjamin Herrenschmidt, Thomas Gleixner,
	Milton Miller, Olof Johansson

The 'hint' used to try and line up irq numbers with hw irq numbers is
rather a hack and not very useful.  It also had some value when irq
reverse mapping was lazy, and not done right at map time.  However, the
lazy mapping is to be removed, so keeping around 'hint' isn't helpful
anymore.  This patch removes it.

v2: Rebase onto v3.4-rc2

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Milton Miller <miltonm@bga.com>
Cc: Olof Johansson <olof@lixom.net>
---
 kernel/irq/irqdomain.c |   23 ++++++-----------------
 1 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index eb05e40..041710d 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -4,6 +4,7 @@
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 #include <linux/irqdomain.h>
+#include <linux/irqnr.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
@@ -350,7 +351,6 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 unsigned int irq_create_mapping(struct irq_domain *domain,
 				irq_hw_number_t hwirq)
 {
-	unsigned int hint;
 	int virq;
 
 	pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
@@ -378,14 +378,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 		return irq_domain_legacy_revmap(domain, hwirq);
 
 	/* Allocate a virtual interrupt number */
-	hint = hwirq % irq_virq_count;
-	if (hint == 0)
-		hint++;
-	virq = irq_alloc_desc_from(hint, 0);
-	if (virq <= 0)
-		virq = irq_alloc_desc_from(1, 0);
+	virq = irq_alloc_desc_from(1, 0);
 	if (virq <= 0) {
-		pr_debug("irq: -> virq allocation failed\n");
+		pr_debug("irq: irq_desc allocation failed\n");
 		return 0;
 	}
 
@@ -516,7 +511,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
 			      irq_hw_number_t hwirq)
 {
 	unsigned int i;
-	unsigned int hint = hwirq % irq_virq_count;
+	struct irq_desc *desc;
 
 	/* Look for default domain if nececssary */
 	if (domain == NULL)
@@ -529,17 +524,11 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
 		return irq_domain_legacy_revmap(domain, hwirq);
 
 	/* Slow path does a linear search of the map */
-	if (hint == 0)
-		hint = 1;
-	i = hint;
-	do {
+	for_each_irq_desc(i, desc)  {
 		struct irq_data *data = irq_get_irq_data(i);
 		if (data && (data->domain == domain) && (data->hwirq == hwirq))
 			return i;
-		i++;
-		if (i >= irq_virq_count)
-			i = 1;
-	} while(i != hint);
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(irq_find_mapping);
-- 
1.7.9.1


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

* [PATCH 2/3] irq_domain: eliminate slow-path revmap lookups
  2012-04-11 23:18 irq_domain fixes for v3.4-rc2 Grant Likely
  2012-04-11 23:18 ` [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers Grant Likely
@ 2012-04-11 23:18 ` Grant Likely
  2012-04-11 23:18 ` [PATCH 3/3] irq_domain: Move irq_virq_count into NOMAP revmap Grant Likely
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Grant Likely @ 2012-04-11 23:18 UTC (permalink / raw)
  To: linux-kernel
  Cc: Grant Likely, Benjamin Herrenschmidt, Thomas Gleixner, Milton Miller

With the current state of irq_domain, the reverse map is always updated
when new IRQs get mapped.  This means that the irq_find_mapping() function
can be simplified to always execute the revmap-specific lookup function.

This patch adds lookup functions for the revmaps that don't yet have one
and removes the slow path lookup code path.

v6: Remove the slow path entirely.  The only place where the slow path
    could get called is for a linear mapping if the hwirq number is larger
    than the linear revmap size.
v5: rewrite to not use a ->revmap() callback.  It is simpler, smaller,
    safer and faster to open code each of the revmap lookups directly into
    irq_find_mapping() via a switch statement.
v4: Fix build failure on incorrect variable reference.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Milton Miller <miltonm@bga.com>
---
 arch/powerpc/sysdev/xics/icp-hv.c      |    2 +-
 arch/powerpc/sysdev/xics/icp-native.c  |    2 +-
 arch/powerpc/sysdev/xics/xics-common.c |    3 -
 include/linux/irqdomain.h              |    4 -
 kernel/irq/irqdomain.c                 |  129 ++++++++++----------------------
 5 files changed, 43 insertions(+), 97 deletions(-)

diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
index 253dce9..14469cf 100644
--- a/arch/powerpc/sysdev/xics/icp-hv.c
+++ b/arch/powerpc/sysdev/xics/icp-hv.c
@@ -111,7 +111,7 @@ static unsigned int icp_hv_get_irq(void)
 	if (vec == XICS_IRQ_SPURIOUS)
 		return NO_IRQ;
 
-	irq = irq_radix_revmap_lookup(xics_host, vec);
+	irq = irq_find_mapping(xics_host, vec);
 	if (likely(irq != NO_IRQ)) {
 		xics_push_cppr(vec);
 		return irq;
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index 4c79b6f..48861d3 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -119,7 +119,7 @@ static unsigned int icp_native_get_irq(void)
 	if (vec == XICS_IRQ_SPURIOUS)
 		return NO_IRQ;
 
-	irq = irq_radix_revmap_lookup(xics_host, vec);
+	irq = irq_find_mapping(xics_host, vec);
 	if (likely(irq != NO_IRQ)) {
 		xics_push_cppr(vec);
 		return irq;
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
index ea5e204..1d7067d 100644
--- a/arch/powerpc/sysdev/xics/xics-common.c
+++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -330,9 +330,6 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq,
 
 	pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
 
-	/* Insert the interrupt mapping into the radix tree for fast lookup */
-	irq_radix_revmap_insert(xics_host, virq, hw);
-
 	/* They aren't all level sensitive but we just don't really know */
 	irq_set_status_flags(virq, IRQ_LEVEL);
 
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index ac17b9b..7a7af17 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -149,10 +149,6 @@ extern void irq_dispose_mapping(unsigned int virq);
 extern unsigned int irq_find_mapping(struct irq_domain *host,
 				     irq_hw_number_t hwirq);
 extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
-extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq,
-				    irq_hw_number_t hwirq);
-extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host,
-					    irq_hw_number_t hwirq);
 extern unsigned int irq_linear_revmap(struct irq_domain *host,
 				      irq_hw_number_t hwirq);
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 041710d..df92a34 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -314,7 +314,8 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 		domain = irq_default_domain;
 
 	BUG_ON(domain == NULL);
-	WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP);
+	if (WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP))
+		return 0;
 
 	virq = irq_alloc_desc_from(1, 0);
 	if (!virq) {
@@ -385,11 +386,22 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
 	}
 
 	if (irq_setup_virq(domain, virq, hwirq)) {
-		if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY)
-			irq_free_desc(virq);
+		irq_free_desc(virq);
 		return 0;
 	}
 
+	switch(domain->revmap_type) {
+	case IRQ_DOMAIN_MAP_LINEAR:
+		if (hwirq < domain->revmap_data.linear.size)
+			domain->revmap_data.linear.revmap[hwirq] = virq;
+		break;
+	case IRQ_DOMAIN_MAP_TREE:
+		mutex_lock(&revmap_trees_mutex);
+		radix_tree_insert(&domain->revmap_data.tree, hwirq,
+				  irq_get_irq_data(virq));
+		mutex_unlock(&revmap_trees_mutex);
+		break;
+	}
 	pr_debug("irq: irq %lu on domain %s mapped to virtual irq %u\n",
 		hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);
 
@@ -510,8 +522,7 @@ EXPORT_SYMBOL_GPL(irq_dispose_mapping);
 unsigned int irq_find_mapping(struct irq_domain *domain,
 			      irq_hw_number_t hwirq)
 {
-	unsigned int i;
-	struct irq_desc *desc;
+	struct irq_data *data;
 
 	/* Look for default domain if nececssary */
 	if (domain == NULL)
@@ -519,107 +530,49 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
 	if (domain == NULL)
 		return 0;
 
-	/* legacy -> bail early */
-	if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
+	switch (domain->revmap_type) {
+	case IRQ_DOMAIN_MAP_LEGACY:
 		return irq_domain_legacy_revmap(domain, hwirq);
-
-	/* Slow path does a linear search of the map */
-	for_each_irq_desc(i, desc)  {
-		struct irq_data *data = irq_get_irq_data(i);
+	case IRQ_DOMAIN_MAP_LINEAR:
+		return irq_linear_revmap(domain, hwirq);
+	case IRQ_DOMAIN_MAP_TREE:
+		rcu_read_lock();
+		data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
+		rcu_read_unlock();
+		if (data)
+			return data->irq;
+		break;
+	case IRQ_DOMAIN_MAP_NOMAP:
+		data = irq_get_irq_data(hwirq);
 		if (data && (data->domain == domain) && (data->hwirq == hwirq))
-			return i;
+			return hwirq;
+		break;
 	}
+
+	WARN(1, "ERROR: irq revmap went horribly wrong. revmap_type=%i\n",
+		domain->revmap_type);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(irq_find_mapping);
 
 /**
- * irq_radix_revmap_lookup() - Find a linux irq from a hw irq number.
- * @domain: domain owning this hardware interrupt
- * @hwirq: hardware irq number in that domain space
- *
- * This is a fast path, for use by irq controller code that uses radix tree
- * revmaps
- */
-unsigned int irq_radix_revmap_lookup(struct irq_domain *domain,
-				     irq_hw_number_t hwirq)
-{
-	struct irq_data *irq_data;
-
-	if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_TREE))
-		return irq_find_mapping(domain, hwirq);
-
-	/*
-	 * Freeing an irq can delete nodes along the path to
-	 * do the lookup via call_rcu.
-	 */
-	rcu_read_lock();
-	irq_data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
-	rcu_read_unlock();
-
-	/*
-	 * If found in radix tree, then fine.
-	 * Else fallback to linear lookup - this should not happen in practice
-	 * as it means that we failed to insert the node in the radix tree.
-	 */
-	return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);
-}
-
-/**
- * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping.
- * @domain: domain owning this hardware interrupt
- * @virq: linux irq number
- * @hwirq: hardware irq number in that domain space
- *
- * This is for use by irq controllers that use a radix tree reverse
- * mapping for fast lookup.
- */
-void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq,
-			     irq_hw_number_t hwirq)
-{
-	struct irq_data *irq_data = irq_get_irq_data(virq);
-
-	if (WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_TREE))
-		return;
-
-	if (virq) {
-		mutex_lock(&revmap_trees_mutex);
-		radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data);
-		mutex_unlock(&revmap_trees_mutex);
-	}
-}
-
-/**
  * irq_linear_revmap() - Find a linux irq from a hw irq number.
  * @domain: domain owning this hardware interrupt
  * @hwirq: hardware irq number in that domain space
  *
- * This is a fast path, for use by irq controller code that uses linear
- * revmaps. It does fallback to the slow path if the revmap doesn't exist
- * yet and will create the revmap entry with appropriate locking
+ * This is a fast path that can be called directly by irq controller code to
+ * save a handful of instructions.
  */
 unsigned int irq_linear_revmap(struct irq_domain *domain,
 			       irq_hw_number_t hwirq)
 {
-	unsigned int *revmap;
-
-	if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR))
-		return irq_find_mapping(domain, hwirq);
+	BUG_ON(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR);
 
-	/* Check revmap bounds */
-	if (unlikely(hwirq >= domain->revmap_data.linear.size))
-		return irq_find_mapping(domain, hwirq);
-
-	/* Check if revmap was allocated */
-	revmap = domain->revmap_data.linear.revmap;
-	if (unlikely(revmap == NULL))
-		return irq_find_mapping(domain, hwirq);
-
-	/* Fill up revmap with slow path if no mapping found */
-	if (unlikely(!revmap[hwirq]))
-		revmap[hwirq] = irq_find_mapping(domain, hwirq);
+	/* Check revmap bounds; complain if exceeded */
+	if (WARN_ON(hwirq >= domain->revmap_data.linear.size))
+		return 0;
 
-	return revmap[hwirq];
+	return domain->revmap_data.linear.revmap[hwirq];
 }
 
 #ifdef CONFIG_IRQ_DOMAIN_DEBUG
-- 
1.7.9.1


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

* [PATCH 3/3] irq_domain: Move irq_virq_count into NOMAP revmap
  2012-04-11 23:18 irq_domain fixes for v3.4-rc2 Grant Likely
  2012-04-11 23:18 ` [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers Grant Likely
  2012-04-11 23:18 ` [PATCH 2/3] irq_domain: eliminate slow-path revmap lookups Grant Likely
@ 2012-04-11 23:18 ` Grant Likely
  2012-04-11 23:20 ` irq_domain fixes for v3.4-rc2 Grant Likely
  2012-04-13 11:16 ` Andreas Schwab
  4 siblings, 0 replies; 9+ messages in thread
From: Grant Likely @ 2012-04-11 23:18 UTC (permalink / raw)
  To: linux-kernel
  Cc: Grant Likely, Benjamin Herrenschmidt, Thomas Gleixner, Milton Miller

This patch replaces the old global setting of irq_virq_count that is only
used by the NOMAP mapping and instead uses a revmap_data property so that
the maximum NOMAP allocation can be set per NOMAP irq_domain.

There is exactly one user of irq_virq_count in-tree right now: PS3.
Also, irq_virq_count is only useful for the NOMAP mapping.  So,
instead of having a single global irq_virq_count values, this change
drops it entirely and added a max_irq argument to irq_domain_add_nomap().
That makes it a property of an individual nomap irq domain instead of
a global system settting.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Milton Miller <miltonm@bga.com>
---
 arch/powerpc/platforms/cell/axon_msi.c       |    2 +-
 arch/powerpc/platforms/cell/beat_interrupt.c |    2 +-
 arch/powerpc/platforms/powermac/smp.c        |    2 +-
 arch/powerpc/platforms/ps3/interrupt.c       |    3 +-
 include/linux/irqdomain.h                    |    6 +++-
 kernel/irq/irqdomain.c                       |   27 +++++--------------------
 6 files changed, 14 insertions(+), 28 deletions(-)

diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index db360fc..d09f3e8 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -392,7 +392,7 @@ static int axon_msi_probe(struct platform_device *device)
 	}
 	memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
 
-	msic->irq_domain = irq_domain_add_nomap(dn, &msic_host_ops, msic);
+	msic->irq_domain = irq_domain_add_nomap(dn, 0, &msic_host_ops, msic);
 	if (!msic->irq_domain) {
 		printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n",
 		       dn->full_name);
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
index e5c3a2c..f9a48af 100644
--- a/arch/powerpc/platforms/cell/beat_interrupt.c
+++ b/arch/powerpc/platforms/cell/beat_interrupt.c
@@ -239,7 +239,7 @@ void __init beatic_init_IRQ(void)
 	ppc_md.get_irq = beatic_get_irq;
 
 	/* Allocate an irq host */
-	beatic_host = irq_domain_add_nomap(NULL, &beatic_pic_host_ops, NULL);
+	beatic_host = irq_domain_add_nomap(NULL, 0, &beatic_pic_host_ops, NULL);
 	BUG_ON(beatic_host == NULL);
 	irq_set_default_host(beatic_host);
 }
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index a81e5a8..b4ddaa3 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -192,7 +192,7 @@ static int psurge_secondary_ipi_init(void)
 {
 	int rc = -ENOMEM;
 
-	psurge_host = irq_domain_add_nomap(NULL, &psurge_host_ops, NULL);
+	psurge_host = irq_domain_add_nomap(NULL, 0, &psurge_host_ops, NULL);
 
 	if (psurge_host)
 		psurge_secondary_virq = irq_create_direct_mapping(psurge_host);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 2a4ff86..5f3b232 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -753,9 +753,8 @@ void __init ps3_init_IRQ(void)
 	unsigned cpu;
 	struct irq_domain *host;
 
-	host = irq_domain_add_nomap(NULL, &ps3_host_ops, NULL);
+	host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL);
 	irq_set_default_host(host);
-	irq_set_virq_count(PS3_PLUG_MAX + 1);
 
 	for_each_possible_cpu(cpu) {
 		struct ps3_private *pd = &per_cpu(ps3_private, cpu);
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 7a7af17..d0995bd 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -98,6 +98,9 @@ struct irq_domain {
 			unsigned int size;
 			unsigned int *revmap;
 		} linear;
+		struct {
+			unsigned int max_irq;
+		} nomap;
 		struct radix_tree_root tree;
 	} revmap_data;
 	const struct irq_domain_ops *ops;
@@ -120,6 +123,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
 					 const struct irq_domain_ops *ops,
 					 void *host_data);
 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);
 struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
@@ -128,7 +132,6 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
 
 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);
 
 static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
@@ -140,7 +143,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
 }
 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);
 
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index df92a34..49d20d4 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -24,7 +24,6 @@ static LIST_HEAD(irq_domain_list);
 static DEFINE_MUTEX(irq_domain_mutex);
 
 static DEFINE_MUTEX(revmap_trees_mutex);
-static unsigned int irq_virq_count = NR_IRQS;
 static struct irq_domain *irq_default_domain;
 
 /**
@@ -185,13 +184,16 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
 }
 
 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)
 {
 	struct irq_domain *domain = irq_domain_alloc(of_node,
 					IRQ_DOMAIN_MAP_NOMAP, ops, host_data);
-	if (domain)
+	if (domain) {
+		domain->revmap_data.nomap.max_irq = max_irq ? max_irq : ~0;
 		irq_domain_add(domain);
+	}
 	return domain;
 }
 
@@ -263,22 +265,6 @@ void irq_set_default_host(struct irq_domain *domain)
 	irq_default_domain = domain;
 }
 
-/**
- * irq_set_virq_count() - Set the maximum number of linux irqs
- * @count: number of linux irqs, capped with NR_IRQS
- *
- * This is mainly for use by platforms like iSeries who want to program
- * the virtual irq number in the controller to avoid the reverse mapping
- */
-void irq_set_virq_count(unsigned int count)
-{
-	pr_debug("irq: Trying to set virq count to %d\n", count);
-
-	BUG_ON(count < NUM_ISA_INTERRUPTS);
-	if (count < NR_IRQS)
-		irq_virq_count = count;
-}
-
 static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq)
 {
@@ -322,13 +308,12 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 		pr_debug("irq: create_direct virq allocation failed\n");
 		return 0;
 	}
-	if (virq >= irq_virq_count) {
+	if (virq >= domain->revmap_data.nomap.max_irq) {
 		pr_err("ERROR: no free irqs available below %i maximum\n",
-			irq_virq_count);
+			domain->revmap_data.nomap.max_irq);
 		irq_free_desc(virq);
 		return 0;
 	}
-
 	pr_debug("irq: create_direct obtained virq %d\n", virq);
 
 	if (irq_setup_virq(domain, virq, virq)) {
-- 
1.7.9.1


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

* Re: irq_domain fixes for v3.4-rc2
  2012-04-11 23:18 irq_domain fixes for v3.4-rc2 Grant Likely
                   ` (2 preceding siblings ...)
  2012-04-11 23:18 ` [PATCH 3/3] irq_domain: Move irq_virq_count into NOMAP revmap Grant Likely
@ 2012-04-11 23:20 ` Grant Likely
  2012-04-13 11:16 ` Andreas Schwab
  4 siblings, 0 replies; 9+ messages in thread
From: Grant Likely @ 2012-04-11 23:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Milton Miller, Andreas Schwab

Oops, missed out the cc's.

g.

On Wed, Apr 11, 2012 at 5:18 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> Hi Ben,
>
> Here are the fixes I'm proposing for the irq_domain issues seen on
> powermac.  I had originally only intended to remove the
> irq_virq_count, but I already had the hint and slow path removal
> patches written and reviewed, and removing them reduces the number of
> failure paths, and simplifies the code quite a bit.
>
> I've pushed this out to the following branch for testing:
>
> git://git.secretlab.ca/git/linux-2.6 irqdomain/test
>
> It has been boot tested on ARM, but not powerpc.  This series of three
> patches applies on top of the existing irqdomain/merge branch on my
> git server:
>
> git://git.secretlab.ca/git/linux-2.6 irqdomain/merge
>
> Can you test on your powermac?
>
> Thanks,
> g.
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

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

* Re: [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers
  2012-04-11 23:18 ` [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers Grant Likely
@ 2012-04-11 23:44   ` Benjamin Herrenschmidt
  2012-04-12  0:11     ` Grant Likely
  0 siblings, 1 reply; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2012-04-11 23:44 UTC (permalink / raw)
  To: Grant Likely; +Cc: linux-kernel, Thomas Gleixner, Milton Miller, Olof Johansson

On Wed, 2012-04-11 at 17:18 -0600, Grant Likely wrote:
> The 'hint' used to try and line up irq numbers with hw irq numbers is
> rather a hack and not very useful.  It also had some value when irq
> reverse mapping was lazy, and not done right at map time.  However, the
> lazy mapping is to be removed, so keeping around 'hint' isn't helpful
> anymore.  This patch removes it.

Please document that this also removes the support for irq_virq_count,
which breaks PS3, to be "fixed" by your patch 3/3 (you may want to
re-order the patches here) and that fixes an actual bug with mapping of
interrupts above NR_IRQS

Cheers,
Ben.

> v2: Rebase onto v3.4-rc2
> 
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Milton Miller <miltonm@bga.com>
> Cc: Olof Johansson <olof@lixom.net>
> ---
>  kernel/irq/irqdomain.c |   23 ++++++-----------------
>  1 files changed, 6 insertions(+), 17 deletions(-)
> 
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index eb05e40..041710d 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -4,6 +4,7 @@
>  #include <linux/irq.h>
>  #include <linux/irqdesc.h>
>  #include <linux/irqdomain.h>
> +#include <linux/irqnr.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/of.h>
> @@ -350,7 +351,6 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
>  unsigned int irq_create_mapping(struct irq_domain *domain,
>  				irq_hw_number_t hwirq)
>  {
> -	unsigned int hint;
>  	int virq;
>  
>  	pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
> @@ -378,14 +378,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
>  		return irq_domain_legacy_revmap(domain, hwirq);
>  
>  	/* Allocate a virtual interrupt number */
> -	hint = hwirq % irq_virq_count;
> -	if (hint == 0)
> -		hint++;
> -	virq = irq_alloc_desc_from(hint, 0);
> -	if (virq <= 0)
> -		virq = irq_alloc_desc_from(1, 0);
> +	virq = irq_alloc_desc_from(1, 0);
>  	if (virq <= 0) {
> -		pr_debug("irq: -> virq allocation failed\n");
> +		pr_debug("irq: irq_desc allocation failed\n");
>  		return 0;
>  	}
>  
> @@ -516,7 +511,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
>  			      irq_hw_number_t hwirq)
>  {
>  	unsigned int i;
> -	unsigned int hint = hwirq % irq_virq_count;
> +	struct irq_desc *desc;
>  
>  	/* Look for default domain if nececssary */
>  	if (domain == NULL)
> @@ -529,17 +524,11 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
>  		return irq_domain_legacy_revmap(domain, hwirq);
>  
>  	/* Slow path does a linear search of the map */
> -	if (hint == 0)
> -		hint = 1;
> -	i = hint;
> -	do {
> +	for_each_irq_desc(i, desc)  {
>  		struct irq_data *data = irq_get_irq_data(i);
>  		if (data && (data->domain == domain) && (data->hwirq == hwirq))
>  			return i;
> -		i++;
> -		if (i >= irq_virq_count)
> -			i = 1;
> -	} while(i != hint);
> +	}
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(irq_find_mapping);



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

* Re: [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers
  2012-04-11 23:44   ` Benjamin Herrenschmidt
@ 2012-04-12  0:11     ` Grant Likely
  0 siblings, 0 replies; 9+ messages in thread
From: Grant Likely @ 2012-04-12  0:11 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-kernel, Thomas Gleixner, Milton Miller, Olof Johansson

On Wed, Apr 11, 2012 at 5:44 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Wed, 2012-04-11 at 17:18 -0600, Grant Likely wrote:
>> The 'hint' used to try and line up irq numbers with hw irq numbers is
>> rather a hack and not very useful.  It also had some value when irq
>> reverse mapping was lazy, and not done right at map time.  However, the
>> lazy mapping is to be removed, so keeping around 'hint' isn't helpful
>> anymore.  This patch removes it.
>
> Please document that this also removes the support for irq_virq_count,
> which breaks PS3, to be "fixed" by your patch 3/3 (you may want to
> re-order the patches here) and that fixes an actual bug with mapping of
> interrupts above NR_IRQS

Yes, I'll either fix this patch or reorder before merging.

g.

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

* Re: irq_domain fixes for v3.4-rc2
  2012-04-11 23:18 irq_domain fixes for v3.4-rc2 Grant Likely
                   ` (3 preceding siblings ...)
  2012-04-11 23:20 ` irq_domain fixes for v3.4-rc2 Grant Likely
@ 2012-04-13 11:16 ` Andreas Schwab
  2012-04-19 18:31   ` Grant Likely
  4 siblings, 1 reply; 9+ messages in thread
From: Andreas Schwab @ 2012-04-13 11:16 UTC (permalink / raw)
  To: Grant Likely; +Cc: linux-kernel

Grant Likely <grant.likely@secretlab.ca> writes:

> I've pushed this out to the following branch for testing:
>
> git://git.secretlab.ca/git/linux-2.6 irqdomain/test

That doesn't work at all.  I get a warning in virq_to_hw and it hangs
later, probably during SMP bringup due to lost IPI interrupts.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: irq_domain fixes for v3.4-rc2
  2012-04-13 11:16 ` Andreas Schwab
@ 2012-04-19 18:31   ` Grant Likely
  0 siblings, 0 replies; 9+ messages in thread
From: Grant Likely @ 2012-04-19 18:31 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linux-kernel

On Fri, 13 Apr 2012 13:16:49 +0200, Andreas Schwab <schwab@linux-m68k.org> wrote:
> Grant Likely <grant.likely@secretlab.ca> writes:
> 
> > I've pushed this out to the following branch for testing:
> >
> > git://git.secretlab.ca/git/linux-2.6 irqdomain/test
> 
> That doesn't work at all.  I get a warning in virq_to_hw and it hangs
> later, probably during SMP bringup due to lost IPI interrupts.

There are a bunch of bugs in the MPIC driver that Ben discovered that
only work because it just happens to be that hwirq == virq.  Removing
the hint breaks the driver badly.  I've backed off from that change
and instead just merged the NR_IRQS fix.  After the MPIC bugs are
fixed I want to revisit removing the hint.

g.


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

end of thread, other threads:[~2012-04-19 18:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-11 23:18 irq_domain fixes for v3.4-rc2 Grant Likely
2012-04-11 23:18 ` [PATCH 1/3] irq_domain: remove "hint" when allocating irq numbers Grant Likely
2012-04-11 23:44   ` Benjamin Herrenschmidt
2012-04-12  0:11     ` Grant Likely
2012-04-11 23:18 ` [PATCH 2/3] irq_domain: eliminate slow-path revmap lookups Grant Likely
2012-04-11 23:18 ` [PATCH 3/3] irq_domain: Move irq_virq_count into NOMAP revmap Grant Likely
2012-04-11 23:20 ` irq_domain fixes for v3.4-rc2 Grant Likely
2012-04-13 11:16 ` Andreas Schwab
2012-04-19 18:31   ` Grant Likely

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.