diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-06-04 01:04:34 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-06-15 14:08:00 -0400 |
commit | 5ca4db61e859526b2dbee3bcea3626d3de49a0b2 (patch) | |
tree | abbe2bc14d1de334834b1c5ace2cbbaf2b7c1b45 | |
parent | efd68e7254503f3207805f674a1ea1d743f5dfe2 (diff) |
irqdomain: Simple NUMA awareness.
While common irqdesc allocation is node aware, the irqdomain code is not.
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.
This plugs in NUMA node id proliferation across the various allocation
callsites by way of_node_to_nid() node lookup. While of_node_to_nid()
does the right thing for OF-capable platforms it doesn't presently handle
the non-DT case. This is trivially dealt with by simply wraping in to
numa_node_id() unconditionally.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r-- | include/linux/of.h | 15 | ||||
-rw-r--r-- | kernel/irq/irqdomain.c | 13 |
2 files changed, 18 insertions, 10 deletions
diff --git a/include/linux/of.h b/include/linux/of.h index 1012377cae92..76930ee78db5 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/kref.h> | 21 | #include <linux/kref.h> |
22 | #include <linux/mod_devicetable.h> | 22 | #include <linux/mod_devicetable.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/topology.h> | ||
24 | 25 | ||
25 | #include <asm/byteorder.h> | 26 | #include <asm/byteorder.h> |
26 | #include <asm/errno.h> | 27 | #include <asm/errno.h> |
@@ -158,11 +159,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) | |||
158 | 159 | ||
159 | #define OF_BAD_ADDR ((u64)-1) | 160 | #define OF_BAD_ADDR ((u64)-1) |
160 | 161 | ||
161 | #ifndef of_node_to_nid | ||
162 | static inline int of_node_to_nid(struct device_node *np) { return -1; } | ||
163 | #define of_node_to_nid of_node_to_nid | ||
164 | #endif | ||
165 | |||
166 | static inline const char* of_node_full_name(struct device_node *np) | 162 | static inline const char* of_node_full_name(struct device_node *np) |
167 | { | 163 | { |
168 | return np ? np->full_name : "<no-node>"; | 164 | return np ? np->full_name : "<no-node>"; |
@@ -412,6 +408,15 @@ static inline int of_machine_is_compatible(const char *compat) | |||
412 | while (0) | 408 | while (0) |
413 | #endif /* CONFIG_OF */ | 409 | #endif /* CONFIG_OF */ |
414 | 410 | ||
411 | #ifndef of_node_to_nid | ||
412 | static inline int of_node_to_nid(struct device_node *np) | ||
413 | { | ||
414 | return numa_node_id(); | ||
415 | } | ||
416 | |||
417 | #define of_node_to_nid of_node_to_nid | ||
418 | #endif | ||
419 | |||
415 | /** | 420 | /** |
416 | * of_property_read_bool - Findfrom a property | 421 | * of_property_read_bool - Findfrom a property |
417 | * @np: device node from which the property value is to be read. | 422 | * @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 38c5eb839c92..79ae0ebb90ba 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
12 | #include <linux/of_address.h> | 12 | #include <linux/of_address.h> |
13 | #include <linux/topology.h> | ||
13 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include <linux/smp.h> | 16 | #include <linux/smp.h> |
@@ -45,7 +46,8 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node, | |||
45 | { | 46 | { |
46 | struct irq_domain *domain; | 47 | struct irq_domain *domain; |
47 | 48 | ||
48 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | 49 | domain = kzalloc_node(sizeof(*domain), GFP_KERNEL, |
50 | of_node_to_nid(of_node)); | ||
49 | if (WARN_ON(!domain)) | 51 | if (WARN_ON(!domain)) |
50 | return NULL; | 52 | return NULL; |
51 | 53 | ||
@@ -229,7 +231,8 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node, | |||
229 | struct irq_domain *domain; | 231 | struct irq_domain *domain; |
230 | unsigned int *revmap; | 232 | unsigned int *revmap; |
231 | 233 | ||
232 | revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL); | 234 | revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL, |
235 | of_node_to_nid(of_node)); | ||
233 | if (WARN_ON(!revmap)) | 236 | if (WARN_ON(!revmap)) |
234 | return NULL; | 237 | return NULL; |
235 | 238 | ||
@@ -367,7 +370,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) | |||
367 | BUG_ON(domain == NULL); | 370 | BUG_ON(domain == NULL); |
368 | WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP); | 371 | WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP); |
369 | 372 | ||
370 | virq = irq_alloc_desc_from(1, 0); | 373 | virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); |
371 | if (!virq) { | 374 | if (!virq) { |
372 | pr_debug("create_direct virq allocation failed\n"); | 375 | pr_debug("create_direct virq allocation failed\n"); |
373 | return 0; | 376 | return 0; |
@@ -433,9 +436,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain, | |||
433 | hint = hwirq % nr_irqs; | 436 | hint = hwirq % nr_irqs; |
434 | if (hint == 0) | 437 | if (hint == 0) |
435 | hint++; | 438 | hint++; |
436 | virq = irq_alloc_desc_from(hint, 0); | 439 | virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node)); |
437 | if (virq <= 0) | 440 | if (virq <= 0) |
438 | virq = irq_alloc_desc_from(1, 0); | 441 | virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); |
439 | if (virq <= 0) { | 442 | if (virq <= 0) { |
440 | pr_debug("-> virq allocation failed\n"); | 443 | pr_debug("-> virq allocation failed\n"); |
441 | return 0; | 444 | return 0; |