2012-05-19 06:12:08

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 0/8] irqdomain cleanups + identity mapping support

Here's the current patch stack I've got against the irqdomain code, which
is about what I need to start being able to reasonably start converting
the SH INTC subsystem over to it.

This whole series is also available via git at:

git://github.com/pmundt/linux-sh.git common/irqdomain

but I've not yet created a signed tag to pull from as there's likely
still a fair bit of work to do. The diffstat looks innocuous enough, but
is obviously of no real value in this case:

Paul Mundt (8):
irqdomain: Support removal of IRQ domains.
irqdomain: Export remaining public API symbols.
irqdomain: Make irq_domain_simple_map() static.
irqdomain: Simple NUMA awareness.
irqdomain: Kill off duplicate definitions.
irqdomain: Support identity mapped VIRQ allocation.
irqdomain: trivial pr_fmt conversion.
irqdomain: Support insertion of existing IRQ allocations.

include/linux/irqdomain.h | 12 +-
include/linux/of.h | 10 +-
kernel/irq/irqdomain.c | 187 ++++++++++++++++++++++++++++++++++++++--------
3 files changed, 168 insertions(+), 41 deletions(-)


2012-05-19 06:12:10

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 6/8] irqdomain: Support identity mapped VIRQ allocation.

This adds a new irq_create_identity_mapping() routine to permit platforms
to utilize 1:1 identity mapping between hardware and linux IRQs for
domain population. The same semantics as irq_create_mapping() apply,
though in this case we only support irqdesc allocation at a static
location, rather than falling back on dynamic lookup.

Signed-off-by: Paul Mundt <[email protected]>
---
include/linux/irqdomain.h | 2 ++
kernel/irq/irqdomain.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 5abb533..e32d2e7 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -149,6 +149,8 @@ extern unsigned int irq_create_mapping(struct irq_domain *host,
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_identity_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);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 5f0ca52..ac44781 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -459,6 +459,47 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
}
EXPORT_SYMBOL_GPL(irq_create_mapping);

+/**
+ * irq_create_identity_mapping() - Allocate an identity mapped irq
+ * @domain: domain owning this hardware interrupt or NULL for default domain
+ * @hwirq: hardware irq number in that domain space
+ *
+ * This routine is used to allocate IRQs with a 1:1 identity mapping
+ * between the hardware and linux irq.
+ */
+unsigned int irq_create_identity_mapping(struct irq_domain *domain,
+ irq_hw_number_t hwirq)
+{
+ int virq;
+
+ pr_debug("irq: irq_create_identity_mapping(0x%p, 0x%lx)\n",
+ domain, hwirq);
+
+ if (domain == NULL)
+ domain = irq_default_domain;
+ if (domain == NULL) {
+ WARN_ON(1);
+ return 0;
+ }
+
+ virq = irq_alloc_desc_at(hwirq, irq_domain_nid(domain->of_node));
+ if (virq < 0) {
+ pr_debug("irq: -> virq allocation failed\n");
+ return 0;
+ }
+
+ if (irq_setup_virq(domain, virq, hwirq)) {
+ if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY)
+ irq_free_desc(virq);
+ return 0;
+ }
+
+ pr_debug("irq: irq %lu identity mapped\n", hwirq);
+
+ return virq;
+}
+EXPORT_SYMBOL_GPL(irq_create_identity_mapping);
+
unsigned int irq_create_of_mapping(struct device_node *controller,
const u32 *intspec, unsigned int intsize)
{
--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:12:40

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 4/8] irqdomain: Simple NUMA awareness.

While common irqdesc allocation is node aware, the irqdomain code is not.

This plugs in NUMA node id proliferation across the various allocation
callsites by way of a new irq_domain_nid() helper. The irq_domain_nid()
routine takes an of_node pointer instead of an irq_domain as it's also
used for node placement of the irq domain data structure itself (at which
point only the of_node is known). For platforms that aren't DT capable,
we simply wrap in to numa_node_id() unconditionally.

In order for this to be generally supportable, it's also necessary to
make of_node_to_nid() generally available. This is accomplished by simply
bumping it down further in the header.

Presently we observe a number of regressions/inconsistencies on
NUMA-capable platforms:

- Platforms using irqdomains with legacy mappings, where the
irq_descs are allocated node-local and the irqdomain data
structure is not.

- Drivers implementing irqdomains will lose node locality
regardless of the underlying struct device's node id.

Signed-off-by: Paul Mundt <[email protected]>
---
include/linux/of.h | 10 +++++-----
kernel/irq/irqdomain.c | 18 +++++++++++++-----
2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/include/linux/of.h b/include/linux/of.h
index fa7fb1d..6478859 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -158,11 +158,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)

#define OF_BAD_ADDR ((u64)-1)

-#ifndef of_node_to_nid
-static inline int of_node_to_nid(struct device_node *np) { return -1; }
-#define of_node_to_nid of_node_to_nid
-#endif
-
extern struct device_node *of_find_node_by_name(struct device_node *from,
const char *name);
#define for_each_node_by_name(dn, name) \
@@ -351,6 +346,11 @@ static inline int of_machine_is_compatible(const char *compat)
#define of_match_node(_matches, _node) NULL
#endif /* CONFIG_OF */

