Commit 8c237cd0 authored by Gavin Shan's avatar Gavin Shan Committed by Rob Herring

drivers/of: Fix depth for sub-tree blob in unflatten_dt_nodes()

The function is unflattening device sub-tree blob if @dad passed to
the function is valid. Currently, this functionality is used by PPC
PowerNV PCI hotplug driver only. There are possibly multiple nodes
in the first level of depth, fdt_next_node() bails immediately when
@depth becomes negative before the second device node can be probed
successfully. It leads to the device nodes except the first one won't
be unflattened successfully.

This fixes the issue by setting the initial depth (@inital_depth) to
1 when this function is called to unflatten device sub-tree blob. No
logic changes when this function is used to unflatten non-sub-tree
blob.

Cc: Rhyland Klein <rklein@nvidia.com>
Fixes: 78c44d91 ("drivers/of: Fix depth when unflattening devicetree")
Signed-off-by: default avatarGavin Shan <gwshan@linux.vnet.ibm.com>
Tested-by: default avatarRhyland Klein <rklein@nvidia.com>
Tested-by: default avatarAndrew Donnellan <andrew.donnellan@au1.ibm.com>
Signed-off-by: default avatarRob Herring <robh@kernel.org>
parent 5c1d3310
...@@ -395,7 +395,7 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -395,7 +395,7 @@ static int unflatten_dt_nodes(const void *blob,
struct device_node **nodepp) struct device_node **nodepp)
{ {
struct device_node *root; struct device_node *root;
int offset = 0, depth = 0; int offset = 0, depth = 0, initial_depth = 0;
#define FDT_MAX_DEPTH 64 #define FDT_MAX_DEPTH 64
unsigned int fpsizes[FDT_MAX_DEPTH]; unsigned int fpsizes[FDT_MAX_DEPTH];
struct device_node *nps[FDT_MAX_DEPTH]; struct device_node *nps[FDT_MAX_DEPTH];
...@@ -405,11 +405,22 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -405,11 +405,22 @@ static int unflatten_dt_nodes(const void *blob,
if (nodepp) if (nodepp)
*nodepp = NULL; *nodepp = NULL;
/*
* We're unflattening device sub-tree if @dad is valid. There are
* possibly multiple nodes in the first level of depth. We need
* set @depth to 1 to make fdt_next_node() happy as it bails
* immediately when negative @depth is found. Otherwise, the device
* nodes except the first one won't be unflattened successfully.
*/
if (dad)
depth = initial_depth = 1;
root = dad; root = dad;
fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0; fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0;
nps[depth] = dad; nps[depth] = dad;
for (offset = 0; for (offset = 0;
offset >= 0 && depth >= 0; offset >= 0 && depth >= initial_depth;
offset = fdt_next_node(blob, offset, &depth)) { offset = fdt_next_node(blob, offset, &depth)) {
if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH)) if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment