summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/IRQ-domain.txt5
-rw-r--r--arch/microblaze/pci/pci-common.c6
-rw-r--r--arch/powerpc/kernel/pci-common.c6
-rw-r--r--arch/powerpc/kernel/vio.c5
-rw-r--r--arch/powerpc/platforms/cell/iommu.c3
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c2
-rw-r--r--arch/sparc/kernel/of_device_64.c2
-rw-r--r--drivers/of/base.c2
-rw-r--r--drivers/of/irq.c2
-rw-r--r--include/linux/irqdomain.h5
-rw-r--r--include/linux/of.h23
-rw-r--r--kernel/irq/irqdomain.c70
12 files changed, 88 insertions, 43 deletions
diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt
index 27dcaabfb4d..1401cece745 100644
--- a/Documentation/IRQ-domain.txt
+++ b/Documentation/IRQ-domain.txt
@@ -93,6 +93,7 @@ Linux IRQ number into the hardware.
Most drivers cannot use this mapping.
==== Legacy ====
+irq_domain_add_simple()
irq_domain_add_legacy()
irq_domain_add_legacy_isa()
@@ -115,3 +116,7 @@ The legacy map should only be used if fixed IRQ mappings must be
supported. For example, ISA controllers would use the legacy map for
mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ
numbers.
+
+Most users of legacy mappings should use irq_domain_add_simple() which
+will use a legacy domain only if an IRQ range is supplied by the
+system and will otherwise use a linear domain mapping.
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index ed22bfc5db1..ca8f6e76996 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -249,8 +249,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
} else {
pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
oirq.size, oirq.specifier[0], oirq.specifier[1],
- oirq.controller ? oirq.controller->full_name :
- "<default>");
+ of_node_full_name(oirq.controller));
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
@@ -1493,8 +1492,7 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose)
struct pci_bus *bus;
struct device_node *node = hose->dn;
- pr_debug("PCI: Scanning PHB %s\n",
- node ? node->full_name : "<NO NAME>");
+ pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
pcibios_setup_phb_resources(hose, &resources);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 8e78e93c818..886c254fd56 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -248,8 +248,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
} else {
pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
oirq.size, oirq.specifier[0], oirq.specifier[1],
- oirq.controller ? oirq.controller->full_name :
- "<default>");
+ of_node_full_name(oirq.controller));
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
@@ -1628,8 +1627,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
struct device_node *node = hose->dn;
int mode;
- pr_debug("PCI: Scanning PHB %s\n",
- node ? node->full_name : "<NO NAME>");
+ pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
/* Get some IO space for the new PHB */
pcibios_setup_phb_io_space(hose);
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index cb87301ccd5..63f72ede434 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -1296,8 +1296,7 @@ static void __devinit vio_dev_release(struct device *dev)
struct iommu_table *tbl = get_iommu_table_base(dev);
if (tbl)
- iommu_free_table(tbl, dev->of_node ?
- dev->of_node->full_name : dev_name(dev));
+ iommu_free_table(tbl, of_node_full_name(dev->of_node));
of_node_put(dev->of_node);
kfree(to_vio_dev(dev));
}
@@ -1509,7 +1508,7 @@ static ssize_t devspec_show(struct device *dev,
{
struct device_node *of_node = dev->of_node;
- return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
+ return sprintf(buf, "%s\n", of_node_full_name(of_node));
}
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index b9f509a34c0..b6732004c88 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -552,8 +552,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
iommu = cell_iommu_for_node(dev_to_node(dev));
if (iommu == NULL || list_empty(&iommu->windows)) {
printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n",
- dev->of_node ? dev->of_node->full_name : "?",
- dev_to_node(dev));
+ of_node_full_name(dev->of_node), dev_to_node(dev));
return NULL;
}
window = list_entry(iommu->windows.next, struct iommu_window, list);
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 2d311c0caf8..6b58a395dff 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1051,7 +1051,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
if (!pdn || !PCI_DN(pdn)) {
printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
"no DMA window found for pci dev=%s dn=%s\n",
- pci_name(dev), dn? dn->full_name : "<null>");
+ pci_name(dev), of_node_full_name(dn));
return;
}
pr_debug(" parent is %s\n", pdn->full_name);
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c
index 7a3be6f6737..7bbdc26d951 100644
--- a/arch/sparc/kernel/of_device_64.c
+++ b/arch/sparc/kernel/of_device_64.c
@@ -580,7 +580,7 @@ static unsigned int __init build_one_device_irq(struct platform_device *op,
printk("%s: Apply [%s:%x] imap --> [%s:%x]\n",
op->dev.of_node->full_name,
pp->full_name, this_orig_irq,
- (iret ? iret->full_name : "NULL"), irq);
+ of_node_full_name(iret), irq);
if (!iret)
break;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index eada3f4ef80..c499cc817c1 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1195,7 +1195,7 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np,
ap->stem[stem_len] = 0;
list_add_tail(&ap->link, &aliases_lookup);
pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
- ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
+ ap->alias, ap->stem, ap->id, of_node_full_name(np));
}
/**
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 9cf00602f56..ff8ab7b2737 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -255,7 +255,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
skiplevel:
/* Iterate again with new parent */
- pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>");
+ pr_debug(" -> new parent: %s\n", of_node_full_name(newpar));
of_node_put(ipar);
ipar = newpar;
newpar = NULL;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 5abb533eb8e..17b60be30ff 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -112,6 +112,11 @@ struct irq_domain {
};
#ifdef CONFIG_IRQ_DOMAIN
+struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
+ unsigned int size,
+ unsigned int first_irq,
+ const struct irq_domain_ops *ops,
+ void *host_data);
struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
unsigned int size,
unsigned int first_irq,
diff --git a/include/linux/of.h b/include/linux/of.h
index 2ec1083af7f..76930ee78db 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -21,6 +21,7 @@
#include <linux/kref.h>
#include <linux/mod_devicetable.h>
#include <linux/spinlock.h>
+#include <linux/topology.h>
#include <asm/byteorder.h>
#include <asm/errno.h>
@@ -158,10 +159,10 @@ 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
+static inline const char* of_node_full_name(struct device_node *np)
+{
+ return np ? np->full_name : "<no-node>";
+}
extern struct device_node *of_find_node_by_name(struct device_node *from,
const char *name);
@@ -303,6 +304,11 @@ const char *of_prop_next_string(struct property *prop, const char *cur);
#else /* CONFIG_OF */
+static inline const char* of_node_full_name(struct device_node *np)
+{
+ return "<no-node>";
+}
+
static inline bool of_have_populated_dt(void)
{
return false;
@@ -402,6 +408,15 @@ static inline int of_machine_is_compatible(const char *compat)
while (0)
#endif /* CONFIG_OF */
+#ifndef of_node_to_nid
+static inline int of_node_to_nid(struct device_node *np)
+{
+ return numa_node_id();
+}
+
+#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 41c1564103f..622fdf4b82b 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -10,6 +10,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>
@@ -45,7 +46,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,
+ of_node_to_nid(of_node));
if (WARN_ON(!domain))
return NULL;
@@ -138,6 +140,36 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
}
/**
+ * irq_domain_add_simple() - Allocate and register a simple irq_domain.
+ * @of_node: pointer to interrupt controller's device tree node.
+ * @size: total number of irqs in mapping
+ * @first_irq: first number of irq block assigned to the domain
+ * @ops: map/unmap domain callbacks
+ * @host_data: Controller private data pointer
+ *
+ * Allocates a legacy irq_domain if irq_base is positive or a linear
+ * domain otherwise.
+ *
+ * This is intended to implement the expected behaviour for most
+ * interrupt controllers which is that a linear mapping should
+ * normally be used unless the system requires a legacy mapping in
+ * order to support supplying interrupt numbers during non-DT
+ * registration of devices.
+ */
+struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
+ unsigned int size,
+ unsigned int first_irq,
+ const struct irq_domain_ops *ops,
+ void *host_data)
+{
+ if (first_irq > 0)
+ return irq_domain_add_legacy(of_node, size, first_irq, 0,
+ ops, host_data);
+ else
+ return irq_domain_add_linear(of_node, size, ops, host_data);
+}
+
+/**
* irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain.
* @of_node: pointer to interrupt controller's device tree node.
* @size: total number of irqs in legacy mapping
@@ -203,7 +235,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
* one can then use irq_create_mapping() to
* explicitly change them
*/
- ops->map(domain, irq, hwirq);
+ if (ops->map)
+ ops->map(domain, irq, hwirq);
/* Clear norequest flags */
irq_clear_status_flags(irq, IRQ_NOREQUEST);
@@ -215,7 +248,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
/**
- * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
+ * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain.
* @of_node: pointer to interrupt controller's device tree node.
* @size: Number of interrupts in the domain.
* @ops: map/unmap domain callbacks
@@ -229,7 +262,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,
+ of_node_to_nid(of_node));
if (WARN_ON(!revmap))
return NULL;
@@ -337,8 +371,8 @@ 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-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
+ if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
+ pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
irq_data->domain = NULL;
irq_data->hwirq = 0;
return -1;
@@ -367,7 +401,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, of_node_to_nid(domain->of_node));
if (!virq) {
pr_debug("create_direct virq allocation failed\n");
return 0;
@@ -433,22 +467,21 @@ 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, of_node_to_nid(domain->of_node));
if (virq <= 0)
- virq = irq_alloc_desc_from(1, 0);
+ virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
if (virq <= 0) {
pr_debug("-> 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);
+ irq_free_desc(virq);
return 0;
}
pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
- hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);
+ hwirq, of_node_full_name(domain->of_node), virq);
return virq;
}
@@ -477,7 +510,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
return intspec[0];
#endif
pr_warning("no irq domain found for %s !\n",
- controller->full_name);
+ of_node_full_name(controller));
return 0;
}
@@ -725,8 +758,8 @@ static int virq_debug_show(struct seq_file *m, void *private)
data = irq_desc_get_chip_data(desc);
seq_printf(m, data ? "0x%p " : " %p ", data);
- if (desc->irq_data.domain && desc->irq_data.domain->of_node)
- p = desc->irq_data.domain->of_node->full_name;
+ if (desc->irq_data.domain)
+ p = of_node_full_name(desc->irq_data.domain->of_node);
else
p = none;
seq_printf(m, "%s\n", p);
@@ -761,12 +794,6 @@ static int __init irq_debugfs_init(void)
__initcall(irq_debugfs_init);
#endif /* CONFIG_IRQ_DOMAIN_DEBUG */
-static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- return 0;
-}
-
/**
* irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings
*
@@ -829,7 +856,6 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d,
EXPORT_SYMBOL_GPL(irq_domain_xlate_onetwocell);
const struct irq_domain_ops irq_domain_simple_ops = {
- .map = irq_domain_simple_map,
.xlate = irq_domain_xlate_onetwocell,
};
EXPORT_SYMBOL_GPL(irq_domain_simple_ops);