+#ifndef of_node_to_nid
+static inline int of_node_to_nid(struct device_node *np) { return -1; }
+#define of_node_to_nid of_node_to_nid
+#endif
+
/**
* of_property_read_bool - Findfrom a property
* @np: device node from which the property value is to be read.
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 92e06442..5f0ca52 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -8,6 +8,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/topology.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp.h>
@@ -25,6 +26,11 @@ static DEFINE_MUTEX(irq_domain_mutex);
static DEFINE_MUTEX(revmap_trees_mutex);
static struct irq_domain *irq_default_domain;

+static inline int irq_domain_nid(struct device_node *of_node)
+{
+ return of_node ? of_node_to_nid(of_node) : numa_node_id();
+}
+
/**
* irq_domain_alloc() - Allocate a new irq_domain data structure
* @of_node: optional device-tree node of the interrupt controller
@@ -43,7 +49,8 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
{
struct irq_domain *domain;

- domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ domain = kzalloc_node(sizeof(*domain), GFP_KERNEL,
+ irq_domain_nid(of_node));
if (WARN_ON(!domain))
return NULL;

@@ -226,7 +233,8 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
struct irq_domain *domain;
unsigned int *revmap;

- revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL);
+ revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL,
+ irq_domain_nid(of_node));
if (WARN_ON(!revmap))
return NULL;

@@ -364,7 +372,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
BUG_ON(domain == NULL);
WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP);

- virq = irq_alloc_desc_from(1, 0);
+ virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
if (!virq) {
pr_debug("irq: create_direct virq allocation failed\n");
return 0;
@@ -430,9 +438,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
hint = hwirq % nr_irqs;
if (hint == 0)
hint++;
- virq = irq_alloc_desc_from(hint, 0);
+ virq = irq_alloc_desc_from(hint, irq_domain_nid(domain->of_node));
if (virq <= 0)
- virq = irq_alloc_desc_from(1, 0);
+ virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
if (virq <= 0) {
pr_debug("irq: -> virq allocation failed\n");
return 0;
--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:12:39

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 1/8] irqdomain: Support removal of IRQ domains.

Now that IRQ domains are being used by modules it's necessary to support
removing them, too. This adds a new irq_domain_remove() routine for doing
the bulk of the heavy lifting. It's left as an exercise to the caller to
ensure all mappings have been appropriatey disposed of before attempting
to remove the domain.

Signed-off-by: Paul Mundt <[email protected]>
---
include/linux/irqdomain.h | 4 ++-
kernel/irq/irqdomain.c | 61 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index c65740d..a796dbf 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -141,10 +141,12 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops,
host_data);
}
+
+extern void irq_domain_remove(struct irq_domain *host);
+
extern struct irq_domain *irq_find_host(struct device_node *node);
extern void irq_set_default_host(struct irq_domain *host);

-
extern unsigned int irq_create_mapping(struct irq_domain *host,
irq_hw_number_t hwirq);
extern void irq_dispose_mapping(unsigned int virq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 0e0ba5f..9cae0b2 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -56,6 +56,12 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
return domain;
}

+static void irq_domain_free(struct irq_domain *domain)
+{
+ of_node_put(domain->of_node);
+ kfree(domain);
+}
+
static void irq_domain_add(struct irq_domain *domain)
{
mutex_lock(&irq_domain_mutex);
@@ -65,6 +71,58 @@ static void irq_domain_add(struct irq_domain *domain)
domain->revmap_type, domain);
}

+/**
+ * irq_domain_remove() - Remove an irq domain.
+ * @domain: domain to remove
+ *
+ * This routine is used to remove an irq domain. The caller must ensure
+ * that all mappings within the domain have been disposed of prior to
+ * use, depending on the revmap type.
+ */
+void irq_domain_remove(struct irq_domain *domain)
+{
+ mutex_lock(&irq_domain_mutex);
+
+ switch (domain->revmap_type) {
+ case IRQ_DOMAIN_MAP_LEGACY:
+ /*
+ * Legacy domains don't manage their own irq_desc
+ * allocations, we expect the caller to handle irq_desc
+ * freeing on their own.
+ */
+ break;
+ case IRQ_DOMAIN_MAP_TREE:
+ /*
+ * radix_tree_delete() takes care of destroying the root
+ * node when all entries are removed. Shout if there are
+ * any mappings left.
+ */
+ WARN_ON(domain->revmap_data.tree.height);
+ break;
+ case IRQ_DOMAIN_MAP_LINEAR:
+ kfree(domain->revmap_data.linear.revmap);
+ domain->revmap_data.linear.size = 0;
+ break;
+ case IRQ_DOMAIN_MAP_NOMAP:
+ break;
+ }
+
+ list_del(&domain->link);
+
+ /*
+ * If the going away domain is the default one, reset it.
+ */
+ if (unlikely(irq_default_domain == domain))
+ irq_set_default_host(NULL);
+
+ mutex_unlock(&irq_domain_mutex);
+
+ pr_debug("irq: Removed domain of type %d @0x%p\n",
+ domain->revmap_type, domain);
+
+ irq_domain_free(domain);
+}
+
static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
irq_hw_number_t hwirq)
{
@@ -117,8 +175,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,

if (WARN_ON(!irq_data || irq_data->domain)) {
mutex_unlock(&irq_domain_mutex);
- of_node_put(domain->of_node);
- kfree(domain);
+ irq_domain_free(domain);
return NULL;
}
}
--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:12:37

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 3/8] irqdomain: Make irq_domain_simple_map() static.

Presently irq_domain_simple_map() isn't labelled as static, but there's
no definition for it in the public irqdomain header either. At present
all in-tree ->map users have meaningful work to do, and all others are
using irq_domain_simple_ops directly. Make it static for now, as it can
always be exported and added to the public API later.

Signed-off-by: Paul Mundt <[email protected]>
---
kernel/irq/irqdomain.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 01d4a0d..92e06442 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -758,8 +758,8 @@ static int __init irq_debugfs_init(void)
__initcall(irq_debugfs_init);
#endif /* CONFIG_IRQ_DOMAIN_DEBUG */

-int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
+static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
{
return 0;
}
--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:13:35

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 5/8] irqdomain: Kill off duplicate definitions.

Presently irqdomain.h has duplicate definitions for irq_find_host() and
irq_set_default_host(), presumably from merge damage. Kill off the
duplicates.

Signed-off-by: Paul Mundt <[email protected]>
---
include/linux/irqdomain.h | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index a796dbf..5abb533 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -144,9 +144,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(

extern void irq_domain_remove(struct irq_domain *host);

-extern struct irq_domain *irq_find_host(struct device_node *node);
-extern void irq_set_default_host(struct irq_domain *host);
-
extern unsigned int irq_create_mapping(struct irq_domain *host,
irq_hw_number_t hwirq);
extern void irq_dispose_mapping(unsigned int virq);
--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:13:31

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 2/8] irqdomain: Export remaining public API symbols.

modules making use of irq domains at the very least need access to the
add/remove/lookup routines, though there's nothing preventing them from
using the remainder of the public API, either.

The current set of exports seem primarily geared at DT-enabled platforms
using DT-backed IRQ domains, where many of the API accesses are hidden
away in OF code. The non-DT cases need to do most of this on their own.

Signed-off-by: Paul Mundt <[email protected]>
---
kernel/irq/irqdomain.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 9cae0b2..01d4a0d 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -122,6 +122,7 @@ void irq_domain_remove(struct irq_domain *domain)

irq_domain_free(domain);
}
+EXPORT_SYMBOL_GPL(irq_domain_remove);

static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
irq_hw_number_t hwirq)
@@ -209,6 +210,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
irq_domain_add(domain);
return domain;
}
+EXPORT_SYMBOL_GPL(irq_domain_add_legacy);

