summaryrefslogtreecommitdiff
path: root/drivers/of/fdt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-14 18:25:40 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-14 18:25:40 -0800
commit37cb8e1f8e10c6e9bd2a1b95cdda0620a21b0551 (patch)
treea1302a6cd2978d7a089534b8232ef3bfa921610e /drivers/of/fdt.c
parent6a77d86655a1f22f099e5c73eef61dea9c56d633 (diff)
parentaa25e446ce76c37bfd75ac06598c316af94e9a26 (diff)
Merge tag 'devicetree-for-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull DeviceTree updates from Rob Herring: "A bigger diffstat than usual with the kbuild changes and a tree wide fix in the binding documentation. Summary: - kbuild cleanups and improvements for dtbs - Code clean-up of overlay code and fixing for some long standing memory leak and race condition in applying overlays - Improvements to DT memory usage making sysfs/kobjects optional and skipping unflattening of disabled nodes. This is part of kernel tinification efforts. - Final piece of removing storing the full path for every DT node. The prerequisite conversion of printk's to use device_node format specifier happened in 4.14. - Sync with current upstream dtc. This brings additional checks to dtb compiling. - Binding doc tree wide removal of leading 0s from examples - RTC binding documentation adding missing devices and some consolidation of duplicated bindings - Vendor prefix documentation for nutsboard, Silicon Storage Technology, shimafuji, Tecon Microprocessor Technologies, DH electronics GmbH, Opal Kelly, and Next Thing" * tag 'devicetree-for-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (55 commits) dt-bindings: usb: add #phy-cells to usb-nop-xceiv dt-bindings: Remove leading zeros from bindings notation kbuild: handle dtb-y and CONFIG_OF_ALL_DTBS natively in Makefile.lib MIPS: dts: remove bogus bcm96358nb4ser.dtb from dtb-y entry kbuild: clean up *.dtb and *.dtb.S patterns from top-level Makefile .gitignore: move *.dtb and *.dtb.S patterns to the top-level .gitignore .gitignore: sort normal pattern rules alphabetically dt-bindings: add vendor prefix for Next Thing Co. scripts/dtc: Update to upstream version v1.4.5-6-gc1e55a5513e9 of: dynamic: fix memory leak related to properties of __of_node_dup of: overlay: make pr_err() string unique of: overlay: pr_err from return NOTIFY_OK to overlay apply/remove of: overlay: remove unneeded check for NULL kbasename() of: overlay: remove a dependency on device node full_name of: overlay: simplify applying symbols from an overlay of: overlay: avoid race condition between applying multiple overlays of: overlay: loosen overly strict phandle clash check of: overlay: expand check of whether overlay changeset can be removed of: overlay: detect cases where device tree may become corrupt of: overlay: minor restructuring ...
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r--drivers/of/fdt.c91
1 files changed, 30 insertions, 61 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index ce30c9a588a4..4675e5ac4d11 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -132,6 +132,19 @@ bool of_fdt_is_big_endian(const void *blob, unsigned long node)
return false;
}
+static bool of_fdt_device_is_available(const void *blob, unsigned long node)
+{
+ const char *status = fdt_getprop(blob, node, "status", NULL);
+
+ if (!status)
+ return true;
+
+ if (!strcmp(status, "ok") || !strcmp(status, "okay"))
+ return true;
+
+ return false;
+}
+
/**
* of_fdt_match - Return true if node matches a list of compatible values
*/
@@ -266,74 +279,32 @@ static void populate_properties(const void *blob,
*pprev = NULL;
}
-static unsigned int populate_node(const void *blob,
- int offset,
- void **mem,
- struct device_node *dad,
- unsigned int fpsize,
- struct device_node **pnp,
- bool dryrun)
+static bool populate_node(const void *blob,
+ int offset,
+ void **mem,
+ struct device_node *dad,
+ struct device_node **pnp,
+ bool dryrun)
{
struct device_node *np;
const char *pathp;
unsigned int l, allocl;
- int new_format = 0;
pathp = fdt_get_name(blob, offset, &l);
if (!pathp) {
*pnp = NULL;
- return 0;
+ return false;
}
allocl = ++l;
- /* 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
- * it later. We detect this because the first character of the name is
- * not '/'.
- */
- if ((*pathp) != '/') {
- new_format = 1;
- if (fpsize == 0) {
- /* root node: special case. fpsize accounts for path
- * plus terminating zero. root node only has '/', so
- * fpsize should be 2, but we want to avoid the first
- * level nodes to have two '/' so we use fpsize 1 here
- */
- fpsize = 1;
- allocl = 2;
- l = 1;
- pathp = "";
- } else {
- /* account for '/' and path size minus terminal 0
- * already in 'l'
- */
- fpsize += l;
- allocl = fpsize;
- }
- }
-
np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl,
__alignof__(struct device_node));
if (!dryrun) {
char *fn;
of_node_init(np);
np->full_name = fn = ((char *)np) + sizeof(*np);
- if (new_format) {
- /* rebuild full path for new format */
- if (dad && dad->parent) {
- strcpy(fn, dad->full_name);
-#ifdef DEBUG
- if ((strlen(fn) + l + 1) != allocl) {
- pr_debug("%s: p: %d, l: %d, a: %d\n",
- pathp, (int)strlen(fn),
- l, allocl);
- }
-#endif
- fn += strlen(fn);
- }
- *(fn++) = '/';
- }
+
memcpy(fn, pathp, l);
if (dad != NULL) {
@@ -355,7 +326,7 @@ static unsigned int populate_node(const void *blob,
}
*pnp = np;
- return fpsize;
+ return true;
}
static void reverse_nodes(struct device_node *parent)
@@ -399,7 +370,6 @@ static int unflatten_dt_nodes(const void *blob,
struct device_node *root;
int offset = 0, depth = 0, initial_depth = 0;
#define FDT_MAX_DEPTH 64
- unsigned int fpsizes[FDT_MAX_DEPTH];
struct device_node *nps[FDT_MAX_DEPTH];
void *base = mem;
bool dryrun = !base;
@@ -418,7 +388,6 @@ static int unflatten_dt_nodes(const void *blob,
depth = initial_depth = 1;
root = dad;
- fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0;
nps[depth] = dad;
for (offset = 0;
@@ -427,11 +396,12 @@ static int unflatten_dt_nodes(const void *blob,
if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
continue;
- fpsizes[depth+1] = populate_node(blob, offset, &mem,
- nps[depth],
- fpsizes[depth],
- &nps[depth+1], dryrun);
- if (!fpsizes[depth+1])
+ if (!IS_ENABLED(CONFIG_OF_KOBJ) &&
+ !of_fdt_device_is_available(blob, offset))
+ continue;
+
+ if (!populate_node(blob, offset, &mem, nps[depth],
+ &nps[depth+1], dryrun))
return mem - base;
if (!dryrun && nodepp && !*nodepp)
@@ -467,6 +437,7 @@ 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
+ * @detached: if true set OF_DETACHED on @mynodes
*
* Returns NULL on failure or the memory chunk containing the unflattened
* device tree on success.
@@ -652,7 +623,6 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
int depth, void *data)
{
static int found;
- const char *status;
int err;
if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) {
@@ -672,8 +642,7 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
return 1;
}
- status = of_get_flat_dt_prop(node, "status", NULL);
- if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0)
+ if (!of_fdt_device_is_available(initial_boot_params, node))
return 0;
err = __reserved_mem_reserve_reg(node, uname);