Merge tag 'v3.5-rc6' into irqdomain/next
authorGrant Likely <grant.likely@secretlab.ca>
Wed, 11 Jul 2012 15:08:35 +0000 (16:08 +0100)
committerGrant Likely <grant.likely@secretlab.ca>
Wed, 11 Jul 2012 15:08:35 +0000 (16:08 +0100)
Linux 3.5-rc6

12 files changed:
Documentation/IRQ-domain.txt
arch/microblaze/pci/pci-common.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/vio.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/pseries/iommu.c
arch/sparc/kernel/of_device_64.c
drivers/of/base.c
drivers/of/irq.c
include/linux/irqdomain.h
include/linux/of.h
kernel/irq/irqdomain.c

index 27dcaabfb4db2f186bb6df8c5fb016a049c2d2d4..1401cece745ae46ce74fcb8c6a319aa05be7a318 100644 (file)
@@ -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.
index ed22bfc5db1476829179e4ebbda3a90322416b70..ca8f6e76996026b42f1d8fcd034ad17948f60b05 100644 (file)
@@ -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);
 
index 8e78e93c818536b4a33a1ae29f10b3d157b29e63..886c254fd565742abeffbf88203ac2681451bebb 100644 (file)
@@ -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);
index cb87301ccd55a63a46f3069efe3b860e3da5c3c8..63f72ede4341c99b224f24da7b9c68076e5c00fb 100644 (file)
@@ -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,
index b9f509a34c012b672e3b368f8121d9446b52d2ee..b6732004c882ea6275cd7c3f3ef345e36800b0d5 100644 (file)
@@ -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);
index 2d311c0caf8ef4499a3a54ebdb24f0c4e41c8735..6b58a395dff67f2cf29aa3c2a3bef33b1ba93142 100644 (file)
@@ -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);
index 7a3be6f6737a0e4ce6beeeec1be866c9b65e747a..7bbdc26d95126e6ca56c946c8b4f1b59eb7ea256 100644 (file)
@@ -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;
index eada3f4ef80100de1e0c3f8f2a236acff6e662a2..c499cc817c172da4f8c52e9cbae683c8b8cdfbdd 100644 (file)
@@ -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));
 }
 
 /**
index 9cf00602f5665b289d1279666504af0010a3fa0f..ff8ab7b27373bd58e31070a366ed0e48217ecceb 100644 (file)
@@ -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;
index 5abb533eb8eb2a68a1645423ed0b8c6e2d0e94fa..17b60be30fff3d4b1b96348b4e711679766ce6e0 100644 (file)
@@ -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,
index 2ec1083af7ffba234db74acdd0e42d25d861b8c1..76930ee78db5f45792c884eaf51931ffa29bac16 100644 (file)
@@ -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.
index 41c1564103f1e082444a6638673d44ccf4707b35..622fdf4b82b6b4e60c36a1c7013b43982f53018c 100644 (file)
@@ -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;
 
@@ -137,6 +139,36 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
        return hwirq - first_hwirq + domain->revmap_data.legacy.first_irq;
 }
 
+/**
+ * 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.
@@ -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);