/**
* irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
@@ -238,6 +240,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
irq_domain_add(domain);
return domain;
}
+EXPORT_SYMBOL_GPL(irq_domain_add_linear);

struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
unsigned int max_irq,
@@ -252,6 +255,7 @@ struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
}
return domain;
}
+EXPORT_SYMBOL_GPL(irq_domain_add_nomap);

/**
* irq_domain_add_tree()
@@ -273,6 +277,7 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
}
return domain;
}
+EXPORT_SYMBOL_GPL(irq_domain_add_tree);

/**
* irq_find_host() - Locates a domain for a given device node
@@ -320,6 +325,7 @@ void irq_set_default_host(struct irq_domain *domain)

irq_default_domain = domain;
}
+EXPORT_SYMBOL_GPL(irq_set_default_host);

static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
irq_hw_number_t hwirq)
@@ -378,6 +384,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)

return virq;
}
+EXPORT_SYMBOL_GPL(irq_create_direct_mapping);

/**
* irq_create_mapping() - Map a hardware interrupt into linux irq space
@@ -617,6 +624,7 @@ unsigned int irq_radix_revmap_lookup(struct irq_domain *domain,
*/
return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);
}
+EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup);

/**
* irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping.
@@ -641,6 +649,7 @@ void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq,
mutex_unlock(&revmap_trees_mutex);
}
}
+EXPORT_SYMBOL_GPL(irq_radix_revmap_insert);

/**
* irq_linear_revmap() - Find a linux irq from a hw irq number.
@@ -674,6 +683,7 @@ unsigned int irq_linear_revmap(struct irq_domain *domain,

return revmap[hwirq];
}
+EXPORT_SYMBOL_GPL(irq_linear_revmap);

#ifdef CONFIG_IRQ_DOMAIN_DEBUG
static int virq_debug_show(struct seq_file *m, void *private)
--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:13:27

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 8/8] irqdomain: Support insertion of existing IRQ allocations.

For platforms that already do their own irqdesc allocation
irq_domain_associate() can be used for inserting a virq in to the
specified domain. This in turn calls back in to the domain's ->map()
routine, fur further processing by the platform.

Signed-off-by: Paul Mundt <[email protected]>
---
include/linux/irqdomain.h | 3 ++-
kernel/irq/irqdomain.c | 17 ++++++++++++-----
2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index e32d2e7..6bbebfa 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -143,7 +143,8 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
}

extern void irq_domain_remove(struct irq_domain *host);
-
+extern int irq_domain_associate(struct irq_domain *host, unsigned int virq,
+ irq_hw_number_t hwirq);
extern unsigned int irq_create_mapping(struct irq_domain *host,
irq_hw_number_t hwirq);
extern void irq_dispose_mapping(unsigned int virq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index e8ac7df..4b5eb8e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -337,13 +337,19 @@ void irq_set_default_host(struct irq_domain *domain)
}
EXPORT_SYMBOL_GPL(irq_set_default_host);

-static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
- irq_hw_number_t hwirq)
+int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq)
{
struct irq_data *irq_data = irq_get_irq_data(virq);

+ if (domain == NULL)
+ domain = irq_default_domain;
+ if (domain == NULL)
+ return -1;
+
irq_data->hwirq = hwirq;
irq_data->domain = domain;
+
if (domain->ops->map(domain, virq, hwirq)) {
pr_debug("-> mapping failed, freeing\n");
irq_data->domain = NULL;
@@ -355,6 +361,7 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,

return 0;
}
+EXPORT_SYMBOL_GPL(irq_domain_associate);

/**
* irq_create_direct_mapping() - Allocate an irq for direct mapping
@@ -387,7 +394,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
}
pr_debug("create_direct obtained virq %d\n", virq);

- if (irq_setup_virq(domain, virq, virq)) {
+ if (irq_domain_associate(domain, virq, virq)) {
irq_free_desc(virq);
return 0;
}
@@ -448,7 +455,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
return 0;
}

- if (irq_setup_virq(domain, virq, hwirq)) {
+ if (irq_domain_associate(domain, virq, hwirq)) {
if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY)
irq_free_desc(virq);
return 0;
@@ -490,7 +497,7 @@ unsigned int irq_create_identity_mapping(struct irq_domain *domain,
return 0;
}

- if (irq_setup_virq(domain, virq, hwirq)) {
+ if (irq_domain_associate(domain, virq, hwirq)) {
if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY)
irq_free_desc(virq);
return 0;
--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:13:24

by Paul Mundt

[permalink] [raw]
Subject: [PATCH 7/8] irqdomain: trivial pr_fmt conversion.

Convert to pr_fmt before things start to get out of hand and some
janitors start getting overly excited.

Signed-off-by: Paul Mundt <[email protected]>
---
kernel/irq/irqdomain.c | 36 +++++++++++++++++++-----------------
1 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index ac44781..e8ac7df 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) "irq: " fmt
+
#include <linux/debugfs.h>
#include <linux/hardirq.h>
#include <linux/interrupt.h>
@@ -124,7 +126,7 @@ void irq_domain_remove(struct irq_domain *domain)

mutex_unlock(&irq_domain_mutex);

- pr_debug("irq: Removed domain of type %d @0x%p\n",
+ pr_debug("Removed domain of type %d @0x%p\n",
domain->revmap_type, domain);

irq_domain_free(domain);
@@ -329,7 +331,7 @@ EXPORT_SYMBOL_GPL(irq_find_host);
*/
void irq_set_default_host(struct irq_domain *domain)
{
- pr_debug("irq: Default domain set to @0x%p\n", domain);
+ pr_debug("Default domain set to @0x%p\n", domain);

irq_default_domain = domain;
}
@@ -343,7 +345,7 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
irq_data->hwirq = hwirq;
irq_data->domain = domain;
if (domain->ops->map(domain, virq, hwirq)) {
- pr_debug("irq: -> mapping failed, freeing\n");
+ pr_debug("-> mapping failed, freeing\n");
irq_data->domain = NULL;
irq_data->hwirq = 0;
return -1;
@@ -374,7 +376,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)

virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
if (!virq) {
- pr_debug("irq: create_direct virq allocation failed\n");
+ pr_debug("create_direct virq allocation failed\n");
return 0;
}
if (virq >= domain->revmap_data.nomap.max_irq) {
@@ -383,7 +385,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
irq_free_desc(virq);
return 0;
}
- pr_debug("irq: create_direct obtained virq %d\n", virq);
+ pr_debug("create_direct obtained virq %d\n", virq);

if (irq_setup_virq(domain, virq, virq)) {
irq_free_desc(virq);
@@ -410,23 +412,23 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
unsigned int hint;
int virq;

- pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
+ pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);

/* Look for default domain if nececssary */
if (domain == NULL)
domain = irq_default_domain;
if (domain == NULL) {
- printk(KERN_WARNING "irq_create_mapping called for"
- " NULL domain, hwirq=%lx\n", hwirq);
+ pr_warning("irq_create_mapping called for"
+ " NULL domain, hwirq=%lx\n", hwirq);
WARN_ON(1);
return 0;
}
- pr_debug("irq: -> using domain @%p\n", domain);
+ pr_debug("-> using domain @%p\n", domain);

/* Check if mapping already exists */
virq = irq_find_mapping(domain, hwirq);
if (virq) {
- pr_debug("irq: -> existing mapping on virq %d\n", virq);
+ pr_debug("-> existing mapping on virq %d\n", virq);
return virq;
}

@@ -442,7 +444,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
if (virq <= 0)
virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
if (virq <= 0) {
- pr_debug("irq: -> virq allocation failed\n");
+ pr_debug("-> virq allocation failed\n");
return 0;
}

@@ -452,7 +454,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
return 0;
}

- pr_debug("irq: irq %lu on domain %s mapped to virtual irq %u\n",
+ pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);

return virq;
@@ -472,7 +474,7 @@ unsigned int irq_create_identity_mapping(struct irq_domain *domain,
{
int virq;

- pr_debug("irq: irq_create_identity_mapping(0x%p, 0x%lx)\n",
+ pr_debug("irq_create_identity_mapping(0x%p, 0x%lx)\n",
domain, hwirq);

if (domain == NULL)
@@ -484,7 +486,7 @@ unsigned int irq_create_identity_mapping(struct irq_domain *domain,

virq = irq_alloc_desc_at(hwirq, irq_domain_nid(domain->of_node));
if (virq < 0) {
- pr_debug("irq: -> virq allocation failed\n");
+ pr_debug("-> virq allocation failed\n");
return 0;
}

@@ -494,7 +496,7 @@ unsigned int irq_create_identity_mapping(struct irq_domain *domain,
return 0;
}

- pr_debug("irq: irq %lu identity mapped\n", hwirq);
+ pr_debug("irq %lu identity mapped\n", hwirq);

return virq;
}
@@ -522,8 +524,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
if (intsize > 0)
return intspec[0];
#endif
- printk(KERN_WARNING "irq: no irq domain found for %s !\n",
- controller->full_name);
+ pr_warning("no irq domain found for %s !\n",
+ controller->full_name);
return 0;
}

--
1.7.9.rc0.28.g0e1cf

2012-05-19 06:34:58

by Joe Perches

[permalink] [raw]
Subject: Re: [PATCH 7/8] irqdomain: trivial pr_fmt conversion.

On Sat, 2012-05-19 at 15:11 +0900, Paul Mundt wrote:
> Convert to pr_fmt before things start to get out of hand and some
> janitors start getting overly excited.

;) OK then, here's some trivia:

> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
[]
> @@ -1,3 +1,5 @@
> +#define pr_fmt(fmt) "irq: " fmt

"irqdomain: " (KBUILD_MODNAME) may be more sensible

[]
> @@ -410,23 +412,23 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
> unsigned int hint;
> int virq;
>
> - pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
> + pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);

"%s: ...", __func__, etc...

> if (domain == NULL) {
> - printk(KERN_WARNING "irq_create_mapping called for"
> - " NULL domain, hwirq=%lx\n", hwirq);
> + pr_warning("irq_create_mapping called for"
> + " NULL domain, hwirq=%lx\n", hwirq);

pr_warn("%s: called with NULL domain, hwirq=%lx\n", hwirq);

> @@ -522,8 +524,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
> if (intsize > 0)
> return intspec[0];
> #endif
> - printk(KERN_WARNING "irq: no irq domain found for %s !\n",
> - controller->full_name);
> + pr_warning("no irq domain found for %s !\n",
> + controller->full_name);

pr_warn(...)

2012-05-19 06:57:13

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH 7/8] irqdomain: trivial pr_fmt conversion.

On Fri, May 18, 2012 at 11:34:55PM -0700, Joe Perches wrote:
> On Sat, 2012-05-19 at 15:11 +0900, Paul Mundt wrote:
> > Convert to pr_fmt before things start to get out of hand and some
> > janitors start getting overly excited.
>
> ;) OK then, here's some trivia:
>
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> []
> > @@ -1,3 +1,5 @@
> > +#define pr_fmt(fmt) "irq: " fmt
>
> "irqdomain: " (KBUILD_MODNAME) may be more sensible
>
Perhaps. The point of the patch was to consolidate rather than change
behaviour. With a consolidation in place it's possible to change it to
whatever people are happy with.

> []
> > @@ -410,23 +412,23 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
> > unsigned int hint;
> > int virq;
> >
> > - pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
> > + pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
>
> "%s: ...", __func__, etc...
>
Unrelated to pr_fmt conversion. In any event, these debug calls are
unlikely to hang around for very long.

> > if (domain == NULL) {
> > - printk(KERN_WARNING "irq_create_mapping called for"
> > - " NULL domain, hwirq=%lx\n", hwirq);
> > + pr_warning("irq_create_mapping called for"
> > + " NULL domain, hwirq=%lx\n", hwirq);
>
> pr_warn("%s: called with NULL domain, hwirq=%lx\n", hwirq);
>
No. pr_warning() matches the log level, pr_warn() does not. A quick grep
also shoes more pr_warning() users than pr_warn(), so it sounds like you
have your work cut out for you. Good luck.

2012-05-19 18:32:13

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 0/8] irqdomain cleanups + identity mapping support

On Sat, 19 May 2012 15:11:40 +0900, Paul Mundt <[email protected]> wrote:
> Here's the current patch stack I've got against the irqdomain code, which
> is about what I need to start being able to reasonably start converting
> the SH INTC subsystem over to it.
>
> This whole series is also available via git at:
>
> git://github.com/pmundt/linux-sh.git common/irqdomain
>
> but I've not yet created a signed tag to pull from as there's likely
> still a fair bit of work to do. The diffstat looks innocuous enough, but
> is obviously of no real value in this case:

I'll look though and cherry pick the patches that I think are ready.

g.

2012-05-19 18:34:10

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 1/8] irqdomain: Support removal of IRQ domains.

On Sat, 19 May 2012 15:11:41 +0900, Paul Mundt <[email protected]> wrote:
> Now that IRQ domains are being used by modules it's necessary to support
> removing them, too. This adds a new irq_domain_remove() routine for doing
> the bulk of the heavy lifting. It's left as an exercise to the caller to
> ensure all mappings have been appropriatey disposed of before attempting
> to remove the domain.
>
> Signed-off-by: Paul Mundt <[email protected]>

Applied, thanks.

g.

> ---
> include/linux/irqdomain.h | 4 ++-
> kernel/irq/irqdomain.c | 61 +++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 62 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index c65740d..a796dbf 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -141,10 +141,12 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
> return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops,
> host_data);
> }
> +
> +extern void irq_domain_remove(struct irq_domain *host);
> +
> extern struct irq_domain *irq_find_host(struct device_node *node);
> extern void irq_set_default_host(struct irq_domain *host);
>
> -
> extern unsigned int irq_create_mapping(struct irq_domain *host,
> irq_hw_number_t hwirq);
> extern void irq_dispose_mapping(unsigned int virq);
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 0e0ba5f..9cae0b2 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -56,6 +56,12 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
> return domain;
> }
>
> +static void irq_domain_free(struct irq_domain *domain)
> +{
> + of_node_put(domain->of_node);
> + kfree(domain);
> +}
> +
> static void irq_domain_add(struct irq_domain *domain)
> {
> mutex_lock(&irq_domain_mutex);
> @@ -65,6 +71,58 @@ static void irq_domain_add(struct irq_domain *domain)
> domain->revmap_type, domain);
> }
>
> +/**
> + * irq_domain_remove() - Remove an irq domain.
> + * @domain: domain to remove
> + *
> + * This routine is used to remove an irq domain. The caller must ensure
> + * that all mappings within the domain have been disposed of prior to
> + * use, depending on the revmap type.
> + */
> +void irq_domain_remove(struct irq_domain *domain)
> +{
> + mutex_lock(&irq_domain_mutex);
> +
> + switch (domain->revmap_type) {
> + case IRQ_DOMAIN_MAP_LEGACY:
> + /*
> + * Legacy domains don't manage their own irq_desc
> + * allocations, we expect the caller to handle irq_desc
> + * freeing on their own.
> + */
> + break;
> + case IRQ_DOMAIN_MAP_TREE:
> + /*
> + * radix_tree_delete() takes care of destroying the root
> + * node when all entries are removed. Shout if there are
> + * any mappings left.
> + */
> + WARN_ON(domain->revmap_data.tree.height);
> + break;
> + case IRQ_DOMAIN_MAP_LINEAR:
> + kfree(domain->revmap_data.linear.revmap);
> + domain->revmap_data.linear.size = 0;
> + break;
> + case IRQ_DOMAIN_MAP_NOMAP:
> + break;
> + }
> +
> + list_del(&domain->link);
> +
> + /*
> + * If the going away domain is the default one, reset it.
> + */
> + if (unlikely(irq_default_domain == domain))
> + irq_set_default_host(NULL);
> +
> + mutex_unlock(&irq_domain_mutex);
> +
> + pr_debug("irq: Removed domain of type %d @0x%p\n",
> + domain->revmap_type, domain);
> +
> + irq_domain_free(domain);
> +}
> +
> static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
> irq_hw_number_t hwirq)
> {
> @@ -117,8 +175,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>
> if (WARN_ON(!irq_data || irq_data->domain)) {
> mutex_unlock(&irq_domain_mutex);
> - of_node_put(domain->of_node);
> - kfree(domain);
> + irq_domain_free(domain);
> return NULL;
> }
> }
> --
> 1.7.9.rc0.28.g0e1cf
>

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

2012-05-19 18:34:53

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 2/8] irqdomain: Export remaining public API symbols.

On Sat, 19 May 2012 15:11:42 +0900, Paul Mundt <[email protected]> wrote:
> modules making use of irq domains at the very least need access to the
> add/remove/lookup routines, though there's nothing preventing them from
> using the remainder of the public API, either.
>
> The current set of exports seem primarily geared at DT-enabled platforms
> using DT-backed IRQ domains, where many of the API accesses are hidden
> away in OF code. The non-DT cases need to do most of this on their own.
>
> Signed-off-by: Paul Mundt <[email protected]>

Applied, thanks.

g.

> ---
> kernel/irq/irqdomain.c | 10 ++++++++++
> 1 files changed, 10 insertions(+), 0 deletions(-)
>
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 9cae0b2..01d4a0d 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -122,6 +122,7 @@ void irq_domain_remove(struct irq_domain *domain)
>
> irq_domain_free(domain);
> }
> +EXPORT_SYMBOL_GPL(irq_domain_remove);
>
> static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
> irq_hw_number_t hwirq)
> @@ -209,6 +210,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> irq_domain_add(domain);
> return domain;
> }
> +EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
>
> /**
> * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
> @@ -238,6 +240,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
> irq_domain_add(domain);
> return domain;
> }
> +EXPORT_SYMBOL_GPL(irq_domain_add_linear);
>
> struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
> unsigned int max_irq,
> @@ -252,6 +255,7 @@ struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
> }
> return domain;
> }
> +EXPORT_SYMBOL_GPL(irq_domain_add_nomap);
>
> /**
> * irq_domain_add_tree()
> @@ -273,6 +277,7 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
> }
> return domain;
> }
> +EXPORT_SYMBOL_GPL(irq_domain_add_tree);
>
> /**
> * irq_find_host() - Locates a domain for a given device node
> @@ -320,6 +325,7 @@ void irq_set_default_host(struct irq_domain *domain)
>
> irq_default_domain = domain;
> }
> +EXPORT_SYMBOL_GPL(irq_set_default_host);
>
> static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
> irq_hw_number_t hwirq)
> @@ -378,6 +384,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
>
> return virq;
> }
> +EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
>
> /**
> * irq_create_mapping() - Map a hardware interrupt into linux irq space
> @@ -617,6 +624,7 @@ unsigned int irq_radix_revmap_lookup(struct irq_domain *domain,
> */
> return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);
> }
> +EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup);
>
> /**
> * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping.
> @@ -641,6 +649,7 @@ void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq,
> mutex_unlock(&revmap_trees_mutex);
> }
> }
> +EXPORT_SYMBOL_GPL(irq_radix_revmap_insert);
>
> /**
> * irq_linear_revmap() - Find a linux irq from a hw irq number.
> @@ -674,6 +683,7 @@ unsigned int irq_linear_revmap(struct irq_domain *domain,
>
> return revmap[hwirq];
> }
> +EXPORT_SYMBOL_GPL(irq_linear_revmap);
>
> #ifdef CONFIG_IRQ_DOMAIN_DEBUG
> static int virq_debug_show(struct seq_file *m, void *private)
> --
> 1.7.9.rc0.28.g0e1cf
>

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

2012-05-19 18:35:47

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 3/8] irqdomain: Make irq_domain_simple_map() static.

On Sat, 19 May 2012 15:11:43 +0900, Paul Mundt <[email protected]> wrote:
> Presently irq_domain_simple_map() isn't labelled as static, but there's
> no definition for it in the public irqdomain header either. At present
> all in-tree ->map users have meaningful work to do, and all others are
> using irq_domain_simple_ops directly. Make it static for now, as it can
> always be exported and added to the public API later.
>
> Signed-off-by: Paul Mundt <[email protected]>

Applied, thanks.

g.

> ---
> kernel/irq/irqdomain.c | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 01d4a0d..92e06442 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -758,8 +758,8 @@ static int __init irq_debugfs_init(void)
> __initcall(irq_debugfs_init);
> #endif /* CONFIG_IRQ_DOMAIN_DEBUG */
>
> -int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
> - irq_hw_number_t hwirq)
> +static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
> + irq_hw_number_t hwirq)
> {
> return 0;
> }
> --
> 1.7.9.rc0.28.g0e1cf
>

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

