All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH 10/11] dtoc: Support adding subnodes alongside existing ones
Date: Sun, 21 Mar 2021 18:24:38 +1300	[thread overview]
Message-ID: <20210321052439.2238169-11-sjg@chromium.org> (raw)
In-Reply-To: <20210321052439.2238169-1-sjg@chromium.org>

So far we have only needed to add subnodes to empty notds, so have not
had to deal with ordering. However this feature is needed for binman's
expanded nodes, since there may be another node in the same section.

While libfdt adds new properties after existing properties, it adds new
subnodes before existing subnodes. This means that we must reorder the
nodes in the cached version, so that the ordering remains consistent.

Update the sync implementation to sync existing subnodes first, then
add new ones, then tidy up the ordering in the cached version. Update the
test to cover this behaviour.

Also improve the comment about property syncing while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 tools/dtoc/fdt.py      | 44 +++++++++++++++++++++++++++++++++---------
 tools/dtoc/test_fdt.py | 16 +++++++++++++++
 2 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index a5e1d0b52f6..63d1f68d816 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -503,9 +503,13 @@ class Node:
             auto_resize: Resize the device tree automatically if it does not
                 have enough space for the update
 
+        Returns:
+            True if the node had to be added, False if it already existed
+
         Raises:
             FdtException if auto_resize is False and there is not enough space
         """
+        added = False
         if self._offset is None:
             # The subnode doesn't exist yet, so add it
             fdt_obj = self._fdt._fdt_obj
@@ -519,23 +523,45 @@ class Node:
             else:
                 offset = fdt_obj.add_subnode(self.parent._offset, self.name)
             self._offset = offset
+            added = True
 
-        # Sync subnodes in reverse so that we don't disturb node offsets for
-        # nodes that are earlier in the DT. This avoids an O(n^2) rescan of
-        # node offsets.
+        # Sync the existing subnodes first, so that we can rely on the offsets
+        # being correct. As soon as we add new subnodes, it pushes all the
+        # existing subnodes up.
         for node in reversed(self.subnodes):
-            node.Sync(auto_resize)
+            if node._offset is not None:
+                node.Sync(auto_resize)
 
-        # Sync properties now, whose offsets should not have been disturbed.
-        # We do this after subnodes, since this disturbs the offsets of these
-        # properties. Note that new properties will have an offset of None here,
-        # which Python 3 cannot sort against int. So use a large value instead
-        # to ensure that the new properties are added first.
+        # Sync subnodes in reverse so that we get the expected order. Each
+        # new node goes at the start of the subnode list. This avoids an O(n^2)
+        # rescan of node offsets.
+        num_added = 0
+        for node in reversed(self.subnodes):
+            if node.Sync(auto_resize):
+                num_added += 1
+        if num_added:
+            # Reorder our list of nodes to put the new ones first, since that's
+            # what libfdt does
+            old_count = len(self.subnodes) - num_added
+            subnodes = self.subnodes[old_count:] + self.subnodes[:old_count]
+            self.subnodes = subnodes
+
+        # Sync properties now, whose offsets should not have been disturbed,
+        # since properties come before subnodes. This is done after all the
+        # subnode processing above, since updating properties can disturb the
+        # offsets of those subnodes.
+        # Properties are synced in reverse order, with new properties added
+        # before existing properties are synced. This ensures that the offsets
+        # of earlier properties are not disturbed.
+        # Note that new properties will have an offset of None here, which
+        # Python cannot sort against int. So use a large value instead so that
+        # new properties are added first.
         prop_list = sorted(self.props.values(),
                            key=lambda prop: prop._offset or 1 << 31,
                            reverse=True)
         for prop in prop_list:
             prop.Sync(auto_resize)
+        return added
 
 
 class Fdt:
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index 1e66e1bc353..49a2853f07f 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -237,6 +237,22 @@ class TestNode(unittest.TestCase):
         """Test adding various subnode and properies"""
         node = self.dtb.GetNode('/i2c at 0')
 
+        # Add one more node next to the pmic one
+        sn1 = node.AddSubnode('node-one')
+        sn1.AddInt('integer-a', 12)
+        sn1.AddInt('integer-b', 23)
+
+        # Sync so that everything is clean
+        self.dtb.Sync(auto_resize=True)
+
+        # Add two subnodes next to pmic and node-one
+        sn2 = node.AddSubnode('node-two')
+        sn2.AddInt('integer-2a', 34)
+        sn2.AddInt('integer-2b', 45)
+
+        sn3 = node.AddSubnode('node-three')
+        sn3.AddInt('integer-3', 123)
+
         # Add a property to the node after i2c at 0 to check that this is not
         # disturbed by adding a subnode to i2c@0
         orig_node = self.dtb.GetNode('/orig-node')
-- 
2.31.0.rc2.261.g7f71774620-goog

  parent reply	other threads:[~2021-03-21  5:24 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-21  5:24 [PATCH 00/11] binman: Enhancements to expanded entries Simon Glass
2021-03-21  5:24 ` [PATCH 01/11] binman: Use a unique number for the symbols test file Simon Glass
2021-03-21  5:24 ` [PATCH 02/11] binman: Allow disabling expanding an entry Simon Glass
2021-03-21  5:24 ` [PATCH 03/11] binman: Add support for a collection of entries Simon Glass
2021-03-21  5:24 ` [PATCH 04/11] binman: Support obtaining section contents immediately Simon Glass
2021-03-21  5:24 ` [PATCH 05/11] binman: Support default alignment for sections Simon Glass
2021-03-21  5:24 ` [PATCH 06/11] dtoc: Improve internal error for Refresh() Simon Glass
2021-03-21  5:24 ` [PATCH 07/11] dtoc: Tidy up property-offset handling Simon Glass
2021-03-21  5:24 ` [PATCH 08/11] dtoc: Tweak ordering of fdt-offsets refreshing Simon Glass
2021-03-21  5:24 ` [PATCH 09/11] dtoc: Add a subnode test for multiple nodes Simon Glass
2021-03-21  5:24 ` Simon Glass [this message]
2021-03-21  5:24 ` [PATCH 11/11] dtoc: Add new check that offsets are correct Simon Glass
2021-03-27  5:19 ` [PATCH 10/11] dtoc: Support adding subnodes alongside existing ones Simon Glass
2021-03-27  5:19 ` [PATCH 11/11] dtoc: Add new check that offsets are correct Simon Glass
2021-03-27  5:19 ` [PATCH 09/11] dtoc: Add a subnode test for multiple nodes Simon Glass
2021-03-27  5:19 ` [PATCH 08/11] dtoc: Tweak ordering of fdt-offsets refreshing Simon Glass
2021-03-27  5:19 ` [PATCH 07/11] dtoc: Tidy up property-offset handling Simon Glass
2021-03-27  5:19 ` [PATCH 06/11] dtoc: Improve internal error for Refresh() Simon Glass
2021-03-27  5:19 ` [PATCH 05/11] binman: Support default alignment for sections Simon Glass
2021-03-27  5:19 ` [PATCH 03/11] binman: Add support for a collection of entries Simon Glass
2021-03-27  5:19 ` [PATCH 04/11] binman: Support obtaining section contents immediately Simon Glass
2021-03-27  5:20 ` [PATCH 02/11] binman: Allow disabling expanding an entry Simon Glass
2021-03-27  5:20 ` [PATCH 01/11] binman: Use a unique number for the symbols test file Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210321052439.2238169-11-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.