From: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
To: <grant.likely@secretlab.ca>, <dirk.brandewie@gmail.com>,
<devicetree-discuss@lists.ozlabs.org>,
<linuxppc-dev@lists.ozlabs.org>,
<microblaze-uclinux@itee.uq.edu.au>
Subject: [PATCH 7/7] fdt.c: Refactor unflatten_device_tree and add fdt_unflatten_tree
Date: Thu, 18 Nov 2010 15:55:02 -0800 [thread overview]
Message-ID: <8aead437-fb77-4e72-8b66-2b1626f6316d@SG2EHSMHS008.ehs.local> (raw)
In-Reply-To: <1290124502-13125-7-git-send-email-stephen.neuendorffer@xilinx.com>
unflatten_device_tree has two dependencies on things that happen
during boot time. Firstly, it references the initial device tree
directly. Secondly, it allocates memory using the early boot
allocator. This patch factors out these dependencies and uses
the new __unflatten_device_tree function to implement a driver-visible
fdt_unflatten_tree function, which can be used to unflatten a
blob after boot time.
Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
--
V2: remove extra __va() call
make dt_alloc functions return void *. This doesn't fix the general
strangeness in this code that constantly casts back and forth between
unsigned long and __be32 *
---
drivers/of/fdt.c | 149 +++++++++++++++++++++++++++++++----------------
include/linux/of_fdt.h | 2 +
2 files changed, 100 insertions(+), 51 deletions(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 236a8c9..e29dbe2 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -11,10 +11,12 @@
#include <linux/kernel.h>
#include <linux/initrd.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/slab.h>
#ifdef CONFIG_PPC
#include <asm/machdep.h>
@@ -312,6 +314,94 @@ unsigned long unflatten_dt_node(struct boot_param_header *blob,
return mem;
}
+/**
+ * __unflatten_device_tree - create tree of device_nodes from flat blob
+ *
+ * unflattens a device-tree, creating the
+ * 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.
+ * @blob: The blob to expand
+ * @mynodes: The device_node tree created by the call
+ * @dt_alloc: An allocator that provides a virtual address to memory
+ * for the resulting tree
+ */
+void __unflatten_device_tree(struct boot_param_header *blob,
+ struct device_node **mynodes,
+ void * (*dt_alloc)(u64 size, u64 align))
+{
+ unsigned long start, mem, size;
+ struct device_node **allnextp = mynodes;
+
+ pr_debug(" -> unflatten_device_tree()\n");
+
+ if (!blob) {
+ pr_debug("No device tree pointer\n");
+ return;
+ }
+
+ pr_debug("Unflattening device tree:\n");
+ pr_debug("magic: %08x\n", be32_to_cpu(blob->magic));
+ pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize));
+ pr_debug("version: %08x\n", be32_to_cpu(blob->version));
+
+ if (be32_to_cpu(blob->magic) != OF_DT_HEADER) {
+ pr_err("Invalid device tree blob header\n");
+ return;
+ }
+
+ /* First pass, scan for size */
+ start = ((unsigned long)blob) +
+ be32_to_cpu(blob->off_dt_struct);
+ size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
+ size = (size | 3) + 1;
+
+ pr_debug(" size is %lx, allocating...\n", size);
+
+ /* Allocate memory for the expanded device tree */
+ mem = (unsigned long)
+ dt_alloc(size + 4, __alignof__(struct device_node));
+
+ ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
+
+ pr_debug(" unflattening %lx...\n", mem);
+
+ /* Second pass, do actual unflattening */
+ start = ((unsigned long)blob) +
+ be32_to_cpu(blob->off_dt_struct);
+ unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
+ if (be32_to_cpup((__be32 *)start) != OF_DT_END)
+ pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
+ if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
+ pr_warning("End of tree marker overwritten: %08x\n",
+ be32_to_cpu(((__be32 *)mem)[size / 4]));
+ *allnextp = NULL;
+
+ pr_debug(" <- unflatten_device_tree()\n");
+}
+
+static void *kernel_tree_alloc(u64 size, u64 align)
+{
+ return kzalloc(size, GFP_KERNEL);
+}
+
+/**
+ * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
+ *
+ * unflattens the device-tree passed by the firmware, creating the
+ * 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.
+ */
+void of_fdt_unflatten_tree(unsigned long *blob,
+ struct device_node **mynodes)
+{
+ struct boot_param_header *device_tree =
+ (struct boot_param_header *)blob;
+ __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
+}
+EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
+
/* Everything below here references initial_boot_params directly. */
int __initdata dt_root_addr_cells;
int __initdata dt_root_size_cells;
@@ -569,6 +659,12 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
return 1;
}
+static void *__init early_device_tree_alloc(u64 size, u64 align)
+{
+ unsigned long mem = early_init_dt_alloc_memory_arch(size, align);
+ return __va(mem);
+}
+
/**
* unflatten_device_tree - create tree of device_nodes from flat blob
*
@@ -579,62 +675,13 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
*/
void __init unflatten_device_tree(void)
{
- unsigned long start, mem, size;
- struct device_node **allnextp = &allnodes;
-
- pr_debug(" -> unflatten_device_tree()\n");
-
- if (!initial_boot_params) {
- pr_debug("No device tree pointer\n");
- return;
- }
-
- pr_debug("Unflattening device tree:\n");
- pr_debug("magic: %08x\n", be32_to_cpu(initial_boot_params->magic));
- pr_debug("size: %08x\n", be32_to_cpu(initial_boot_params->totalsize));
- pr_debug("version: %08x\n", be32_to_cpu(initial_boot_params->version));
-
- if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) {
- pr_err("Invalid device tree blob header\n");
- return;
- }
-
- /* First pass, scan for size */
- start = ((unsigned long)initial_boot_params) +
- be32_to_cpu(initial_boot_params->off_dt_struct);
- size = unflatten_dt_node(initial_boot_params, 0, &start,
- NULL, NULL, 0);
- size = (size | 3) + 1;
-
- pr_debug(" size is %lx, allocating...\n", size);
-
- /* Allocate memory for the expanded device tree */
- mem = early_init_dt_alloc_memory_arch(size + 4,
- __alignof__(struct device_node));
- mem = (unsigned long) __va(mem);
-
- ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
-
- pr_debug(" unflattening %lx...\n", mem);
-
- /* Second pass, do actual unflattening */
- start = ((unsigned long)initial_boot_params) +
- be32_to_cpu(initial_boot_params->off_dt_struct);
- unflatten_dt_node(initial_boot_params, mem, &start,
- NULL, &allnextp, 0);
- if (be32_to_cpup((__be32 *)start) != OF_DT_END)
- pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
- if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
- pr_warning("End of tree marker overwritten: %08x\n",
- be32_to_cpu(((__be32 *)mem)[size / 4]));
- *allnextp = NULL;
+ __unflatten_device_tree(initial_boot_params, &allnodes,
+ early_device_tree_alloc);
/* Get pointer to OF "/chosen" node for use everywhere */
of_chosen = of_find_node_by_path("/chosen");
if (of_chosen == NULL)
of_chosen = of_find_node_by_path("/chosen@0");
-
- pr_debug(" <- unflatten_device_tree()\n");
}
#endif /* CONFIG_EARLY_FLATTREE */
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 70c5b73..9ce5dfd 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -68,6 +68,8 @@ extern void *of_fdt_get_property(struct boot_param_header *blob,
extern int of_fdt_is_compatible(struct boot_param_header *blob,
unsigned long node,
const char *compat);
+extern void of_fdt_unflatten_tree(unsigned long *blob,
+ struct device_node **mynodes);
/* TBD: Temporary export of fdt globals - remove when code fully merged */
extern int __initdata dt_root_addr_cells;
--
1.5.6.6
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
next prev parent reply other threads:[~2010-11-19 0:10 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1290021345-4303-1-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:54 ` [PATCH 0/7] add of_fdt_unflatten_tree Stephen Neuendorffer
[not found] ` <1290124502-13125-1-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:54 ` [PATCH 1/7] fdt: Add Kconfig for EARLY_FLATTREE Stephen Neuendorffer
2010-12-30 0:15 ` Grant Likely
[not found] ` <1290124502-13125-2-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:54 ` [PATCH 2/7] arch/x86: Add support for device tree code Stephen Neuendorffer
2010-12-30 0:17 ` Grant Likely
[not found] ` <1290124502-13125-3-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:54 ` [PATCH 3/7] arch/x86: select OF and OF_FLATTREE Stephen Neuendorffer
2010-12-30 0:17 ` Grant Likely
[not found] ` <1290124502-13125-4-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:54 ` [PATCH 4/7] fdt.c: Add non-boottime device tree functions Stephen Neuendorffer
2010-12-30 0:34 ` Grant Likely
[not found] ` <1290124502-13125-5-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:55 ` [PATCH 5/7] fdt.c: Refactor unflatten_dt_node Stephen Neuendorffer
2010-12-30 0:35 ` Grant Likely
[not found] ` <1290124502-13125-6-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:55 ` [PATCH 6/7] fdt.c: Reorder unflatten_dt_node Stephen Neuendorffer
2010-12-30 0:36 ` Grant Likely
[not found] ` <1290124502-13125-7-git-send-email-stephen.neuendorffer@xilinx.com>
2010-11-18 23:55 ` Stephen Neuendorffer [this message]
2010-12-30 0:43 ` [PATCH 7/7] fdt.c: Refactor unflatten_device_tree and add fdt_unflatten_tree Grant Likely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8aead437-fb77-4e72-8b66-2b1626f6316d@SG2EHSMHS008.ehs.local \
--to=stephen.neuendorffer@xilinx.com \
--cc=devicetree-discuss@lists.ozlabs.org \
--cc=dirk.brandewie@gmail.com \
--cc=grant.likely@secretlab.ca \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=microblaze-uclinux@itee.uq.edu.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox