aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2016-05-03 09:22:51 -0400
committerRob Herring <robh@kernel.org>2016-05-16 08:22:35 -0400
commit83262418b0ef8bda66eca7c72d4c24ae6f7b230e (patch)
treee0eca40010efc061ba901a13ca42ec12a461eec0
parentc4263233f30e72f2645ff83c9074c994f88b015a (diff)
drivers/of: Return allocated memory from of_fdt_unflatten_tree()
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>
-rw-r--r--drivers/of/fdt.c33
-rw-r--r--include/linux/of_fdt.h6
2 files changed, 25 insertions, 14 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 0d53687d4b8c..ef1ccee51af8 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -454,11 +454,14 @@ static int unflatten_dt_nodes(const void *blob,
454 * @mynodes: The device_node tree created by the call 454 * @mynodes: The device_node tree created by the call
455 * @dt_alloc: An allocator that provides a virtual address to memory 455 * @dt_alloc: An allocator that provides a virtual address to memory
456 * for the resulting tree 456 * for the resulting tree
457 *
458 * Returns NULL on failure or the memory chunk containing the unflattened
459 * device tree on success.
457 */ 460 */
458static void __unflatten_device_tree(const void *blob, 461static void *__unflatten_device_tree(const void *blob,
459 struct device_node *dad, 462 struct device_node *dad,
460 struct device_node **mynodes, 463 struct device_node **mynodes,
461 void * (*dt_alloc)(u64 size, u64 align)) 464 void *(*dt_alloc)(u64 size, u64 align))
462{ 465{
463 int size; 466 int size;
464 void *mem; 467 void *mem;
@@ -467,7 +470,7 @@ static void __unflatten_device_tree(const void *blob,
467 470
468 if (!blob) { 471 if (!blob) {
469 pr_debug("No device tree pointer\n"); 472 pr_debug("No device tree pointer\n");
470 return; 473 return NULL;
471 } 474 }
472 475
473 pr_debug("Unflattening device tree:\n"); 476 pr_debug("Unflattening device tree:\n");
@@ -477,13 +480,13 @@ static void __unflatten_device_tree(const void *blob,
477 480
478 if (fdt_check_header(blob)) { 481 if (fdt_check_header(blob)) {
479 pr_err("Invalid device tree blob header\n"); 482 pr_err("Invalid device tree blob header\n");
480 return; 483 return NULL;
481 } 484 }
482 485
483 /* First pass, scan for size */ 486 /* First pass, scan for size */
484 size = unflatten_dt_nodes(blob, NULL, dad, NULL); 487 size = unflatten_dt_nodes(blob, NULL, dad, NULL);
485 if (size < 0) 488 if (size < 0)
486 return; 489 return NULL;
487 490
488 size = ALIGN(size, 4); 491 size = ALIGN(size, 4);
489 pr_debug(" size is %d, allocating...\n", size); 492 pr_debug(" size is %d, allocating...\n", size);
@@ -503,6 +506,7 @@ static void __unflatten_device_tree(const void *blob,
503 be32_to_cpup(mem + size)); 506 be32_to_cpup(mem + size));
504 507
505 pr_debug(" <- unflatten_device_tree()\n"); 508 pr_debug(" <- unflatten_device_tree()\n");
509 return mem;
506} 510}
507 511
508static void *kernel_tree_alloc(u64 size, u64 align) 512static void *kernel_tree_alloc(u64 size, u64 align)
@@ -522,14 +526,21 @@ static DEFINE_MUTEX(of_fdt_unflatten_mutex);
522 * tree of struct device_node. It also fills the "name" and "type" 526 * tree of struct device_node. It also fills the "name" and "type"
523 * pointers of the nodes so the normal device-tree walking functions 527 * pointers of the nodes so the normal device-tree walking functions
524 * can be used. 528 * can be used.
529 *
530 * Returns NULL on failure or the memory chunk containing the unflattened
531 * device tree on success.
525 */ 532 */
526void of_fdt_unflatten_tree(const unsigned long *blob, 533void *of_fdt_unflatten_tree(const unsigned long *blob,
527 struct device_node *dad, 534 struct device_node *dad,
528 struct device_node **mynodes) 535 struct device_node **mynodes)
529{ 536{
537 void *mem;
538
530 mutex_lock(&of_fdt_unflatten_mutex); 539 mutex_lock(&of_fdt_unflatten_mutex);
531 __unflatten_device_tree(blob, dad, mynodes, &kernel_tree_alloc); 540 mem = __unflatten_device_tree(blob, dad, mynodes, &kernel_tree_alloc);
532 mutex_unlock(&of_fdt_unflatten_mutex); 541 mutex_unlock(&of_fdt_unflatten_mutex);
542
543 return mem;
533} 544}
534EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); 545EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
535 546
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 1bffcbd56f8e..901ec01c9fba 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -37,9 +37,9 @@ extern bool of_fdt_is_big_endian(const void *blob,
37 unsigned long node); 37 unsigned long node);
38extern int of_fdt_match(const void *blob, unsigned long node, 38extern int of_fdt_match(const void *blob, unsigned long node,
39 const char *const *compat); 39 const char *const *compat);
40extern void of_fdt_unflatten_tree(const unsigned long *blob, 40extern void *of_fdt_unflatten_tree(const unsigned long *blob,
41 struct device_node *dad, 41 struct device_node *dad,
42 struct device_node **mynodes); 42 struct device_node **mynodes);
43 43
44/* TBD: Temporary export of fdt globals - remove when code fully merged */ 44/* TBD: Temporary export of fdt globals - remove when code fully merged */
45extern int __initdata dt_root_addr_cells; 45extern int __initdata dt_root_addr_cells;