2012-05-19 18:41:40

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 4/8] irqdomain: Simple NUMA awareness.

On Sat, 19 May 2012 15:11:44 +0900, Paul Mundt <[email protected]> wrote:
> While common irqdesc allocation is node aware, the irqdomain code is not.
>
> This plugs in NUMA node id proliferation across the various allocation
> callsites by way of a new irq_domain_nid() helper. The irq_domain_nid()
> routine takes an of_node pointer instead of an irq_domain as it's also
> used for node placement of the irq domain data structure itself (at which
> point only the of_node is known). For platforms that aren't DT capable,
> we simply wrap in to numa_node_id() unconditionally.
>
> In order for this to be generally supportable, it's also necessary to
> make of_node_to_nid() generally available. This is accomplished by simply
> bumping it down further in the header.
>
> Presently we observe a number of regressions/inconsistencies on
> NUMA-capable platforms:
>
> - Platforms using irqdomains with legacy mappings, where the
> irq_descs are allocated node-local and the irqdomain data
> structure is not.
>
> - Drivers implementing irqdomains will lose node locality
> regardless of the underlying struct device's node id.
>
> Signed-off-by: Paul Mundt <[email protected]>
> ---
> include/linux/of.h | 10 +++++-----
> kernel/irq/irqdomain.c | 18 +++++++++++++-----
> 2 files changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/of.h b/include/linux/of.h
> index fa7fb1d..6478859 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -158,11 +158,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
>
> #define OF_BAD_ADDR ((u64)-1)
>
> -#ifndef of_node_to_nid
> -static inline int of_node_to_nid(struct device_node *np) { return -1; }
> -#define of_node_to_nid of_node_to_nid
> -#endif
> -
> extern struct device_node *of_find_node_by_name(struct device_node *from,
> const char *name);
> #define for_each_node_by_name(dn, name) \
> @@ -351,6 +346,11 @@ static inline int of_machine_is_compatible(const char *compat)
> #define of_match_node(_matches, _node) NULL
> #endif /* CONFIG_OF */
>
> +#ifndef of_node_to_nid
> +static inline int of_node_to_nid(struct device_node *np) { return -1; }
> +#define of_node_to_nid of_node_to_nid
> +#endif
> +
> /**
> * of_property_read_bool - Findfrom a property
> * @np: device node from which the property value is to be read.
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 92e06442..5f0ca52 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -8,6 +8,7 @@
> #include <linux/mutex.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> +#include <linux/topology.h>
> #include <linux/seq_file.h>
> #include <linux/slab.h>
> #include <linux/smp.h>
> @@ -25,6 +26,11 @@ static DEFINE_MUTEX(irq_domain_mutex);
> static DEFINE_MUTEX(revmap_trees_mutex);
> static struct irq_domain *irq_default_domain;
>
> +static inline int irq_domain_nid(struct device_node *of_node)
> +{
> + return of_node ? of_node_to_nid(of_node) : numa_node_id();
> +}
> +

I think this logic should just be rolled into of_node_to_nid()
directly instead of an irq_domain-specific helper. PowerPC and Sparc
are the only architectures doing anything special with of_node_to_nid
at the moment. I don't think anyone has bothered to define an
arch-independent binding for NUMA associations.

Otherwise this patch looks good to me.

> /**
> * irq_domain_alloc() - Allocate a new irq_domain data structure
> * @of_node: optional device-tree node of the interrupt controller
> @@ -43,7 +49,8 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
> {
> struct irq_domain *domain;
>
> - domain = kzalloc(sizeof(*domain), GFP_KERNEL);
> + domain = kzalloc_node(sizeof(*domain), GFP_KERNEL,
> + irq_domain_nid(of_node));
> if (WARN_ON(!domain))
> return NULL;
>
> @@ -226,7 +233,8 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
> struct irq_domain *domain;
> unsigned int *revmap;
>
> - revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL);
> + revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL,
> + irq_domain_nid(of_node));
> if (WARN_ON(!revmap))
> return NULL;
>
> @@ -364,7 +372,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
> BUG_ON(domain == NULL);
> WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP);
>
> - virq = irq_alloc_desc_from(1, 0);
> + virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
> if (!virq) {
> pr_debug("irq: create_direct virq allocation failed\n");
> return 0;
> @@ -430,9 +438,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
> hint = hwirq % nr_irqs;
> if (hint == 0)
> hint++;
> - virq = irq_alloc_desc_from(hint, 0);
> + virq = irq_alloc_desc_from(hint, irq_domain_nid(domain->of_node));
> if (virq <= 0)
> - virq = irq_alloc_desc_from(1, 0);
> + virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
> if (virq <= 0) {
> pr_debug("irq: -> virq allocation failed\n");
> return 0;
> --
> 1.7.9.rc0.28.g0e1cf
>

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

2012-05-19 18:42:27

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 5/8] irqdomain: Kill off duplicate definitions.

On Sat, 19 May 2012 15:11:45 +0900, Paul Mundt <[email protected]> wrote:
> Presently irqdomain.h has duplicate definitions for irq_find_host() and
> irq_set_default_host(), presumably from merge damage. Kill off the
> duplicates.
>
> Signed-off-by: Paul Mundt <[email protected]>

Applied, thanks.

g.

> ---
> include/linux/irqdomain.h | 3 ---
> 1 files changed, 0 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index a796dbf..5abb533 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -144,9 +144,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
>
> extern void irq_domain_remove(struct irq_domain *host);
>
> -extern struct irq_domain *irq_find_host(struct device_node *node);
> -extern void irq_set_default_host(struct irq_domain *host);
> -
> extern unsigned int irq_create_mapping(struct irq_domain *host,
> irq_hw_number_t hwirq);
> extern void irq_dispose_mapping(unsigned int virq);
> --
> 1.7.9.rc0.28.g0e1cf
>

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

2012-05-19 18:49:19

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 7/8] irqdomain: trivial pr_fmt conversion.

On Sat, 19 May 2012 15:11:47 +0900, Paul Mundt <[email protected]> wrote:
> Convert to pr_fmt before things start to get out of hand and some
> janitors start getting overly excited.
>
> Signed-off-by: Paul Mundt <[email protected]>

Applied, thanks.

g.

> ---
> kernel/irq/irqdomain.c | 36 +++++++++++++++++++-----------------
> 1 files changed, 19 insertions(+), 17 deletions(-)
>
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index ac44781..e8ac7df 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -1,3 +1,5 @@
> +#define pr_fmt(fmt) "irq: " fmt
> +
> #include <linux/debugfs.h>
> #include <linux/hardirq.h>
> #include <linux/interrupt.h>
> @@ -124,7 +126,7 @@ void irq_domain_remove(struct irq_domain *domain)
>
> mutex_unlock(&irq_domain_mutex);
>
> - pr_debug("irq: Removed domain of type %d @0x%p\n",
> + pr_debug("Removed domain of type %d @0x%p\n",
> domain->revmap_type, domain);
>
> irq_domain_free(domain);
> @@ -329,7 +331,7 @@ EXPORT_SYMBOL_GPL(irq_find_host);
> */
> void irq_set_default_host(struct irq_domain *domain)
> {
> - pr_debug("irq: Default domain set to @0x%p\n", domain);
> + pr_debug("Default domain set to @0x%p\n", domain);
>
> irq_default_domain = domain;
> }
> @@ -343,7 +345,7 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
> irq_data->hwirq = hwirq;
> irq_data->domain = domain;
> if (domain->ops->map(domain, virq, hwirq)) {
> - pr_debug("irq: -> mapping failed, freeing\n");
> + pr_debug("-> mapping failed, freeing\n");
> irq_data->domain = NULL;
> irq_data->hwirq = 0;
> return -1;
> @@ -374,7 +376,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
>
> virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
> if (!virq) {
> - pr_debug("irq: create_direct virq allocation failed\n");
> + pr_debug("create_direct virq allocation failed\n");
> return 0;
> }
> if (virq >= domain->revmap_data.nomap.max_irq) {
> @@ -383,7 +385,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
> irq_free_desc(virq);
> return 0;
> }
> - pr_debug("irq: create_direct obtained virq %d\n", virq);
> + pr_debug("create_direct obtained virq %d\n", virq);
>
> if (irq_setup_virq(domain, virq, virq)) {
> irq_free_desc(virq);
> @@ -410,23 +412,23 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
> unsigned int hint;
> int virq;
>
> - pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
> + pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
>
> /* Look for default domain if nececssary */
> if (domain == NULL)
> domain = irq_default_domain;
> if (domain == NULL) {
> - printk(KERN_WARNING "irq_create_mapping called for"
> - " NULL domain, hwirq=%lx\n", hwirq);
> + pr_warning("irq_create_mapping called for"
> + " NULL domain, hwirq=%lx\n", hwirq);
> WARN_ON(1);
> return 0;
> }
> - pr_debug("irq: -> using domain @%p\n", domain);
> + pr_debug("-> using domain @%p\n", domain);
>
> /* Check if mapping already exists */
> virq = irq_find_mapping(domain, hwirq);
> if (virq) {
> - pr_debug("irq: -> existing mapping on virq %d\n", virq);
> + pr_debug("-> existing mapping on virq %d\n", virq);
> return virq;
> }
>
> @@ -442,7 +444,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
> if (virq <= 0)
> virq = irq_alloc_desc_from(1, irq_domain_nid(domain->of_node));
> if (virq <= 0) {
> - pr_debug("irq: -> virq allocation failed\n");
> + pr_debug("-> virq allocation failed\n");
> return 0;
> }
>
> @@ -452,7 +454,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
> return 0;
> }
>
> - pr_debug("irq: irq %lu on domain %s mapped to virtual irq %u\n",
> + pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
> hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);
>
> return virq;
> @@ -472,7 +474,7 @@ unsigned int irq_create_identity_mapping(struct irq_domain *domain,
> {
> int virq;
>
> - pr_debug("irq: irq_create_identity_mapping(0x%p, 0x%lx)\n",
> + pr_debug("irq_create_identity_mapping(0x%p, 0x%lx)\n",
> domain, hwirq);
>
> if (domain == NULL)
> @@ -484,7 +486,7 @@ unsigned int irq_create_identity_mapping(struct irq_domain *domain,
>
> virq = irq_alloc_desc_at(hwirq, irq_domain_nid(domain->of_node));
> if (virq < 0) {
> - pr_debug("irq: -> virq allocation failed\n");
> + pr_debug("-> virq allocation failed\n");
> return 0;
> }
>
> @@ -494,7 +496,7 @@ unsigned int irq_create_identity_mapping(struct irq_domain *domain,
> return 0;
> }
>
> - pr_debug("irq: irq %lu identity mapped\n", hwirq);
> + pr_debug("irq %lu identity mapped\n", hwirq);
>
> return virq;
> }
> @@ -522,8 +524,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
> if (intsize > 0)
> return intspec[0];
> #endif
> - printk(KERN_WARNING "irq: no irq domain found for %s !\n",
> - controller->full_name);
> + pr_warning("no irq domain found for %s !\n",
> + controller->full_name);
> return 0;
> }
>
> --
> 1.7.9.rc0.28.g0e1cf
>

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

2012-05-19 20:21:44

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 6/8] irqdomain: Support identity mapped VIRQ allocation.

On Sat, 19 May 2012 15:11:46 +0900, Paul Mundt <[email protected]> wrote:
> This adds a new irq_create_identity_mapping() routine to permit platforms
> to utilize 1:1 identity mapping between hardware and linux IRQs for
> domain population. The same semantics as irq_create_mapping() apply,
> though in this case we only support irqdesc allocation at a static
> location, rather than falling back on dynamic lookup.
>
> Signed-off-by: Paul Mundt <[email protected]>
> ---
> include/linux/irqdomain.h | 2 ++
> kernel/irq/irqdomain.c | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 43 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 5abb533..e32d2e7 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -149,6 +149,8 @@ extern unsigned int irq_create_mapping(struct irq_domain *host,
> 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_identity_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);
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 5f0ca52..ac44781 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -459,6 +459,47 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
> }
> EXPORT_SYMBOL_GPL(irq_create_mapping);
>
> +/**
> + * irq_create_identity_mapping() - Allocate an identity mapped irq
> + * @domain: domain owning this hardware interrupt or NULL for default domain
> + * @hwirq: hardware irq number in that domain space
> + *
> + * This routine is used to allocate IRQs with a 1:1 identity mapping
> + * between the hardware and linux irq.
> + */
> +unsigned int irq_create_identity_mapping(struct irq_domain *domain,
> + irq_hw_number_t hwirq)

How about the following for an API (omitting error checking, and the
actual names are up for debate):

int irq_domain_associate_many(struct irq_domain *domain,
unsigned int irq_base,
irq_hw_number_t hwirq_base,
int count)
{
int i;
for (i = 0; i < count; i++)
irq_setup_virq(domain, irq_base + i, hwirq_base + i);
}
int irq_create_strict_mappings(struct irq_domain *domain,
unsigned int irq_base,
irq_hw_number_t hwirq_base,
int count)
{
/* Allows for non-identity, but still static mappings of a
* range of irq numbers */
irq_alloc_descs(irq_base, irq_base, irq_domain_nid(domain->of_node));
irq_domain_associate_many(domain, irq_base, hwirq, count);
...
}

/* in header */
static int irq_create_identity_mapping(struct irq_domain *domain,
irq_hw_number_t hwirq_base)
{
irq_create_strict_mappings(domain, hwirq_base, hwirq_base, 1);
}

That would give the ability to either associated for pre-allocated
irq_descs, or strict map for allocating a specific range of irqs.


> +{
> + int virq;
> +
> + pr_debug("irq: irq_create_identity_mapping(0x%p, 0x%lx)\n",
> + domain, hwirq);
> +
> + if (domain == NULL)
> + domain = irq_default_domain;

This is a new API, and I'm not a fan of the irq_default_domain usage
so I'd like just drop the above too lines. My opinion is that if your
calling into get a mapping, then the code really should know what
domain it is requesting from. If a default domain really is needed,
then there it should be explicit for the caller to find the default
domain and then pass that in to this function.

> + if (domain == NULL) {
> + WARN_ON(1);
> + return 0;
> + }
> +
> + virq = irq_alloc_desc_at(hwirq, irq_domain_nid(domain->of_node));
> + if (virq < 0) {
> + pr_debug("irq: -> virq allocation failed\n");
> + return 0;
> + }
> +
> + if (irq_setup_virq(domain, virq, hwirq)) {
> + if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY)
> + irq_free_desc(virq);
> + return 0;
> + }
> +
> + pr_debug("irq: irq %lu identity mapped\n", hwirq);
> +
> + return virq;
> +}
> +EXPORT_SYMBOL_GPL(irq_create_identity_mapping);
> +
> unsigned int irq_create_of_mapping(struct device_node *controller,
> const u32 *intspec, unsigned int intsize)
> {
> --
> 1.7.9.rc0.28.g0e1cf
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

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

2012-05-21 04:46:23

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH 4/8] irqdomain: Simple NUMA awareness.

