diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-10 13:53:52 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-10 13:53:52 -0700 |
commit | 31f7c3a688f75bceaf2fd009efc489659ad6aa61 (patch) | |
tree | 1721765e553c01559d1b784563d4840c5d3dd0b9 /drivers/of/fdt.c | |
parent | ec5b103ecfde929004b691f29183255aeeadecd5 (diff) | |
parent | 2bc552df76d83cf1455ac8cf4c87615bfd15df74 (diff) | |
download | lwn-31f7c3a688f75bceaf2fd009efc489659ad6aa61.tar.gz lwn-31f7c3a688f75bceaf2fd009efc489659ad6aa61.zip |
Merge tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux
Pull device tree core updates from Grant Likely:
"Generally minor changes. A bunch of bug fixes, particularly for
initialization and some refactoring. Most notable change if feeding
the entire flattened tree into the random pool at boot. May not be
significant, but shouldn't hurt either"
Tim Bird questions whether the boot time cost of the random feeding may
be noticeable. And "add_device_randomness()" is definitely not some
speed deamon of a function.
* tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux:
of/platform: add error reporting to of_amba_device_create()
irq/of: Fix comment typo for irq_of_parse_and_map
of: Feed entire flattened device tree into the random pool
of/fdt: Clean up casting in unflattening path
of/fdt: Remove duplicate memory clearing on FDT unflattening
gpio: implement gpio-ranges binding document fix
of: call __of_parse_phandle_with_args from of_parse_phandle
of: introduce of_parse_phandle_with_fixed_args
of: move of_parse_phandle()
of: move documentation of of_parse_phandle_with_args
of: Fix missing memory initialization on FDT unflattening
of: consolidate definition of early_init_dt_alloc_memory_arch()
of: Make of_get_phy_mode() return int i.s.o. const int
include: dt-binding: input: create a DT header defining key codes.
of/platform: Staticize of_platform_device_create_pdata()
of: Specify initrd location using 64-bit
dt: Typo fix
OF: make of_property_for_each_{u32|string}() use parameters if OF is not enabled
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r-- | drivers/of/fdt.c | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 4fb06f3e7b3c..229dd9d69e18 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -11,12 +11,14 @@ #include <linux/kernel.h> #include <linux/initrd.h> +#include <linux/memblock.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> +#include <linux/random.h> #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ #ifdef CONFIG_PPC @@ -125,13 +127,13 @@ int of_fdt_match(struct boot_param_header *blob, unsigned long node, return score; } -static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size, +static void *unflatten_dt_alloc(void **mem, unsigned long size, unsigned long align) { void *res; - *mem = ALIGN(*mem, align); - res = (void *)*mem; + *mem = PTR_ALIGN(*mem, align); + res = *mem; *mem += size; return res; @@ -146,9 +148,9 @@ static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size, * @allnextpp: pointer to ->allnext from last allocated device_node * @fpsize: Size of the node path up at the current depth. */ -static unsigned long unflatten_dt_node(struct boot_param_header *blob, - unsigned long mem, - unsigned long *p, +static void * unflatten_dt_node(struct boot_param_header *blob, + void *mem, + void **p, struct device_node *dad, struct device_node ***allnextpp, unsigned long fpsize) @@ -161,15 +163,15 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob, int has_name = 0; int new_format = 0; - tag = be32_to_cpup((__be32 *)(*p)); + tag = be32_to_cpup(*p); if (tag != OF_DT_BEGIN_NODE) { pr_err("Weird tag at start of node: %x\n", tag); return mem; } *p += 4; - pathp = (char *)*p; + pathp = *p; l = allocl = strlen(pathp) + 1; - *p = ALIGN(*p + l, 4); + *p = PTR_ALIGN(*p + l, 4); /* version 0x10 has a more compact unit name here instead of the full * path. we accumulate the full path size using "fpsize", we'll rebuild @@ -201,7 +203,6 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob, __alignof__(struct device_node)); if (allnextpp) { char *fn; - memset(np, 0, sizeof(*np)); np->full_name = fn = ((char *)np) + sizeof(*np); if (new_format) { /* rebuild full path for new format */ @@ -239,7 +240,7 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob, u32 sz, noff; char *pname; - tag = be32_to_cpup((__be32 *)(*p)); + tag = be32_to_cpup(*p); if (tag == OF_DT_NOP) { *p += 4; continue; @@ -247,11 +248,11 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob, if (tag != OF_DT_PROP) break; *p += 4; - sz = be32_to_cpup((__be32 *)(*p)); - noff = be32_to_cpup((__be32 *)((*p) + 4)); + sz = be32_to_cpup(*p); + noff = be32_to_cpup(*p + 4); *p += 8; if (be32_to_cpu(blob->version) < 0x10) - *p = ALIGN(*p, sz >= 8 ? 8 : 4); + *p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4); pname = of_fdt_get_string(blob, noff); if (pname == NULL) { @@ -281,11 +282,11 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob, np->phandle = be32_to_cpup((__be32 *)*p); pp->name = pname; pp->length = sz; - pp->value = (void *)*p; + pp->value = *p; *prev_pp = pp; prev_pp = &pp->next; } - *p = ALIGN((*p) + sz, 4); + *p = PTR_ALIGN((*p) + sz, 4); } /* with version 0x10 we may not have the name property, recreate * it here from the unit name if absent @@ -334,7 +335,7 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob, else mem = unflatten_dt_node(blob, mem, p, np, allnextpp, fpsize); - tag = be32_to_cpup((__be32 *)(*p)); + tag = be32_to_cpup(*p); } if (tag != OF_DT_END_NODE) { pr_err("Weird tag at end of node: %x\n", tag); @@ -360,7 +361,8 @@ static 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; + unsigned long size; + void *start, *mem; struct device_node **allnextp = mynodes; pr_debug(" -> unflatten_device_tree()\n"); @@ -381,32 +383,28 @@ static void __unflatten_device_tree(struct boot_param_header *blob, } /* 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; + start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); + size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); + size = ALIGN(size, 4); 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)); + mem = dt_alloc(size + 4, __alignof__(struct device_node)); + memset(mem, 0, size); - memset((void *)mem, 0, size); + *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef); - ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); - - pr_debug(" unflattening %lx...\n", mem); + pr_debug(" unflattening %p...\n", mem); /* Second pass, do actual unflattening */ - start = ((unsigned long)blob) + - be32_to_cpu(blob->off_dt_struct); + start = ((void *)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) + if (be32_to_cpup(start) != OF_DT_END) + pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start)); + if (be32_to_cpup(mem + size) != 0xdeadbeef) pr_warning("End of tree marker overwritten: %08x\n", - be32_to_cpu(((__be32 *)mem)[size / 4])); + be32_to_cpup(mem + size)); *allnextp = NULL; pr_debug(" <- unflatten_device_tree()\n"); @@ -628,7 +626,8 @@ int __init of_scan_flat_dt_by_path(const char *path, */ void __init early_init_dt_check_for_initrd(unsigned long node) { - unsigned long start, end, len; + u64 start, end; + unsigned long len; __be32 *prop; pr_debug("Looking for initrd properties... "); @@ -636,15 +635,16 @@ void __init early_init_dt_check_for_initrd(unsigned long node) prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len); if (!prop) return; - start = of_read_ulong(prop, len/4); + start = of_read_number(prop, len/4); prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len); if (!prop) return; - end = of_read_ulong(prop, len/4); + end = of_read_number(prop, len/4); early_init_dt_setup_initrd_arch(start, end); - pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", start, end); + pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", + (unsigned long long)start, (unsigned long long)end); } #else inline void early_init_dt_check_for_initrd(unsigned long node) @@ -774,6 +774,17 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, return 1; } +#ifdef CONFIG_HAVE_MEMBLOCK +/* + * called from unflatten_device_tree() to bootstrap devicetree itself + * Architectures can override this definition if memblock isn't used + */ +void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align) +{ + return __va(memblock_alloc(size, align)); +} +#endif + /** * unflatten_device_tree - create tree of device_nodes from flat blob * @@ -792,3 +803,14 @@ void __init unflatten_device_tree(void) } #endif /* CONFIG_OF_EARLY_FLATTREE */ + +/* Feed entire flattened device tree into the random pool */ +static int __init add_fdt_randomness(void) +{ + if (initial_boot_params) + add_device_randomness(initial_boot_params, + be32_to_cpu(initial_boot_params->totalsize)); + + return 0; +} +core_initcall(add_fdt_randomness); |