summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/of/fdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/of/fdt.c')
-rw-r--r--kernel/drivers/of/fdt.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/kernel/drivers/of/fdt.c b/kernel/drivers/of/fdt.c
index d91f721a0..655f79db7 100644
--- a/kernel/drivers/of/fdt.c
+++ b/kernel/drivers/of/fdt.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/initrd.h>
#include <linux/memblock.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_reserved_mem.h>
@@ -164,11 +165,14 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size,
* unflatten_dt_node - Alloc and populate a device_node from the flat tree
* @blob: The parent device tree blob
* @mem: Memory chunk to use for allocating device nodes and properties
- * @p: pointer to node in flat tree
+ * @poffset: pointer to node in flat tree
* @dad: Parent struct device_node
+ * @nodepp: The device_node tree created by the call
* @fpsize: Size of the node path up at the current depth.
+ * @dryrun: If true, do not allocate device nodes but still calculate needed
+ * memory size
*/
-static void * unflatten_dt_node(void *blob,
+static void * unflatten_dt_node(const void *blob,
void *mem,
int *poffset,
struct device_node *dad,
@@ -181,7 +185,7 @@ static void * unflatten_dt_node(void *blob,
struct property *pp, **prev_pp = NULL;
const char *pathp;
unsigned int l, allocl;
- static int depth = 0;
+ static int depth;
int old_depth;
int offset;
int has_name = 0;
@@ -378,7 +382,7 @@ static void * unflatten_dt_node(void *blob,
* @dt_alloc: An allocator that provides a virtual address to memory
* for the resulting tree
*/
-static void __unflatten_device_tree(void *blob,
+static void __unflatten_device_tree(const void *blob,
struct device_node **mynodes,
void * (*dt_alloc)(u64 size, u64 align))
{
@@ -433,6 +437,8 @@ static void *kernel_tree_alloc(u64 size, u64 align)
return kzalloc(size, GFP_KERNEL);
}
+static DEFINE_MUTEX(of_fdt_unflatten_mutex);
+
/**
* of_fdt_unflatten_tree - create tree of device_nodes from flat blob
*
@@ -441,10 +447,12 @@ static void *kernel_tree_alloc(u64 size, u64 align)
* pointers of the nodes so the normal device-tree walking functions
* can be used.
*/
-void of_fdt_unflatten_tree(unsigned long *blob,
+void of_fdt_unflatten_tree(const unsigned long *blob,
struct device_node **mynodes)
{
+ mutex_lock(&of_fdt_unflatten_mutex);
__unflatten_device_tree(blob, mynodes, &kernel_tree_alloc);
+ mutex_unlock(&of_fdt_unflatten_mutex);
}
EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
@@ -580,11 +588,6 @@ void __init early_init_fdt_scan_reserved_mem(void)
if (!initial_boot_params)
return;
- /* Reserve the dtb region */
- early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
- fdt_totalsize(initial_boot_params),
- 0);
-
/* Process header /memreserve/ fields */
for (n = 0; ; n++) {
fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
@@ -598,6 +601,20 @@ void __init early_init_fdt_scan_reserved_mem(void)
}
/**
+ * early_init_fdt_reserve_self() - reserve the memory used by the FDT blob
+ */
+void __init early_init_fdt_reserve_self(void)
+{
+ if (!initial_boot_params)
+ return;
+
+ /* Reserve the dtb region */
+ early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
+ fdt_totalsize(initial_boot_params),
+ 0);
+}
+
+/**
* of_scan_flat_dt - scan flattened tree blob and call callback on each.
* @it: callback function
* @data: context data pointer
@@ -801,20 +818,24 @@ static int __init early_init_dt_scan_chosen_serial(void)
if (!p || !l)
return -ENOENT;
+ /* Remove console options if present */
+ l = strchrnul(p, ':') - p;
+
/* Get the node specified by stdout-path */
- offset = fdt_path_offset(fdt, p);
+ offset = fdt_path_offset_namelen(fdt, p, l);
if (offset < 0)
return -ENODEV;
while (match->compatible[0]) {
- unsigned long addr;
+ u64 addr;
+
if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
match++;
continue;
}
addr = fdt_translate_address(fdt, offset);
- if (!addr)
+ if (addr == OF_BAD_ADDR)
return -ENXIO;
of_setup_earlycon(addr, match->data);
@@ -1017,13 +1038,24 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
return __va(memblock_alloc(size, align));
}
#else
+void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+ WARN_ON(1);
+}
+
int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
phys_addr_t size, bool nomap)
{
- pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n",
+ pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n",
&base, &size, nomap ? " (nomap)" : "");
return -ENOSYS;
}
+
+void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+ WARN_ON(1);
+ return NULL;
+}
#endif
bool __init early_init_dt_verify(void *params)