Merge remote-tracking branch 'lsk/v3.10/topic/of' into linux-linaro-lsk
authorMark Brown <broonie@kernel.org>
Mon, 16 Feb 2015 07:57:48 +0000 (16:57 +0900)
committerMark Brown <broonie@kernel.org>
Mon, 16 Feb 2015 07:57:48 +0000 (16:57 +0900)
Conflicts:
arch/powerpc/kernel/prom.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/selftest.c
include/linux/of.h

12 files changed:
1  2 
arch/powerpc/kernel/prom.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/hotplug-memory.c
arch/powerpc/platforms/pseries/setup.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/base.c
drivers/of/fdt.c
drivers/of/selftest.c
fs/proc/root.c
include/linux/of.h

index fe0c17dcfbd7d0e706a3d5d85630c6255bed11a1,03883589c5c4ed6abaeb05a1d97529da9f96645d..bbfd8b75c77f88303b41af1d02dabd3551a59fa3
@@@ -757,80 -756,45 +757,10 @@@ struct device_node *of_find_next_cache_
        return NULL;
  }
  
- #ifdef CONFIG_PPC_PSERIES
- /*
-  * Fix up the uninitialized fields in a new device node:
-  * name, type and pci-specific fields
-  */
- static int of_finish_dynamic_node(struct device_node *node)
- {
-       struct device_node *parent = of_get_parent(node);
-       int err = 0;
-       const phandle *ibm_phandle;
-       node->name = of_get_property(node, "name", NULL);
-       node->type = of_get_property(node, "device_type", NULL);
-       if (!node->name)
-               node->name = "<NULL>";
-       if (!node->type)
-               node->type = "<NULL>";
-       if (!parent) {
-               err = -ENODEV;
-               goto out;
-       }
-       /* We don't support that function on PowerMac, at least
-        * not yet
-        */
-       if (machine_is(powermac))
-               return -ENODEV;
-       /* fix up new node's phandle field */
-       if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL)))
-               node->phandle = *ibm_phandle;
- out:
-       of_node_put(parent);
-       return err;
- }
- static int prom_reconfig_notifier(struct notifier_block *nb,
-                                 unsigned long action, void *node)
- {
-       int err;
-       switch (action) {
-       case OF_RECONFIG_ATTACH_NODE:
-               err = of_finish_dynamic_node(node);
-               if (err < 0)
-                       printk(KERN_ERR "finish_node returned %d\n", err);
-               break;
-       default:
-               err = 0;
-               break;
-       }
-       return notifier_from_errno(err);
- }
- static struct notifier_block prom_reconfig_nb = {
-       .notifier_call = prom_reconfig_notifier,
-       .priority = 10, /* This one needs to run first */
- };
- static int __init prom_reconfig_setup(void)
- {
-       return of_reconfig_notifier_register(&prom_reconfig_nb);
- }
- __initcall(prom_reconfig_setup);
- #endif
- bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
  {
 -      int hardid;
 -      struct device_node *np;
 -
 -      hardid = get_hard_smp_processor_id(cpu);
 -
 -      for_each_node_by_type(np, "cpu") {
 -              const u32 *intserv;
 -              unsigned int plen, t;
 -
 -              /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
 -               * fallback to "reg" property and assume no threads
 -               */
 -              intserv = of_get_property(np, "ibm,ppc-interrupt-server#s",
 -                              &plen);
 -              if (intserv == NULL) {
 -                      const u32 *reg = of_get_property(np, "reg", NULL);
 -                      if (reg == NULL)
 -                              continue;
 -                      if (*reg == hardid) {
 -                              if (thread)
 -                                      *thread = 0;
 -                              return np;
 -                      }
 -              } else {
 -                      plen /= sizeof(u32);
 -                      for (t = 0; t < plen; t++) {
 -                              if (hardid == intserv[t]) {
 -                                      if (thread)
 -                                              *thread = t;
 -                                      return np;
 -                              }
 -                      }
 -              }
 -      }
 -      return NULL;
 +      return (int)phys_id == get_hard_smp_processor_id(cpu);
  }
 -EXPORT_SYMBOL(of_get_cpu_node);
  
  #if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
  static struct debugfs_blob_wrapper flat_dt_blob;
