olpc ofw question

Mitch Bradley wmb at firmworks.com
Thu Aug 12 11:53:44 EST 2010


Andres Salomon wrote:
> On Wed, 11 Aug 2010 22:48:43 +0200 (CEST)
> "Segher Boessenkool" <segher at kernel.crashing.org> wrote:
>
>   
>>> I've run a comparison between OLPC's old OFW code (which mounts the
>>> device-tree at /ofw, and makes use of the sparc code) versus the
>>> code which I'm planning to send upstream (which mounts the
>>> device-tree at /proc/device-tree, and makes use of PROC_DEVTREE).
>>> The results are here:
>>>       
>> [unit addresses are missing]
>>
>>     
>>> Any insight into the reasoning for this mangling?
>>>       
>> It sounds to me like you're not putting the (textual representation
>> of the) unit address in the device_node->full_name field.  How do
>> you fill that field?
>>     
>
> Ah, that could very well be it.  Note that the *old* OLPC code used the
> 'path_component_name' of device_node.  The new code uses just 'name' in
> pdt_build_full_name(), as path_component_name is #ifdef'd out
> for !SPARC.  I guess I'm not entirely sure why sparc used
> path_component_name in the first place..
>   

I think I understand the situation.  The guess that I articulated on IRC 
is essentially correct.  The (human-readable) text representation of the 
unit address - i.e. the stuff after "@" - is parent-bus-specific.  The 
numerical representation of a unit address is easily determined - it is 
the first "#address-cells" cells of the "reg" property.  But the 
rendering of that into ASCII is not as obvious.

A live OF environment gets the text representation by calling the parent 
bus's "decode-unit" method with the numerical representation as an 
argument.  (In the other direction, the "encode-unit" method goes from 
text to numerical.)   There's an easy way to get that effect via the 
client interface - just call "package-to-path" on the phandle, and OF 
will return the full pathname in canonical form.

If you look in arch/sparc/kernel/prom.c:sparc32_path_component() you'll 
see what is going on.  That routine derives a "name at address" string 
using a heuristic described in this comment:


/* The following routines deal with the black magic of fully naming a
 * node.
 *
 * Certain well known named nodes are just the simple name string.
 *
 * Actual devices have an address specifier appended to the base name
 * string, like this "foo at addr".  The "addr" can be in any number of
 * formats, and the platform plus the type of the node determine the
 * format and how it is constructed.
 *
 * For children of the ROOT node, the naming convention is fixed and
 * determined by whether this is a sun4u or sun4v system.
 *
 * For children of other nodes, it is bus type specific.  So
 * we walk up the tree until we discover a "device_type" property
 * we recognize and we go from there.
 */

As I described above, it's not really black magic; extract the numerical 
form of the unit address and pass it to the parent's encode-unit method 
.  Either someone didn't know about that, or perhaps they had some 
reason for not using it.  It's certainly do-able during the phase while 
OF is still alive.

In the non-SPARC case, I think the code was dealing with a flattened 
device tree, where the node name had already been pre-digested to 
include the @addr suffix.  In that case, decoding the unit address into 
the text representation was somebody else's problem, so there was no 
(non-SPARC) Linux code to handle it.

The "proc_of.c" code that I wrote in Dec 2006 uses the package-to-path 
method mentioned above, getting the "name at addr" representation 
(package-to-path returns the full path, but you can easily extract just 
the tail component with strrchr(path, '/'))

>
> The code that fills in full_name:
>
>                 dp->full_name = pdt_build_full_name(dp);
>
>
> static char * __init pdt_build_full_name(struct device_node *dp)
> {
>         int len, ourlen, plen;
>         char *n;
>
>         plen = strlen(dp->parent->full_name);
>         ourlen = strlen(fetch_node_name(dp));
>         len = ourlen + plen + 2;
>
>         n = prom_early_alloc(len);
>         strcpy(n, dp->parent->full_name);
>         if (!of_is_root_node(dp->parent)) {
>                 strcpy(n + plen, "/");
>                 plen++;
>         }
>         strcpy(n + plen, fetch_node_name(dp));
>
>         return n;
> }
>
> #if defined(CONFIG_SPARC)
> static inline const char *fetch_node_name(struct device_node *dp)
> {
>         return dp->path_component_name;
> }
> #else
> static inline const char *fetch_node_name(struct device_node *dp)
> {
>         return dp->name;
> }
> #endif
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
>
>   


More information about the devicetree-discuss mailing list