Merge tag 'devicetree-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree updates from Rob Herring: - Rewrite of the unflattening code to avoid recursion and lessen the stack usage. - Rewrite of the phandle args parsing code to get rid of the fixed args size. This is needed for IOMMU code. - Sync to latest dtc which adds more dts style checking. These warnings are enabled with "W=1" compiles. - Tegra documentation updates related to the above warnings. - A bunch of spelling and other doc fixes. - Various vendor prefix additions. * tag 'devicetree-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (52 commits) devicetree: Add Creative Technology vendor id gpio: dt-bindings: add ibm,ppc4xx-gpio binding of/unittest: Remove unnecessary module.h header inclusion drivers/of: Fix build warning in populate_node() drivers/of: Fix depth when unflattening devicetree of: dynamic: changeset prop-update revert fix drivers/of: Export of_detach_node() drivers/of: Return allocated memory from of_fdt_unflatten_tree() drivers/of: Specify parent node in of_fdt_unflatten_tree() drivers/of: Rename unflatten_dt_node() drivers/of: Avoid recursively calling unflatten_dt_node() drivers/of: Split unflatten_dt_node() of: include errno.h in of_graph.h of: document refcount incrementation of of_get_cpu_node() Documentation: dt: soc: fix spelling mistakes Documentation: dt: power: fix spelling mistake Documentation: dt: pinctrl: fix spelling mistake Documentation: dt: opp: fix spelling mistake Documentation: dt: net: fix spelling mistakes Documentation: dt: mtd: fix spelling mistake ...
This commit is contained in:
+143
-82
@@ -394,7 +394,8 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
|
||||
* before booting secondary cores. This function uses arch_match_cpu_phys_id
|
||||
* which can be overridden by architecture specific implementation.
|
||||
*
|
||||
* Returns a node pointer for the logical cpu if found, else NULL.
|
||||
* Returns a node pointer for the logical cpu with refcount incremented, use
|
||||
* of_node_put() on it when done. Returns NULL if not found.
|
||||
*/
|
||||
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
|
||||
{
|
||||
@@ -1440,106 +1441,155 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *cells_name,
|
||||
int cell_count)
|
||||
{
|
||||
const __be32 *list;
|
||||
int size;
|
||||
|
||||
memset(it, 0, sizeof(*it));
|
||||
|
||||
list = of_get_property(np, list_name, &size);
|
||||
if (!list)
|
||||
return -ENOENT;
|
||||
|
||||
it->cells_name = cells_name;
|
||||
it->cell_count = cell_count;
|
||||
it->parent = np;
|
||||
it->list_end = list + size / sizeof(*list);
|
||||
it->phandle_end = list;
|
||||
it->cur = list;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int of_phandle_iterator_next(struct of_phandle_iterator *it)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
if (it->node) {
|
||||
of_node_put(it->node);
|
||||
it->node = NULL;
|
||||
}
|
||||
|
||||
if (!it->cur || it->phandle_end >= it->list_end)
|
||||
return -ENOENT;
|
||||
|
||||
it->cur = it->phandle_end;
|
||||
|
||||
/* If phandle is 0, then it is an empty entry with no arguments. */
|
||||
it->phandle = be32_to_cpup(it->cur++);
|
||||
|
||||
if (it->phandle) {
|
||||
|
||||
/*
|
||||
* Find the provider node and parse the #*-cells property to
|
||||
* determine the argument length.
|
||||
*/
|
||||
it->node = of_find_node_by_phandle(it->phandle);
|
||||
|
||||
if (it->cells_name) {
|
||||
if (!it->node) {
|
||||
pr_err("%s: could not find phandle\n",
|
||||
it->parent->full_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(it->node, it->cells_name,
|
||||
&count)) {
|
||||
pr_err("%s: could not get %s for %s\n",
|
||||
it->parent->full_name,
|
||||
it->cells_name,
|
||||
it->node->full_name);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
count = it->cell_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the arguments actually fit in the remaining
|
||||
* property data length
|
||||
*/
|
||||
if (it->cur + count > it->list_end) {
|
||||
pr_err("%s: arguments longer than property\n",
|
||||
it->parent->full_name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
it->phandle_end = it->cur + count;
|
||||
it->cur_count = count;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (it->node) {
|
||||
of_node_put(it->node);
|
||||
it->node = NULL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
||||
uint32_t *args,
|
||||
int size)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
count = it->cur_count;
|
||||
|
||||
if (WARN_ON(size < count))
|
||||
count = size;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
args[i] = be32_to_cpup(it->cur++);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int __of_parse_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *cells_name,
|
||||
int cell_count, int index,
|
||||
struct of_phandle_args *out_args)
|
||||
{
|
||||
const __be32 *list, *list_end;
|
||||
int rc = 0, size, cur_index = 0;
|
||||
uint32_t count = 0;
|
||||
struct device_node *node = NULL;
|
||||
phandle phandle;
|
||||
|
||||
/* Retrieve the phandle list property */
|
||||
list = of_get_property(np, list_name, &size);
|
||||
if (!list)
|
||||
return -ENOENT;
|
||||
list_end = list + size / sizeof(*list);
|
||||
struct of_phandle_iterator it;
|
||||
int rc, cur_index = 0;
|
||||
|
||||
/* Loop over the phandles until all the requested entry is found */
|
||||
while (list < list_end) {
|
||||
rc = -EINVAL;
|
||||
count = 0;
|
||||
|
||||
of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
|
||||
/*
|
||||
* If phandle is 0, then it is an empty entry with no
|
||||
* arguments. Skip forward to the next entry.
|
||||
*/
|
||||
phandle = be32_to_cpup(list++);
|
||||
if (phandle) {
|
||||
/*
|
||||
* Find the provider node and parse the #*-cells
|
||||
* property to determine the argument length.
|
||||
*
|
||||
* This is not needed if the cell count is hard-coded
|
||||
* (i.e. cells_name not set, but cell_count is set),
|
||||
* except when we're going to return the found node
|
||||
* below.
|
||||
*/
|
||||
if (cells_name || cur_index == index) {
|
||||
node = of_find_node_by_phandle(phandle);
|
||||
if (!node) {
|
||||
pr_err("%s: could not find phandle\n",
|
||||
np->full_name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (cells_name) {
|
||||
if (of_property_read_u32(node, cells_name,
|
||||
&count)) {
|
||||
pr_err("%s: could not get %s for %s\n",
|
||||
np->full_name, cells_name,
|
||||
node->full_name);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
count = cell_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the arguments actually fit in the
|
||||
* remaining property data length
|
||||
*/
|
||||
if (list + count > list_end) {
|
||||
pr_err("%s: arguments longer than property\n",
|
||||
np->full_name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* All of the error cases above bail out of the loop, so at
|
||||
* All of the error cases bail out of the loop, so at
|
||||
* this point, the parsing is successful. If the requested
|
||||
* index matches, then fill the out_args structure and return,
|
||||
* or return -ENOENT for an empty entry.
|
||||
*/
|
||||
rc = -ENOENT;
|
||||
if (cur_index == index) {
|
||||
if (!phandle)
|
||||
if (!it.phandle)
|
||||
goto err;
|
||||
|
||||
if (out_args) {
|
||||
int i;
|
||||
if (WARN_ON(count > MAX_PHANDLE_ARGS))
|
||||
count = MAX_PHANDLE_ARGS;
|
||||
out_args->np = node;
|
||||
out_args->args_count = count;
|
||||
for (i = 0; i < count; i++)
|
||||
out_args->args[i] = be32_to_cpup(list++);
|
||||
int c;
|
||||
|
||||
c = of_phandle_iterator_args(&it,
|
||||
out_args->args,
|
||||
MAX_PHANDLE_ARGS);
|
||||
out_args->np = it.node;
|
||||
out_args->args_count = c;
|
||||
} else {
|
||||
of_node_put(node);
|
||||
of_node_put(it.node);
|
||||
}
|
||||
|
||||
/* Found it! return success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
of_node_put(node);
|
||||
node = NULL;
|
||||
list += count;
|
||||
cur_index++;
|
||||
}
|
||||
|
||||
@@ -1547,12 +1597,11 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
|
||||
* Unlock node before returning result; will be one of:
|
||||
* -ENOENT : index is for empty phandle
|
||||
* -EINVAL : parsing error on data
|
||||
* [1..n] : Number of phandle (count mode; when index = -1)
|
||||
*/
|
||||
rc = index < 0 ? cur_index : -ENOENT;
|
||||
|
||||
err:
|
||||
if (node)
|
||||
of_node_put(node);
|
||||
if (it.node)
|
||||
of_node_put(it.node);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1684,8 +1733,20 @@ EXPORT_SYMBOL(of_parse_phandle_with_fixed_args);
|
||||
int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
|
||||
const char *cells_name)
|
||||
{
|
||||
return __of_parse_phandle_with_args(np, list_name, cells_name, 0, -1,
|
||||
NULL);
|
||||
struct of_phandle_iterator it;
|
||||
int rc, cur_index = 0;
|
||||
|
||||
rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
while ((rc = of_phandle_iterator_next(&it)) == 0)
|
||||
cur_index += 1;
|
||||
|
||||
if (rc != -ENOENT)
|
||||
return rc;
|
||||
|
||||
return cur_index;
|
||||
}
|
||||
EXPORT_SYMBOL(of_count_phandle_with_args);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user