Simple merge
index a7bb5da6a96bfe5d8a38e7ea53faafbc87b77f0e,78384870b33710f447e717bf3fe6add962efbd39..b51ebc38fd7e0241668384843d6627a489596839
@@@ -84,10 -75,7 +76,13 @@@ config OF_MT
        depends on MTD
        def_bool y
  
 +config OF_RESERVED_MEM
 +      depends on OF_EARLY_FLATTREE
 +      bool
 +      help
 +        Helpers to allow for reservation of memory regions
 +
+ config OF_RESOLVE
+       bool
  endmenu # OF
index 2aaa7b90fc14ea2d1d3f143d48ff9a74e2e03f5b,3841eb368ccca307d308c9f192bd0a2736b2f419..c1933a40f6b3e53abf96f87413672ca06b842d1e
@@@ -11,6 -12,4 +12,7 @@@ obj-$(CONFIG_OF_MDIO) += of_mdio.
  obj-$(CONFIG_OF_PCI)  += of_pci.o
  obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
  obj-$(CONFIG_OF_MTD)  += of_mtd.o
 +obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
+ obj-$(CONFIG_OF_RESOLVE)  += resolver.o
 +
 +CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt
index fe11d06be0a82e263a9ac40e7639d868d47eb42e,4a2cf4f70f4796de9928db02d841bccc7e497349..f0668356867bbbaceb514d4205597bcbdaf9be6d
   *      2 of the License, or (at your option) any later version.
   */
  #include <linux/ctype.h>
 +#include <linux/cpu.h>
  #include <linux/module.h>
  #include <linux/of.h>
 +#include <linux/of_graph.h>
  #include <linux/spinlock.h>
  #include <linux/slab.h>
+ #include <linux/string.h>
  #include <linux/proc_fs.h>
  
  #include "of_private.h"
index fa951c30a1c5d1566cc8b6423362ed1af63b6d3f,acbd3699be75afbd7bbd384ebae5b807d7af8fa1..42fcf572ebfe0526f46d79fa5355b9dc8442c04c
@@@ -187,20 -232,27 +188,19 @@@ static void * unflatten_dt_node(struct 
                                dad->next->sibling = np;
                        dad->next = np;
                }