On Sat, May 19, 2012 at 12:41:35PM -0600, Grant Likely wrote:
> On Sat, 19 May 2012 15:11:44 +0900, Paul Mundt <[email protected]> wrote:
> > +static inline int irq_domain_nid(struct device_node *of_node)
> > +{
> > + return of_node ? of_node_to_nid(of_node) : numa_node_id();
> > +}
> > +
>
> I think this logic should just be rolled into of_node_to_nid()
> directly instead of an irq_domain-specific helper. PowerPC and Sparc
> are the only architectures doing anything special with of_node_to_nid
> at the moment. I don't think anyone has bothered to define an
> arch-independent binding for NUMA associations.
>
> Otherwise this patch looks good to me.
>
Ok, that sounds fine to me. I've done that in the updated patch. We do
need to include linux/topology.h for the numa_node_id() definition, but
that seems to not cause too much trouble. Cross builds for sparc and
powerpc OF + NUMA platforms seem to hold up at least.

2012-05-21 04:55:21

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH 6/8] irqdomain: Support identity mapped VIRQ allocation.

On Sat, May 19, 2012 at 02:21:40PM -0600, Grant Likely wrote:
> On Sat, 19 May 2012 15:11:46 +0900, Paul Mundt <[email protected]> wrote:
> > This adds a new irq_create_identity_mapping() routine to permit platforms
> > to utilize 1:1 identity mapping between hardware and linux IRQs for
> > domain population. The same semantics as irq_create_mapping() apply,
> > though in this case we only support irqdesc allocation at a static
> > location, rather than falling back on dynamic lookup.
> >
> How about the following for an API (omitting error checking, and the
> actual names are up for debate):
>
> int irq_domain_associate_many(struct irq_domain *domain,
> unsigned int irq_base,
> irq_hw_number_t hwirq_base,
> int count)
> {
> int i;
> for (i = 0; i < count; i++)
> irq_setup_virq(domain, irq_base + i, hwirq_base + i);
> }
> int irq_create_strict_mappings(struct irq_domain *domain,
> unsigned int irq_base,
> irq_hw_number_t hwirq_base,
> int count)
> {
> /* Allows for non-identity, but still static mappings of a
> * range of irq numbers */
> irq_alloc_descs(irq_base, irq_base, irq_domain_nid(domain->of_node));
> irq_domain_associate_many(domain, irq_base, hwirq, count);
> ...
> }
>
> /* in header */
> static int irq_create_identity_mapping(struct irq_domain *domain,
> irq_hw_number_t hwirq_base)
> {
> irq_create_strict_mappings(domain, hwirq_base, hwirq_base, 1);
> }
>
> That would give the ability to either associated for pre-allocated
> irq_descs, or strict map for allocating a specific range of irqs.
>
That's cleaner than what I had, so it looks good to me. This is what I've
implemented in the updated patch.

I've still provided irq_domain_associate() in addition to the _many()
case to support non-linear association. I'll probably start out by doing
the sh intc conversion using this API alongside the radix tree, and then
gradually converting over to having the irqdomain code do all of my irq
desc management for me.

> This is a new API, and I'm not a fan of the irq_default_domain usage
> so I'd like just drop the above too lines. My opinion is that if your
> calling into get a mapping, then the code really should know what
> domain it is requesting from. If a default domain really is needed,
> then there it should be explicit for the caller to find the default
> domain and then pass that in to this function.
>
Yes, agreed. Adding something like irq_get_default_domain() is trivial if
and when a need arises.

Updated patches to follow.