[U-Boot-Users] LIBFDT: first version of fdt_find_compatible_node

Wolfgang Grandegger wg at grandegger.com
Thu Apr 26 09:39:32 CEST 2007

Jerry Van Baren wrote:
> Wolfgang Grandegger wrote:
>> Jerry Van Baren wrote:
>>> Wolfgang Grandegger wrote:
>>>> Hello,
>>>> attached you can find a patch implementing fdt_find_compatible_node():
> [snip]
>>> For the above version of fdt_find_compatible_node(), as well as the 
>>> one that fills the cache table (snipped), I'm thinking it would be 
>>> better to use the function I added:
>>> uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset, 
>>> char **namep)
>>> I added this to step through the nodes and properties for dumping the 
>>> tree.  Rather than having Yet Another (slightly modified) Copy of the 
>>> loop & switch, you should be able to use fdt_next_tag() to step 
>>> through the nodes and properties, doing the
>>>   if (streq(fdt_string(fdt, namestroff), "device_type"))
>>> on the **namep parameter on every call to find the device_type 
>>> properties.  Does this make sense?
>> Yes, my concern was the overhead due to looking up the location of 
>> each node name and property. But for fast scanning, the cached version 
>> is much better anyhow, I think.
>> What is your opinion on the cached version? Do we need it? Should we 
>> keep both?
>> Wolfgang.
> Hi wg,
> Yes, blob parsing will be done from the start of the blob until an 
> answer is found every time a question is asked of it.  Not a paradigm of 
> efficiency. :-/
> WRT the cached version, I have doubts about how much time it will save 
> since I expect the "find compatible" will only be used during 
> initialization.  Is it worth optimizing?  Really slow memory - yes. Fast 
> memory - I doubt it.
> a) I don't picture blobs being stored in really slow memory (no i2c 
> memories).
> b) If the memory really is slow, it seems like it would be as good or 
> better to copy the blob to RAM and use it out of RAM (but there may be 
> chicken & egg problems with that - I don't know how deeply you are 
> looking to embed this).
> I don't know what board/processor/memory you are ultimately targeting 
> with this, so my criticisms may not be valid.  I know denx.de 
> support(s|ed) some very slow to boot boards that lots of tricks were 
> done WRT optimization of env variables because they were stored in i2c 
> memory.

I'm doing that for a MPC823 at 50 MHz, a very low-end system, and almost 
to slow for 2.6. I will do some real measurements when time permits to 
get a better feeling.

> --------
> Other puzzlements:
> You are storing "level" in the cache table, I don't see why.  That is 
> only used while scanning the blob to keep track of node nesting and 
> unnesting and exit when we've unnested back out to the original level. 
> Nesting isn't really applicable when it is in the cache.
> In fdt_find_compatible_node() you have local static variables:
> +    static int level, typefound;
> +    static int nodeoffset, nextoffset;
> and I don't understand why.  I expected them to be auto variables, 
> initialized on entry and discarded on exit.

This is to continue a scan started with startoffset=0.

  *   startoffset  - the node to start searching from or 0, the node
  *                  you pass will not be searched, only the next one
  *                  will; typically, you pass 0 to start the search
  *                  and then what the previous call returned.

And it could be used in the following way:

  offset = 0;
  do {
      offset = fdt_find_compatible_node(fdt, offset, "type", "comp");
  } while (offset >= 0);

This is to be compatible with the Linux version (prom.c) and to scan for 
more than one compatible device efficiently (without re-scanning). For 
example, for the MPC5200 there are 8 compatible GPTs defined. To do so, 
we must preserve nextoffset and level. I also preserve typefound and 
nodeoffset for efficiency reasons and to check sub-sequent calls of 

> Looking closer at your cached version, I see you really are using 
> nodeoffset as a persistent variable there and I cringe a bit.  That 
> implementation presumes you ask questions sequentially or always reset 
> to 0.  This would prevent you from, for instance, searching for the 
> "/soc8360 at ..." node using fdt_path_offset() and then looking for devices 
> inside that node.  Given what is being represented and how, perhaps I'm 
> creating an unreasonable strawman.

Yes that's the current behaviour for both versions. I thought a scan 
will always be started with 0. Nevertheless, as I see it, the Linux 
version does not use the hierarchy but just scans all device (nodes) 
sequentially. But this could be changed easily and I was already 
thinking to do so.

> Instead of using a static variable, you could scan the cache table for 
> an element whose stored offset is greater than or equal to startoffset, 
> and search the table forward from there (the offsets in the table will 
> be monotonically increasing because of how you build the table). 
> Slightly less efficient, but it will still be pretty good and much 
> better than scanning the whole blob... or maybe I'm complaining based on 
> an unreasonable strawman.

Slightly less efficient, yes, that was my motivation. In U-Boot we 
access the libfdt always sequentially and therefore the trick with 
static variables for efficiency seems OK to me.

> After writing all the above, it bothers me a bit that the hierarchical 
> tree structure of the device tree is getting stuck into a one 
> dimensional cache (the hierarchy is lost), but I cannot think at this 
> point why that would bite us down the road.

See above. I have to check my assumption, though. Let's  clarify first 
the intended behavior of fdt_find_compatible_node().


More information about the U-Boot mailing list