-               kref_init(&np->kref);
        }
        /* process properties */
 -      while (1) {
 -              u32 sz, noff;
 -              char *pname;
 -
 -              tag = be32_to_cpup((__be32 *)(*p));
 -              if (tag == OF_DT_NOP) {
 -                      *p += 4;
 -                      continue;
 -              }
 -              if (tag != OF_DT_PROP)
 +      for (offset = fdt_first_property_offset(blob, *poffset);
 +           (offset >= 0);
 +           (offset = fdt_next_property_offset(blob, offset))) {
 +              const char *pname;
 +              u32 sz;
 +
 +              if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) {
 +                      offset = -FDT_ERR_INTERNAL;
                        break;
 -              *p += 4;
 -              sz = be32_to_cpup((__be32 *)(*p));
 -              noff = be32_to_cpup((__be32 *)((*p) + 4));
 -              *p += 8;
 -              if (be32_to_cpu(blob->version) < 0x10)
 -                      *p = ALIGN(*p, sz >= 8 ? 8 : 4);
 -
 -              pname = of_fdt_get_string(blob, noff);
 +              }
 +
                if (pname == NULL) {
                        pr_info("Can't find property name in list !\n");
                        break;
index f5e8dc7a725c201cd8c9a13b79ad8257c1428f14,93058d08f70b976350eb14e062297f750b91c617..825d89cbfde283cbcdb46e4f5eda9f24ade1447a
@@@ -146,68 -151,90 +152,143 @@@ static void __init of_selftest_property
        rc = of_property_match_string(np, "phandle-list-names", "third");
        selftest(rc == 2, "third expected:0 got:%i\n", rc);
        rc = of_property_match_string(np, "phandle-list-names", "fourth");
 -      selftest(rc == -ENODATA, "unmatched string; rc=%i", rc);
 +      selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc);
        rc = of_property_match_string(np, "missing-property", "blah");
 -      selftest(rc == -EINVAL, "missing property; rc=%i", rc);
 +      selftest(rc == -EINVAL, "missing property; rc=%i\n", rc);
        rc = of_property_match_string(np, "empty-property", "blah");
 -      selftest(rc == -ENODATA, "empty property; rc=%i", rc);
 +      selftest(rc == -ENODATA, "empty property; rc=%i\n", rc);
        rc = of_property_match_string(np, "unterminated-string", "blah");
 -      selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
 +      selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
 +
 +      /* of_property_count_strings() tests */
 +      rc = of_property_count_strings(np, "string-property");
 +      selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
 +      rc = of_property_count_strings(np, "phandle-list-names");
 +      selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
 +      rc = of_property_count_strings(np, "unterminated-string");
 +      selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
 +      rc = of_property_count_strings(np, "unterminated-string-list");
 +      selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);
 +
 +      /* of_property_read_string_index() tests */
 +      rc = of_property_read_string_index(np, "string-property", 0, strings);
 +      selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc);
 +      strings[0] = NULL;
 +      rc = of_property_read_string_index(np, "string-property", 1, strings);
 +      selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
 +      rc = of_property_read_string_index(np, "phandle-list-names", 0, strings);
 +      selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
 +      rc = of_property_read_string_index(np, "phandle-list-names", 1, strings);
 +      selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc);
 +      rc = of_property_read_string_index(np, "phandle-list-names", 2, strings);
 +      selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc);
 +      strings[0] = NULL;
 +      rc = of_property_read_string_index(np, "phandle-list-names", 3, strings);
 +      selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
 +      strings[0] = NULL;
 +      rc = of_property_read_string_index(np, "unterminated-string", 0, strings);
 +      selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
 +      rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings);
 +      selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
 +      strings[0] = NULL;
 +      rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */
 +      selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
 +      strings[1] = NULL;
 +
 +      /* of_property_read_string_array() tests */
 +      rc = of_property_read_string_array(np, "string-property", strings, 4);
 +      selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
 +      rc = of_property_read_string_array(np, "phandle-list-names", strings, 4);
 +      selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
 +      rc = of_property_read_string_array(np, "unterminated-string", strings, 4);
 +      selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
 +      /* -- An incorrectly formed string should cause a failure */
 +      rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4);
 +      selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);
 +      /* -- parsing the correctly formed strings should still work: */
 +      strings[2] = NULL;
 +      rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2);
 +      selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc);
 +      strings[1] = NULL;
 +      rc = of_property_read_string_array(np, "phandle-list-names", strings, 1);
 +      selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]);
  }
  
