Merge tag 'devicetree-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull DeviceTree updates from Rob Herring: - Sync dtc to upstream version v1.4.6-9-gaadd0b65c987. This adds a bunch more warnings (hidden behind W=1). - Build dtc lexer and parser files instead of using shipped versions. - Rework overlay apply API to take an FDT as input and apply overlays in a single step. - Add a phandle lookup cache. This improves boot time by hundreds of msec on systems with large DT. - Add trivial mcp4017/18/19 potentiometers bindings. - Remove VLA stack usage in DT code. * tag 'devicetree-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (26 commits) of: unittest: fix an error code in of_unittest_apply_overlay() of: unittest: move misplaced function declaration of: unittest: Remove VLA stack usage of: overlay: Fix forgotten reference to of_overlay_apply() of: Documentation: Fix forgotten reference to of_overlay_apply() of: unittest: local return value variable related cleanups of: unittest: remove unneeded local return value variables dt-bindings: trivial: add various mcp4017/18/19 potentiometers of: unittest: fix an error test in of_unittest_overlay_8() of: cache phandle nodes to reduce cost of of_find_node_by_phandle() dt-bindings: rockchip-dw-mshc: use consistent clock names MAINTAINERS: Add linux/of_*.h headers to appropriate subsystems scripts: turn off some new dtc warnings by default scripts/dtc: Update to upstream version v1.4.6-9-gaadd0b65c987 scripts/dtc: generate lexer and parser during build instead of shipping powerpc: boot: add strrchr function of: overlay: do not include path in full_name of added nodes of: unittest: clean up changeset test arm64/efi: Make strrchr() available to the EFI namespace ARM: boot: add strrchr function ...
This commit is contained in:
@@ -91,10 +91,72 @@ int __weak of_node_to_nid(struct device_node *np)
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct device_node **phandle_cache;
|
||||
static u32 phandle_cache_mask;
|
||||
|
||||
/*
|
||||
* Assumptions behind phandle_cache implementation:
|
||||
* - phandle property values are in a contiguous range of 1..n
|
||||
*
|
||||
* If the assumptions do not hold, then
|
||||
* - the phandle lookup overhead reduction provided by the cache
|
||||
* will likely be less
|
||||
*/
|
||||
static void of_populate_phandle_cache(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 cache_entries;
|
||||
struct device_node *np;
|
||||
u32 phandles = 0;
|
||||
|
||||
raw_spin_lock_irqsave(&devtree_lock, flags);
|
||||
|
||||
kfree(phandle_cache);
|
||||
phandle_cache = NULL;
|
||||
|
||||
for_each_of_allnodes(np)
|
||||
if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
|
||||
phandles++;
|
||||
|
||||
cache_entries = roundup_pow_of_two(phandles);
|
||||
phandle_cache_mask = cache_entries - 1;
|
||||
|
||||
phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache),
|
||||
GFP_ATOMIC);
|
||||
if (!phandle_cache)
|
||||
goto out;
|
||||
|
||||
for_each_of_allnodes(np)
|
||||
if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
|
||||
phandle_cache[np->phandle & phandle_cache_mask] = np;
|
||||
|
||||
out:
|
||||
raw_spin_unlock_irqrestore(&devtree_lock, flags);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MODULES
|
||||
static int __init of_free_phandle_cache(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&devtree_lock, flags);
|
||||
|
||||
kfree(phandle_cache);
|
||||
phandle_cache = NULL;
|
||||
|
||||
raw_spin_unlock_irqrestore(&devtree_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall_sync(of_free_phandle_cache);
|
||||
#endif
|
||||
|
||||
void __init of_core_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
of_populate_phandle_cache();
|
||||
|
||||
/* Create the kset, and register existing nodes */
|
||||
mutex_lock(&of_mutex);
|
||||
of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
|
||||
@@ -1021,16 +1083,32 @@ EXPORT_SYMBOL_GPL(of_modalias_node);
|
||||
*/
|
||||
struct device_node *of_find_node_by_phandle(phandle handle)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct device_node *np = NULL;
|
||||
unsigned long flags;
|
||||
phandle masked_handle;
|
||||
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
raw_spin_lock_irqsave(&devtree_lock, flags);
|
||||
for_each_of_allnodes(np)
|
||||
if (np->phandle == handle)
|
||||
break;
|
||||
|
||||
masked_handle = handle & phandle_cache_mask;
|
||||
|
||||
if (phandle_cache) {
|
||||
if (phandle_cache[masked_handle] &&
|
||||
handle == phandle_cache[masked_handle]->phandle)
|
||||
np = phandle_cache[masked_handle];
|
||||
}
|
||||
|
||||
if (!np) {
|
||||
for_each_of_allnodes(np)
|
||||
if (np->phandle == handle) {
|
||||
if (phandle_cache)
|
||||
phandle_cache[masked_handle] = np;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_get(np);
|
||||
raw_spin_unlock_irqrestore(&devtree_lock, flags);
|
||||
return np;
|
||||
@@ -1283,6 +1361,190 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na
|
||||
}
|
||||
EXPORT_SYMBOL(of_parse_phandle_with_args);
|
||||
|
||||
/**
|
||||
* of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it
|
||||
* @np: pointer to a device tree node containing a list
|
||||
* @list_name: property name that contains a list
|
||||
* @stem_name: stem of property names that specify phandles' arguments count
|
||||
* @index: index of a phandle to parse out
|
||||
* @out_args: optional pointer to output arguments structure (will be filled)
|
||||
*
|
||||
* This function is useful to parse lists of phandles and their arguments.
|
||||
* Returns 0 on success and fills out_args, on error returns appropriate errno
|
||||
* value. The difference between this function and of_parse_phandle_with_args()
|
||||
* is that this API remaps a phandle if the node the phandle points to has
|
||||
* a <@stem_name>-map property.
|
||||
*
|
||||
* Caller is responsible to call of_node_put() on the returned out_args->np
|
||||
* pointer.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* phandle1: node1 {
|
||||
* #list-cells = <2>;
|
||||
* }
|
||||
*
|
||||
* phandle2: node2 {
|
||||
* #list-cells = <1>;
|
||||
* }
|
||||
*
|
||||
* phandle3: node3 {
|
||||
* #list-cells = <1>;
|
||||
* list-map = <0 &phandle2 3>,
|
||||
* <1 &phandle2 2>,
|
||||
* <2 &phandle1 5 1>;
|
||||
* list-map-mask = <0x3>;
|
||||
* };
|
||||
*
|
||||
* node4 {
|
||||
* list = <&phandle1 1 2 &phandle3 0>;
|
||||
* }
|
||||
*
|
||||
* To get a device_node of the `node2' node you may call this:
|
||||
* of_parse_phandle_with_args(node4, "list", "list", 1, &args);
|
||||
*/
|
||||
int of_parse_phandle_with_args_map(const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *stem_name,
|
||||
int index, struct of_phandle_args *out_args)
|
||||
{
|
||||
char *cells_name, *map_name = NULL, *mask_name = NULL;
|
||||
char *pass_name = NULL;
|
||||
struct device_node *cur, *new = NULL;
|
||||
const __be32 *map, *mask, *pass;
|
||||
static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
|
||||
static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
|
||||
__be32 initial_match_array[MAX_PHANDLE_ARGS];
|
||||
const __be32 *match_array = initial_match_array;
|
||||
int i, ret, map_len, match;
|
||||
u32 list_size, new_size;
|
||||
|
||||
if (index < 0)
|
||||
return -EINVAL;
|
||||
|
||||
cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
|
||||
if (!cells_name)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = -ENOMEM;
|
||||
map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name);
|
||||
if (!map_name)
|
||||
goto free;
|
||||
|
||||
mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name);
|
||||
if (!mask_name)
|
||||
goto free;
|
||||
|
||||
pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name);
|
||||
if (!pass_name)
|
||||
goto free;
|
||||
|
||||
ret = __of_parse_phandle_with_args(np, list_name, cells_name, 0, index,
|
||||
out_args);
|
||||
if (ret)
|
||||
goto free;
|
||||
|
||||
/* Get the #<list>-cells property */
|
||||
cur = out_args->np;
|
||||
ret = of_property_read_u32(cur, cells_name, &list_size);
|
||||
if (ret < 0)
|
||||
goto put;
|
||||
|
||||
/* Precalculate the match array - this simplifies match loop */
|
||||
for (i = 0; i < list_size; i++)
|
||||
initial_match_array[i] = cpu_to_be32(out_args->args[i]);
|
||||
|
||||
ret = -EINVAL;
|
||||
while (cur) {
|
||||
/* Get the <list>-map property */
|
||||
map = of_get_property(cur, map_name, &map_len);
|
||||
if (!map) {
|
||||
ret = 0;
|
||||
goto free;
|
||||
}
|
||||
map_len /= sizeof(u32);
|
||||
|
||||
/* Get the <list>-map-mask property (optional) */
|
||||
mask = of_get_property(cur, mask_name, NULL);
|
||||
if (!mask)
|
||||
mask = dummy_mask;
|
||||
/* Iterate through <list>-map property */
|
||||
match = 0;
|
||||
while (map_len > (list_size + 1) && !match) {
|
||||
/* Compare specifiers */
|
||||
match = 1;
|
||||
for (i = 0; i < list_size; i++, map_len--)
|
||||
match &= !((match_array[i] ^ *map++) & mask[i]);
|
||||
|
||||
of_node_put(new);
|
||||
new = of_find_node_by_phandle(be32_to_cpup(map));
|
||||
map++;
|
||||
map_len--;
|
||||
|
||||
/* Check if not found */
|
||||
if (!new)
|
||||
goto put;
|
||||
|
||||
if (!of_device_is_available(new))
|
||||
match = 0;
|
||||
|
||||
ret = of_property_read_u32(new, cells_name, &new_size);
|
||||
if (ret)
|
||||
goto put;
|
||||
|
||||
/* Check for malformed properties */
|
||||
if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
|
||||
goto put;
|
||||
if (map_len < new_size)
|
||||
goto put;
|
||||
|
||||
/* Move forward by new node's #<list>-cells amount */
|
||||
map += new_size;
|
||||
map_len -= new_size;
|
||||
}
|
||||
if (!match)
|
||||
goto put;
|
||||
|
||||
/* Get the <list>-map-pass-thru property (optional) */
|
||||
pass = of_get_property(cur, pass_name, NULL);
|
||||
if (!pass)
|
||||
pass = dummy_pass;
|
||||
|
||||
/*
|
||||
* Successfully parsed a <list>-map translation; copy new
|
||||
* specifier into the out_args structure, keeping the
|
||||
* bits specified in <list>-map-pass-thru.
|
||||
*/
|
||||
match_array = map - new_size;
|
||||
for (i = 0; i < new_size; i++) {
|
||||
__be32 val = *(map - new_size + i);
|
||||
|
||||
if (i < list_size) {
|
||||
val &= ~pass[i];
|
||||
val |= cpu_to_be32(out_args->args[i]) & pass[i];
|
||||
}
|
||||
|
||||
out_args->args[i] = be32_to_cpu(val);
|
||||
}
|
||||
out_args->args_count = list_size = new_size;
|
||||
/* Iterate again with new provider */
|
||||
out_args->np = new;
|
||||
of_node_put(cur);
|
||||
cur = new;
|
||||
}
|
||||
put:
|
||||
of_node_put(cur);
|
||||
of_node_put(new);
|
||||
free:
|
||||
kfree(mask_name);
|
||||
kfree(map_name);
|
||||
kfree(cells_name);
|
||||
kfree(pass_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(of_parse_phandle_with_args_map);
|
||||
|
||||
/**
|
||||
* of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list
|
||||
* @np: pointer to a device tree node containing a list
|
||||
|
@@ -383,25 +383,24 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
|
||||
|
||||
/**
|
||||
* __of_node_dup() - Duplicate or create an empty device node dynamically.
|
||||
* @fmt: Format string (plus vargs) for new full name of the device node
|
||||
* @np: if not NULL, contains properties to be duplicated in new node
|
||||
* @full_name: string value to be duplicated into new node's full_name field
|
||||
*
|
||||
* Create an device tree node, either by duplicating an empty node or by allocating
|
||||
* an empty one suitable for further modification. The node data are
|
||||
* dynamically allocated and all the node flags have the OF_DYNAMIC &
|
||||
* OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
|
||||
* memory error.
|
||||
* Create a device tree node, optionally duplicating the properties of
|
||||
* another node. The node data are dynamically allocated and all the node
|
||||
* flags have the OF_DYNAMIC & OF_DETACHED bits set.
|
||||
*
|
||||
* Returns the newly allocated node or NULL on out of memory error.
|
||||
*/
|
||||
struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...)
|
||||
struct device_node *__of_node_dup(const struct device_node *np,
|
||||
const char *full_name)
|
||||
{
|
||||
va_list vargs;
|
||||
struct device_node *node;
|
||||
|
||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||
if (!node)
|
||||
return NULL;
|
||||
va_start(vargs, fmt);
|
||||
node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
|
||||
va_end(vargs);
|
||||
node->full_name = kstrdup(full_name, GFP_KERNEL);
|
||||
if (!node->full_name) {
|
||||
kfree(node);
|
||||
return NULL;
|
||||
|
@@ -104,7 +104,8 @@ extern void *__unflatten_device_tree(const void *blob,
|
||||
* own the devtree lock or work on detached trees only.
|
||||
*/
|
||||
struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
|
||||
__printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...);
|
||||
struct device_node *__of_node_dup(const struct device_node *np,
|
||||
const char *full_name);
|
||||
|
||||
struct device_node *__of_find_node_by_path(struct device_node *parent,
|
||||
const char *path);
|
||||
@@ -131,6 +132,9 @@ extern void __of_detach_node_sysfs(struct device_node *np);
|
||||
extern void __of_sysfs_remove_bin_file(struct device_node *np,
|
||||
struct property *prop);
|
||||
|
||||
/* illegal phandle value (set when unresolved) */
|
||||
#define OF_PHANDLE_ILLEGAL 0xdeadbeef
|
||||
|
||||
/* iterators for transactions, used for overlays */
|
||||
/* forward iterator */
|
||||
#define for_each_transaction_entry(_oft, _te) \
|
||||
|
@@ -312,7 +312,20 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
|
||||
* If @node has child nodes, add the children recursively via
|
||||
* build_changeset_next_level().
|
||||
*
|
||||
* NOTE: Multiple mods of created nodes not supported.
|
||||
* NOTE_1: A live devicetree created from a flattened device tree (FDT) will
|
||||
* not contain the full path in node->full_name. Thus an overlay
|
||||
* created from an FDT also will not contain the full path in
|
||||
* node->full_name. However, a live devicetree created from Open
|
||||
* Firmware may have the full path in node->full_name.
|
||||
*
|
||||
* add_changeset_node() follows the FDT convention and does not include
|
||||
* the full path in node->full_name. Even though it expects the overlay
|
||||
* to not contain the full path, it uses kbasename() to remove the
|
||||
* full path should it exist. It also uses kbasename() in comparisons
|
||||
* to nodes in the live devicetree so that it can apply an overlay to
|
||||
* a live devicetree created from Open Firmware.
|
||||
*
|
||||
* NOTE_2: Multiple mods of created nodes not supported.
|
||||
* If more than one fragment contains a node that does not already exist
|
||||
* in the live tree, then for each fragment of_changeset_attach_node()
|
||||
* will add a changeset entry to add the node. When the changeset is
|
||||
@@ -339,8 +352,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
|
||||
break;
|
||||
|
||||
if (!tchild) {
|
||||
tchild = __of_node_dup(node, "%pOF/%s",
|
||||
target_node, node_kbasename);
|
||||
tchild = __of_node_dup(node, node_kbasename);
|
||||
if (!tchild)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -958,7 +970,7 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs)
|
||||
* @ovcs_id: Pointer to overlay changeset id
|
||||
*
|
||||
* Removes an overlay if it is permissible. @ovcs_id was previously returned
|
||||
* by of_overlay_apply().
|
||||
* by of_overlay_fdt_apply().
|
||||
*
|
||||
* If an error occurred while attempting to revert the overlay changeset,
|
||||
* then an attempt is made to re-apply any changeset entry that was
|
||||
|
@@ -19,9 +19,6 @@
|
||||
|
||||
#include "of_private.h"
|
||||
|
||||
/* illegal phandle value (set when unresolved) */
|
||||
#define OF_PHANDLE_ILLEGAL 0xdeadbeef
|
||||
|
||||
static phandle live_tree_max_phandle(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
@@ -26,6 +26,18 @@
|
||||
#phandle-cells = <3>;
|
||||
};
|
||||
|
||||
provider4: provider4 {
|
||||
#phandle-cells = <2>;
|
||||
phandle-map = <0 1 &provider1 3>,
|
||||
<4 0 &provider0>,
|
||||
<16 5 &provider3 3 5 0>,
|
||||
<200 8 &provider2 23 6>,
|
||||
<19 0 &provider2 15 0>,
|
||||
<2 3 &provider3 2 5 3>;
|
||||
phandle-map-mask = <0xff 0xf>;
|
||||
phandle-map-pass-thru = <0x0 0xf0>;
|
||||
};
|
||||
|
||||
consumer-a {
|
||||
phandle-list = <&provider1 1>,
|
||||
<&provider2 2 0>,
|
||||
@@ -44,6 +56,19 @@
|
||||
unterminated-string = [40 41 42 43];
|
||||
unterminated-string-list = "first", "second", [40 41 42 43];
|
||||
};
|
||||
|
||||
consumer-b {
|
||||
phandle-list = <&provider1 1>,
|
||||
<&provider4 2 3>,
|
||||
<0>,
|
||||
<&provider4 4 0x100>,
|
||||
<&provider4 0 0x61>,
|
||||
<&provider0>,
|
||||
<&provider4 19 0x20>;
|
||||
phandle-list-bad-phandle = <12345678 0 0>;
|
||||
phandle-list-bad-args = <&provider2 1 0>,
|
||||
<&provider4 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@@ -45,8 +45,6 @@ static struct unittest_results {
|
||||
failed; \
|
||||
})
|
||||
|
||||
static int __init overlay_data_apply(const char *overlay_name, int *overlay_id);
|
||||
|
||||
static void __init of_unittest_find_node_by_name(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
@@ -254,12 +252,18 @@ static void __init of_unittest_check_tree_linkage(void)
|
||||
static void __init of_unittest_printf_one(struct device_node *np, const char *fmt,
|
||||
const char *expected)
|
||||
{
|
||||
unsigned char buf[strlen(expected)+10];
|
||||
unsigned char *buf;
|
||||
int buf_size;
|
||||
int size, i;
|
||||
|
||||
buf_size = strlen(expected) + 10;
|
||||
buf = kmalloc(buf_size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
/* Baseline; check conversion with a large size limit */
|
||||
memset(buf, 0xff, sizeof(buf));
|
||||
size = snprintf(buf, sizeof(buf) - 2, fmt, np);
|
||||
memset(buf, 0xff, buf_size);
|
||||
size = snprintf(buf, buf_size - 2, fmt, np);
|
||||
|
||||
/* use strcmp() instead of strncmp() here to be absolutely sure strings match */
|
||||
unittest((strcmp(buf, expected) == 0) && (buf[size+1] == 0xff),
|
||||
@@ -270,12 +274,13 @@ static void __init of_unittest_printf_one(struct device_node *np, const char *fm
|
||||
size++;
|
||||
for (i = 0; i < 2; i++, size--) {
|
||||
/* Clear the buffer, and make sure it works correctly still */
|
||||
memset(buf, 0xff, sizeof(buf));
|
||||
memset(buf, 0xff, buf_size);
|
||||
snprintf(buf, size+1, fmt, np);
|
||||
unittest(strncmp(buf, expected, size) == 0 && (buf[size+1] == 0xff),
|
||||
"snprintf failed; size=%i fmt='%s' expected='%s' rslt='%s'\n",
|
||||
size, fmt, expected, buf);
|
||||
}
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static void __init of_unittest_printf(void)
|
||||
@@ -455,6 +460,125 @@ static void __init of_unittest_parse_phandle_with_args(void)
|
||||
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||
}
|
||||
|
||||
static void __init of_unittest_parse_phandle_with_args_map(void)
|
||||
{
|
||||
struct device_node *np, *p0, *p1, *p2, *p3;
|
||||
struct of_phandle_args args;
|
||||
int i, rc;
|
||||
|
||||
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-b");
|
||||
if (!np) {
|
||||
pr_err("missing testcase data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p0 = of_find_node_by_path("/testcase-data/phandle-tests/provider0");
|
||||
if (!p0) {
|
||||
pr_err("missing testcase data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p1 = of_find_node_by_path("/testcase-data/phandle-tests/provider1");
|
||||
if (!p1) {
|
||||
pr_err("missing testcase data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p2 = of_find_node_by_path("/testcase-data/phandle-tests/provider2");
|
||||
if (!p2) {
|
||||
pr_err("missing testcase data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p3 = of_find_node_by_path("/testcase-data/phandle-tests/provider3");
|
||||
if (!p3) {
|
||||
pr_err("missing testcase data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells");
|
||||
unittest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
bool passed = true;
|
||||
|
||||
rc = of_parse_phandle_with_args_map(np, "phandle-list",
|
||||
"phandle", i, &args);
|
||||
|
||||
/* Test the values from tests-phandle.dtsi */
|
||||
switch (i) {
|
||||
case 0:
|
||||
passed &= !rc;
|
||||
passed &= (args.np == p1);
|
||||
passed &= (args.args_count == 1);
|
||||
passed &= (args.args[0] == 1);
|
||||
break;
|
||||
case 1:
|
||||
passed &= !rc;
|
||||
passed &= (args.np == p3);
|
||||
passed &= (args.args_count == 3);
|
||||
passed &= (args.args[0] == 2);
|
||||
passed &= (args.args[1] == 5);
|
||||
passed &= (args.args[2] == 3);
|
||||
break;
|
||||
case 2:
|
||||
passed &= (rc == -ENOENT);
|
||||
break;
|
||||
case 3:
|
||||
passed &= !rc;
|
||||
passed &= (args.np == p0);
|
||||
passed &= (args.args_count == 0);
|
||||
break;
|
||||
case 4:
|
||||
passed &= !rc;
|
||||
passed &= (args.np == p1);
|
||||
passed &= (args.args_count == 1);
|
||||
passed &= (args.args[0] == 3);
|
||||
break;
|
||||
case 5:
|
||||
passed &= !rc;
|
||||
passed &= (args.np == p0);
|
||||
passed &= (args.args_count == 0);
|
||||
break;
|
||||
case 6:
|
||||
passed &= !rc;
|
||||
passed &= (args.np == p2);
|
||||
passed &= (args.args_count == 2);
|
||||
passed &= (args.args[0] == 15);
|
||||
passed &= (args.args[1] == 0x20);
|
||||
break;
|
||||
case 7:
|
||||
passed &= (rc == -ENOENT);
|
||||
break;
|
||||
default:
|
||||
passed = false;
|
||||
}
|
||||
|
||||
unittest(passed, "index %i - data error on node %s rc=%i\n",
|
||||
i, args.np->full_name, rc);
|
||||
}
|
||||
|
||||
/* Check for missing list property */
|
||||
rc = of_parse_phandle_with_args_map(np, "phandle-list-missing",
|
||||
"phandle", 0, &args);
|
||||
unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc);
|
||||
|
||||
/* Check for missing cells,map,mask property */
|
||||
rc = of_parse_phandle_with_args_map(np, "phandle-list",
|
||||
"phandle-missing", 0, &args);
|
||||
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||
|
||||
/* Check for bad phandle in list */
|
||||
rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle",
|
||||
"phandle", 0, &args);
|
||||
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||
|
||||
/* Check for incorrectly formed argument list */
|
||||
rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args",
|
||||
"phandle", 1, &args);
|
||||
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||
}
|
||||
|
||||
static void __init of_unittest_property_string(void)
|
||||
{
|
||||
const char *strings[4];
|
||||
@@ -564,42 +688,72 @@ static void __init of_unittest_property_copy(void)
|
||||
static void __init of_unittest_changeset(void)
|
||||
{
|
||||
#ifdef CONFIG_OF_DYNAMIC
|
||||
struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" };
|
||||
struct property *ppadd, padd = { .name = "prop-add", .length = 1, .value = "" };
|
||||
struct property *ppname_n1, pname_n1 = { .name = "name", .length = 3, .value = "n1" };
|
||||
struct property *ppname_n2, pname_n2 = { .name = "name", .length = 3, .value = "n2" };
|
||||
struct property *ppname_n21, pname_n21 = { .name = "name", .length = 3, .value = "n21" };
|
||||
struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" };
|
||||
struct property *ppremove;
|
||||
struct device_node *n1, *n2, *n21, *nremove, *parent, *np;
|
||||
struct device_node *n1, *n2, *n21, *nchangeset, *nremove, *parent, *np;
|
||||
struct of_changeset chgset;
|
||||
|
||||
n1 = __of_node_dup(NULL, "/testcase-data/changeset/n1");
|
||||
n1 = __of_node_dup(NULL, "n1");
|
||||
unittest(n1, "testcase setup failure\n");
|
||||
n2 = __of_node_dup(NULL, "/testcase-data/changeset/n2");
|
||||
|
||||
n2 = __of_node_dup(NULL, "n2");
|
||||
unittest(n2, "testcase setup failure\n");
|
||||
n21 = __of_node_dup(NULL, "%s/%s", "/testcase-data/changeset/n2", "n21");
|
||||
|
||||
n21 = __of_node_dup(NULL, "n21");
|
||||
unittest(n21, "testcase setup failure %p\n", n21);
|
||||
nremove = of_find_node_by_path("/testcase-data/changeset/node-remove");
|
||||
|
||||
nchangeset = of_find_node_by_path("/testcase-data/changeset");
|
||||
nremove = of_get_child_by_name(nchangeset, "node-remove");
|
||||
unittest(nremove, "testcase setup failure\n");
|
||||
|
||||
ppadd = __of_prop_dup(&padd, GFP_KERNEL);
|
||||
unittest(ppadd, "testcase setup failure\n");
|
||||
|
||||
ppname_n1 = __of_prop_dup(&pname_n1, GFP_KERNEL);
|
||||
unittest(ppname_n1, "testcase setup failure\n");
|
||||
|
||||
ppname_n2 = __of_prop_dup(&pname_n2, GFP_KERNEL);
|
||||
unittest(ppname_n2, "testcase setup failure\n");
|
||||
|
||||
ppname_n21 = __of_prop_dup(&pname_n21, GFP_KERNEL);
|
||||
unittest(ppname_n21, "testcase setup failure\n");
|
||||
|
||||
ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL);
|
||||
unittest(ppupdate, "testcase setup failure\n");
|
||||
parent = nremove->parent;
|
||||
|
||||
parent = nchangeset;
|
||||
n1->parent = parent;
|
||||
n2->parent = parent;
|
||||
n21->parent = n2;
|
||||
n2->child = n21;
|
||||
|
||||
ppremove = of_find_property(parent, "prop-remove", NULL);
|
||||
unittest(ppremove, "failed to find removal prop");
|
||||
|
||||
of_changeset_init(&chgset);
|
||||
|
||||
unittest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n");
|
||||
unittest(!of_changeset_add_property(&chgset, n1, ppname_n1), "fail add prop name\n");
|
||||
|
||||
unittest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n");
|
||||
unittest(!of_changeset_add_property(&chgset, n2, ppname_n2), "fail add prop name\n");
|
||||
|
||||
unittest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n");
|
||||
unittest(!of_changeset_add_property(&chgset, n21, ppname_n21), "fail add prop name\n");
|
||||
|
||||
unittest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n");
|
||||
unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n");
|
||||
|
||||
unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop prop-add\n");
|
||||
unittest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
|
||||
unittest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
|
||||
|
||||
unittest(!of_changeset_apply(&chgset), "apply failed\n");
|
||||
|
||||
of_node_put(nchangeset);
|
||||
|
||||
/* Make sure node names are constructed correctly */
|
||||
unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")),
|
||||
"'%pOF' not added\n", n21);
|
||||
@@ -1036,6 +1190,7 @@ static int __init unittest_data_add(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_OVERLAY
|
||||
static int __init overlay_data_apply(const char *overlay_name, int *overlay_id);
|
||||
|
||||
static int unittest_probe(struct platform_device *pdev)
|
||||
{
|
||||
@@ -1267,26 +1422,18 @@ static void of_unittest_destroy_tracked_overlays(void)
|
||||
static int __init of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
|
||||
int *overlay_id)
|
||||
{
|
||||
struct device_node *np = NULL;
|
||||
const char *overlay_name;
|
||||
int ret;
|
||||
|
||||
overlay_name = overlay_name_from_nr(overlay_nr);
|
||||
|
||||
ret = overlay_data_apply(overlay_name, overlay_id);
|
||||
if (!ret) {
|
||||
if (!overlay_data_apply(overlay_name, overlay_id)) {
|
||||
unittest(0, "could not apply overlay \"%s\"\n",
|
||||
overlay_name);
|
||||
goto out;
|
||||
return -EFAULT;
|
||||
}
|
||||
of_unittest_track_overlay(*overlay_id);
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
of_node_put(np);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* apply an overlay while checking before and after states */
|
||||
@@ -1380,11 +1527,8 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,
|
||||
/* test activation of device */
|
||||
static void __init of_unittest_overlay_0(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should enable */
|
||||
ret = of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 0);
|
||||
@@ -1393,11 +1537,8 @@ static void __init of_unittest_overlay_0(void)
|
||||
/* test deactivation of device */
|
||||
static void __init of_unittest_overlay_1(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should disable */
|
||||
ret = of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 1);
|
||||
@@ -1406,11 +1547,8 @@ static void __init of_unittest_overlay_1(void)
|
||||
/* test activation of device */
|
||||
static void __init of_unittest_overlay_2(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should enable */
|
||||
ret = of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 2);
|
||||
@@ -1419,11 +1557,8 @@ static void __init of_unittest_overlay_2(void)
|
||||
/* test deactivation of device */
|
||||
static void __init of_unittest_overlay_3(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should disable */
|
||||
ret = of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 3);
|
||||
@@ -1432,11 +1567,8 @@ static void __init of_unittest_overlay_3(void)
|
||||
/* test activation of a full device node */
|
||||
static void __init of_unittest_overlay_4(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should disable */
|
||||
ret = of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 4);
|
||||
@@ -1445,11 +1577,8 @@ static void __init of_unittest_overlay_4(void)
|
||||
/* test overlay apply/revert sequence */
|
||||
static void __init of_unittest_overlay_5(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should disable */
|
||||
ret = of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 5);
|
||||
@@ -1458,7 +1587,7 @@ static void __init of_unittest_overlay_5(void)
|
||||
/* test overlay application in sequence */
|
||||
static void __init of_unittest_overlay_6(void)
|
||||
{
|
||||
int ret, i, ov_id[2], ovcs_id;
|
||||
int i, ov_id[2], ovcs_id;
|
||||
int overlay_nr = 6, unittest_nr = 6;
|
||||
int before = 0, after = 1;
|
||||
const char *overlay_name;
|
||||
@@ -1481,8 +1610,7 @@ static void __init of_unittest_overlay_6(void)
|
||||
|
||||
overlay_name = overlay_name_from_nr(overlay_nr + i);
|
||||
|
||||
ret = overlay_data_apply(overlay_name, &ovcs_id);
|
||||
if (!ret) {
|
||||
if (!overlay_data_apply(overlay_name, &ovcs_id)) {
|
||||
unittest(0, "could not apply overlay \"%s\"\n",
|
||||
overlay_name);
|
||||
return;
|
||||
@@ -1506,8 +1634,7 @@ static void __init of_unittest_overlay_6(void)
|
||||
|
||||
for (i = 1; i >= 0; i--) {
|
||||
ovcs_id = ov_id[i];
|
||||
ret = of_overlay_remove(&ovcs_id);
|
||||
if (ret != 0) {
|
||||
if (of_overlay_remove(&ovcs_id)) {
|
||||
unittest(0, "%s failed destroy @\"%s\"\n",
|
||||
overlay_name_from_nr(overlay_nr + i),
|
||||
unittest_path(unittest_nr + i,
|
||||
@@ -1536,7 +1663,7 @@ static void __init of_unittest_overlay_6(void)
|
||||
/* test overlay application in sequence */
|
||||
static void __init of_unittest_overlay_8(void)
|
||||
{
|
||||
int ret, i, ov_id[2], ovcs_id;
|
||||
int i, ov_id[2], ovcs_id;
|
||||
int overlay_nr = 8, unittest_nr = 8;
|
||||
const char *overlay_name;
|
||||
|
||||
@@ -1547,8 +1674,7 @@ static void __init of_unittest_overlay_8(void)
|
||||
|
||||
overlay_name = overlay_name_from_nr(overlay_nr + i);
|
||||
|
||||
ret = overlay_data_apply(overlay_name, &ovcs_id);
|
||||
if (ret < 0) {
|
||||
if (!overlay_data_apply(overlay_name, &ovcs_id)) {
|
||||
unittest(0, "could not apply overlay \"%s\"\n",
|
||||
overlay_name);
|
||||
return;
|
||||
@@ -1559,8 +1685,7 @@ static void __init of_unittest_overlay_8(void)
|
||||
|
||||
/* now try to remove first overlay (it should fail) */
|
||||
ovcs_id = ov_id[0];
|
||||
ret = of_overlay_remove(&ovcs_id);
|
||||
if (ret == 0) {
|
||||
if (!of_overlay_remove(&ovcs_id)) {
|
||||
unittest(0, "%s was destroyed @\"%s\"\n",
|
||||
overlay_name_from_nr(overlay_nr + 0),
|
||||
unittest_path(unittest_nr,
|
||||
@@ -1571,8 +1696,7 @@ static void __init of_unittest_overlay_8(void)
|
||||
/* removing them in order should work */
|
||||
for (i = 1; i >= 0; i--) {
|
||||
ovcs_id = ov_id[i];
|
||||
ret = of_overlay_remove(&ovcs_id);
|
||||
if (ret != 0) {
|
||||
if (of_overlay_remove(&ovcs_id)) {
|
||||
unittest(0, "%s not destroyed @\"%s\"\n",
|
||||
overlay_name_from_nr(overlay_nr + i),
|
||||
unittest_path(unittest_nr,
|
||||
@@ -1604,8 +1728,8 @@ static void __init of_unittest_overlay_10(void)
|
||||
|
||||
ret = of_path_device_type_exists(child_path, PDEV_OVERLAY);
|
||||
kfree(child_path);
|
||||
if (unittest(ret, "overlay test %d failed; no child device\n", 10))
|
||||
return;
|
||||
|
||||
unittest(ret, "overlay test %d failed; no child device\n", 10);
|
||||
}
|
||||
|
||||
/* test insertion of a bus with parent devices (and revert) */
|
||||
@@ -1616,9 +1740,7 @@ static void __init of_unittest_overlay_11(void)
|
||||
/* device should disable */
|
||||
ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1,
|
||||
PDEV_OVERLAY);
|
||||
if (unittest(ret == 0,
|
||||
"overlay test %d failed; overlay application\n", 11))
|
||||
return;
|
||||
unittest(ret == 0, "overlay test %d failed; overlay apply\n", 11);
|
||||
}
|
||||
|
||||
#if IS_BUILTIN(CONFIG_I2C) && IS_ENABLED(CONFIG_OF_OVERLAY)
|
||||
@@ -1769,7 +1891,7 @@ static int unittest_i2c_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
static int unittest_i2c_mux_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret, i, nchans;
|
||||
int i, nchans;
|
||||
struct device *dev = &client->dev;
|
||||
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
|
||||
struct device_node *np = client->dev.of_node, *child;
|
||||
@@ -1785,8 +1907,7 @@ static int unittest_i2c_mux_probe(struct i2c_client *client,
|
||||
|
||||
max_reg = (u32)-1;
|
||||
for_each_child_of_node(np, child) {
|
||||
ret = of_property_read_u32(child, "reg", ®);
|
||||
if (ret)
|
||||
if (of_property_read_u32(child, "reg", ®))
|
||||
continue;
|
||||
if (max_reg == (u32)-1 || reg > max_reg)
|
||||
max_reg = reg;
|
||||
@@ -1802,8 +1923,7 @@ static int unittest_i2c_mux_probe(struct i2c_client *client,
|
||||
if (!muxc)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < nchans; i++) {
|
||||
ret = i2c_mux_add_adapter(muxc, 0, i, 0);
|
||||
if (ret) {
|
||||
if (i2c_mux_add_adapter(muxc, 0, i, 0)) {
|
||||
dev_err(dev, "Failed to register mux #%d\n", i);
|
||||
i2c_mux_del_adapters(muxc);
|
||||
return -ENODEV;
|
||||
@@ -1877,11 +1997,8 @@ static void of_unittest_overlay_i2c_cleanup(void)
|
||||
|
||||
static void __init of_unittest_overlay_i2c_12(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should enable */
|
||||
ret = of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 12);
|
||||
@@ -1890,11 +2007,8 @@ static void __init of_unittest_overlay_i2c_12(void)
|
||||
/* test deactivation of device */
|
||||
static void __init of_unittest_overlay_i2c_13(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should disable */
|
||||
ret = of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 13);
|
||||
@@ -1907,11 +2021,8 @@ static void of_unittest_overlay_i2c_14(void)
|
||||
|
||||
static void __init of_unittest_overlay_i2c_15(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device should enable */
|
||||
ret = of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY);
|
||||
if (ret != 0)
|
||||
if (of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY))
|
||||
return;
|
||||
|
||||
unittest(1, "overlay test %d passed\n", 15);
|
||||
@@ -1927,10 +2038,8 @@ static inline void of_unittest_overlay_i2c_15(void) { }
|
||||
static void __init of_unittest_overlay(void)
|
||||
{
|
||||
struct device_node *bus_np = NULL;
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&unittest_driver);
|
||||
if (ret != 0) {
|
||||
if (platform_driver_register(&unittest_driver)) {
|
||||
unittest(0, "could not register unittest driver\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -1941,8 +2050,7 @@ static void __init of_unittest_overlay(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = of_platform_default_populate(bus_np, NULL, NULL);
|
||||
if (ret != 0) {
|
||||
if (of_platform_default_populate(bus_np, NULL, NULL)) {
|
||||
unittest(0, "could not populate bus @ \"%s\"\n", bus_path);
|
||||
goto out;
|
||||
}
|
||||
@@ -2156,10 +2264,8 @@ static int __init overlay_data_apply(const char *overlay_name, int *overlay_id)
|
||||
}
|
||||
|
||||
size = info->dtb_end - info->dtb_begin;
|
||||
if (!size) {
|
||||
if (!size)
|
||||
pr_err("no overlay data for %s\n", overlay_name);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->overlay_id);
|
||||
if (overlay_id)
|
||||
@@ -2193,7 +2299,6 @@ static __init void of_unittest_overlay_high_level(void)
|
||||
struct device_node *overlay_base_symbols;
|
||||
struct device_node **pprev;
|
||||
struct property *prop;
|
||||
int ret;
|
||||
|
||||
if (!overlay_base_root) {
|
||||
unittest(0, "overlay_base_root not initialized\n");
|
||||
@@ -2284,19 +2389,15 @@ static __init void of_unittest_overlay_high_level(void)
|
||||
prop->name);
|
||||
goto err_unlock;
|
||||
}
|
||||
ret = __of_add_property(of_symbols, new_prop);
|
||||
if (ret) {
|
||||
if (!strcmp(new_prop->name, "name")) {
|
||||
/* auto-generated by unflatten */
|
||||
ret = 0;
|
||||
if (__of_add_property(of_symbols, new_prop)) {
|
||||
/* "name" auto-generated by unflatten */
|
||||
if (!strcmp(new_prop->name, "name"))
|
||||
continue;
|
||||
}
|
||||
unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
|
||||
prop->name);
|
||||
goto err_unlock;
|
||||
}
|
||||
ret = __of_add_property_sysfs(of_symbols, new_prop);
|
||||
if (ret) {
|
||||
if (__of_add_property_sysfs(of_symbols, new_prop)) {
|
||||
unittest(0, "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
|
||||
prop->name);
|
||||
goto err_unlock;
|
||||
@@ -2355,6 +2456,7 @@ static int __init of_unittest(void)
|
||||
of_unittest_find_node_by_name();
|
||||
of_unittest_dynamic();
|
||||
of_unittest_parse_phandle_with_args();
|
||||
of_unittest_parse_phandle_with_args_map();
|
||||
of_unittest_printf();
|
||||
of_unittest_property_string();
|
||||
of_unittest_property_copy();
|
||||
|
مرجع در شماره جدید
Block a user