drivers/of: Return allocated memory from of_fdt_unflatten_tree()
authorGavin Shan <gwshan@linux.vnet.ibm.com>
Tue, 3 May 2016 13:22:51 +0000 (23:22 +1000)
committerRob Herring <robh@kernel.org>
Mon, 16 May 2016 12:22:35 +0000 (07:22 -0500)
This returns the allocate memory chunk, storing the unflattened device
tree, from of_fdt_unflatten_tree() so that memory chunk can be released
on demand in PowerNV PCI hotplug driver.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Rob Herring <robh@kernel.org>
drivers/of/fdt.c
include/linux/of_fdt.h

index 0d53687..ef1ccee 100644 (file)
@@ -454,11 +454,14 @@ static int unflatten_dt_nodes(const void *blob,
  * @mynodes: The device_node tree created by the call
  * @dt_alloc: An allocator that provides a virtual address to memory
  * for the resulting tree
+ *
+ * Returns NULL on failure or the memory chunk containing the unflattened
+ * device tree on success.
  */
-static void __unflatten_device_tree(const void *blob,
-                            struct device_node *dad,
-                            struct device_node **mynodes,
-                            void * (*dt_alloc)(u64 size, u64 align))
+static void *__unflatten_device_tree(const void *blob,
+                                    struct device_node *dad,
+                                    struct device_node **mynodes,
+                                    void *(*dt_alloc)(u64 size, u64 align))
 {
        int size;
        void *mem;
@@ -467,7 +470,7 @@ static void __unflatten_device_tree(const void *blob,
 
        if (!blob) {
                pr_debug("No device tree pointer\n");
-               return;
+               return NULL;
        }
 
        pr_debug("Unflattening device tree:\n");
@@ -477,13 +480,13 @@ static void __unflatten_device_tree(const void *blob,
 
        if (fdt_check_header(blob)) {
                pr_err("Invalid device tree blob header\n");
-               return;
+               return NULL;
        }
 
        /* First pass, scan for size */
        size = unflatten_dt_nodes(blob, NULL, dad, NULL);
        if (size < 0)
-               return;
+               return NULL;
 
        size = ALIGN(size, 4);
        pr_debug("  size is %d, allocating...\n", size);
@@ -503,6 +506,7 @@ static void __unflatten_device_tree(const void *blob,
                           be32_to_cpup(mem + size));
 
        pr_debug(" <- unflatten_device_tree()\n");
+       return mem;
 }
 
 static void *kernel_tree_alloc(u64 size, u64 align)
@@ -522,14 +526,21 @@ static DEFINE_MUTEX(of_fdt_unflatten_mutex);
  * tree of struct device_node. It also fills the "name" and "type"
  * pointers of the nodes so the normal device-tree walking functions
  * can be used.
+ *
+ * Returns NULL on failure or the memory chunk containing the unflattened
+ * device tree on success.
  */
-void of_fdt_unflatten_tree(const unsigned long *blob,
-                       struct device_node *dad,
-                       struct device_node **mynodes)
+void *of_fdt_unflatten_tree(const unsigned long *blob,
+                           struct device_node *dad,
+                           struct device_node **mynodes)
 {
+       void *mem;
+
        mutex_lock(&of_fdt_unflatten_mutex);
-       __unflatten_device_tree(blob, dad, mynodes, &kernel_tree_alloc);
+       mem = __unflatten_device_tree(blob, dad, mynodes, &kernel_tree_alloc);
        mutex_unlock(&of_fdt_unflatten_mutex);
+
+       return mem;
 }
 EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
 
index 1bffcbd..901ec01 100644 (file)
@@ -37,9 +37,9 @@ extern bool of_fdt_is_big_endian(const void *blob,
                                 unsigned long node);
 extern int of_fdt_match(const void *blob, unsigned long node,
                        const char *const *compat);
-extern void of_fdt_unflatten_tree(const unsigned long *blob,
-                              struct device_node *dad,
-                              struct device_node **mynodes);
+extern void *of_fdt_unflatten_tree(const unsigned long *blob,
+                                  struct device_node *dad,
+                                  struct device_node **mynodes);
 
 /* TBD: Temporary export of fdt globals - remove when code fully merged */
 extern int __initdata dt_root_addr_cells;