+ #define propcmp(p1, p2) (((p1)->length == (p2)->length) && \
+                       (p1)->value && (p2)->value && \
+                       !memcmp((p1)->value, (p2)->value, (p1)->length) && \
+                       !strcmp((p1)->name, (p2)->name))
+ static void __init of_selftest_property_copy(void)
+ {
+ #ifdef CONFIG_OF_DYNAMIC
+       struct property p1 = { .name = "p1", .length = 0, .value = "" };
+       struct property p2 = { .name = "p2", .length = 5, .value = "abcd" };
+       struct property *new;
+       new = __of_prop_dup(&p1, GFP_KERNEL);
+       selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n");
+       kfree(new->value);
+       kfree(new->name);
+       kfree(new);
+       new = __of_prop_dup(&p2, GFP_KERNEL);
+       selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n");
+       kfree(new->value);
+       kfree(new->name);
+       kfree(new);
+ #endif
+ }
+ static void __init of_selftest_changeset(void)
+ {
+ #ifdef CONFIG_OF_DYNAMIC
+       struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" };
+       struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" };
+       struct property *ppremove;
+       struct device_node *n1, *n2, *n21, *nremove, *parent;
+       struct of_changeset chgset;
+       of_changeset_init(&chgset);
+       n1 = __of_node_alloc("/testcase-data/changeset/n1", GFP_KERNEL);
+       selftest(n1, "testcase setup failure\n");
+       n2 = __of_node_alloc("/testcase-data/changeset/n2", GFP_KERNEL);
+       selftest(n2, "testcase setup failure\n");
+       n21 = __of_node_alloc("/testcase-data/changeset/n2/n21", GFP_KERNEL);
+       selftest(n21, "testcase setup failure %p\n", n21);
+       nremove = of_find_node_by_path("/testcase-data/changeset/node-remove");
+       selftest(nremove, "testcase setup failure\n");
+       ppadd = __of_prop_dup(&padd, GFP_KERNEL);
+       selftest(ppadd, "testcase setup failure\n");
+       ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL);
+       selftest(ppupdate, "testcase setup failure\n");
+       parent = nremove->parent;
+       n1->parent = parent;
+       n2->parent = parent;
+       n21->parent = n2;
+       n2->child = n21;
+       ppremove = of_find_property(parent, "prop-remove", NULL);
+       selftest(ppremove, "failed to find removal prop");
+       of_changeset_init(&chgset);
+       selftest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n");
+       selftest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n");
+       selftest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n");
+       selftest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n");
+       selftest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n");
+       selftest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
+       selftest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
+       mutex_lock(&of_mutex);
+       selftest(!of_changeset_apply(&chgset), "apply failed\n");
+       mutex_unlock(&of_mutex);
+       mutex_lock(&of_mutex);
+       selftest(!of_changeset_revert(&chgset), "revert failed\n");
+       mutex_unlock(&of_mutex);
+       of_changeset_destroy(&chgset);
+ #endif
+ }
  static int __init of_selftest(void)
  {
        struct device_node *np;
  
        pr_info("start of selftest - you will see error messages\n");
        of_selftest_parse_phandle_with_args();
-       pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
+       of_selftest_property_match_string();
+       of_selftest_property_copy();
+       of_selftest_changeset();
 +      of_selftest_property_string();
+       pr_info("end of selftest - %i passed, %i failed\n",
+               selftest_results.passed, selftest_results.failed);
        return 0;
  }
  late_initcall(of_selftest);
diff --cc fs/proc/root.c
Simple merge
index ae6e390be7a5ada815748c4dd68dab5e8c4b4c6c,1596e3352326a6b759e3d49788f6402bfff230e2..2cde26e9fb5fa24c59079f723de9c5b64ec4f5b4
@@@ -539,69 -586,73 +585,137 @@@ static inline int of_node_to_nid(struc
  #endif
  
  /**
 + * of_property_read_string_array() - Read an array of strings from a multiple
 + * strings property.
 + * @np:               device node from which the property value is to be read.
 + * @propname: name of the property to be searched.
 + * @out_strs: output array of string pointers.
 + * @sz:               number of array elements to read.
 + *
 + * Search for a property in a device tree node and retrieve a list of
 + * terminated string values (pointer to data, not a copy) in that property.
 + *
 + * If @out_strs is NULL, the number of strings in the property is returned.
 + */
 +static inline int of_property_read_string_array(struct device_node *np,
 +                                              const char *propname, const char **out_strs,
 +                                              size_t sz)
 +{
 +      return of_property_read_string_helper(np, propname, out_strs, sz, 0);
 +}
 +
 +/**
 + * of_property_count_strings() - Find and return the number of strings from a
 + * multiple strings property.
 + * @np:               device node from which the property value is to be read.
 + * @propname: name of the property to be searched.
 + *
 + * Search for a property in a device tree node and retrieve the number of null
 + * terminated string contain in it. Returns the number of strings on
 + * success, -EINVAL if the property does not exist, -ENODATA if property
 + * does not have a value, and -EILSEQ if the string is not null-terminated
 + * within the length of the property data.
 + */
 +static inline int of_property_count_strings(struct device_node *np,
 +                                          const char *propname)
 +{
 +      return of_property_read_string_helper(np, propname, NULL, 0, 0);
 +}
 +
 +/**
 + * of_property_read_string_index() - Find and read a string from a multiple
 + * strings property.
 + * @np:               device node from which the property value is to be read.
 + * @propname: name of the property to be searched.
 + * @index:    index of the string in the list of strings
 + * @out_string:       pointer to null terminated return string, modified only if
 + *            return value is 0.
 + *
 + * Search for a property in a device tree node and retrieve a null
 + * terminated string value (pointer to data, not a copy) in the list of strings
 + * contained in that property.
 + * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
 + * property does not have a value, and -EILSEQ if the string is not
 + * null-terminated within the length of the property data.
 + *
 + * The out_string pointer is modified only if a valid string can be decoded.
 + */
 +static inline int of_property_read_string_index(struct device_node *np,
 +                                              const char *propname,
 +                                              int index, const char **output)
 +{
 +      int rc = of_property_read_string_helper(np, propname, output, 1, index);
 +      return rc < 0 ? rc : 0;
 +}
 +
++/*
+  * of_property_count_u8_elems - Count the number of u8 elements in a property
+  *
+  * @np:               device node from which the property value is to be read.
+  * @propname: name of the property to be searched.
+  *
+  * Search for a property in a device node and count the number of u8 elements
+  * in it. Returns number of elements on sucess, -EINVAL if the property does
+  * not exist or its length does not match a multiple of u8 and -ENODATA if the
+  * property does not have a value.
+  */
+ static inline int of_property_count_u8_elems(const struct device_node *np,
+                               const char *propname)
+ {
+       return of_property_count_elems_of_size(np, propname, sizeof(u8));
+ }
+ /**
+  * of_property_count_u16_elems - Count the number of u16 elements in a property
+  *
+  * @np:               device node from which the property value is to be read.
+  * @propname: name of the property to be searched.
+  *
+  * Search for a property in a device node and count the number of u16 elements
+  * in it. Returns number of elements on sucess, -EINVAL if the property does
+  * not exist or its length does not match a multiple of u16 and -ENODATA if the
+  * property does not have a value.
+  */
+ static inline int of_property_count_u16_elems(const struct device_node *np,
+                               const char *propname)
+ {
+       return of_property_count_elems_of_size(np, propname, sizeof(u16));
+ }
+ /**
+  * of_property_count_u32_elems - Count the number of u32 elements in a property
+  *
+  * @np:               device node from which the property value is to be read.
+  * @propname: name of the property to be searched.
+  *
+  * Search for a property in a device node and count the number of u32 elements
+  * in it. Returns number of elements on sucess, -EINVAL if the property does
+  * not exist or its length does not match a multiple of u32 and -ENODATA if the
+  * property does not have a value.
+  */
+ static inline int of_property_count_u32_elems(const struct device_node *np,
+                               const char *propname)
+ {
+       return of_property_count_elems_of_size(np, propname, sizeof(u32));
+ }
+ /**
+  * of_property_count_u64_elems - Count the number of u64 elements in a property
+  *
+  * @np:               device node from which the property value is to be read.
+  * @propname: name of the property to be searched.
+  *
+  * Search for a property in a device node and count the number of u64 elements
+  * in it. Returns number of elements on sucess, -EINVAL if the property does
+  * not exist or its length does not match a multiple of u64 and -ENODATA if the
+  * property does not have a value.
+  */
+ static inline int of_property_count_u64_elems(const struct device_node *np,
+                               const char *propname)
+ {
+       return of_property_count_elems_of_size(np, propname, sizeof(u64));
+ }
  /**
   * of_property_read_bool - Findfrom a property
   * @np:               device node from which the property value is to be read.