devicetree-compiler.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Fair <b-fair-l0cyMroinI0@public.gmane.org>
To: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
Cc: Jon Loeliger <jdl-CYoMK+44s/E@public.gmane.org>,
	Nishanth Menon <nm-l0cyMroinI0@public.gmane.org>,
	Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH] libfdt: add helpers to read address and size from reg
Date: Mon, 5 Dec 2016 11:46:31 -0600	[thread overview]
Message-ID: <c0553cfe-b902-8fa7-e2fc-dafc0523d4b2@ti.com> (raw)
In-Reply-To: <20161202031256.GB10089-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>

On 12/01/2016 09:12 PM, David Gibson wrote:
> On Wed, Nov 30, 2016 at 01:35:04PM -0600, Benjamin Fair wrote:
>> On 11/25/2016 04:51 AM, David Gibson wrote:
>>> On Wed, Nov 09, 2016 at 10:58:32AM -0600, Benjamin Fair wrote:
>> [...]
>>>
>>> I like the concept of a helper to read entries from reg, but there
>>> some things about the execution of it I think need some more thought.
>>>
>>
>> Thanks for the review.
>>
>> [...]
>>>> diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c
>>>> index eff4dbc..92cbed9 100644
>>>> --- a/libfdt/fdt_addresses.c
>>>> +++ b/libfdt/fdt_addresses.c
>>>> @@ -55,6 +55,9 @@
>>>>
>>>>  #include "libfdt_internal.h"
>>>>
>>>> +#define BYTES_PER_CELL 4
>>>> +#define BITS_PER_CELL 32
>>>
>>> You shouldn't need these.  BYTES_PER_CELL == sizeof(fdt32_t).
>>>
>>
>> Of course. Thanks. I'll get rid of them.
>>
>>>> +
>>>>  int fdt_address_cells(const void *fdt, int nodeoffset)
>>>>  {
>>>>  	const fdt32_t *ac;
>>>> @@ -94,3 +97,62 @@ int fdt_size_cells(const void *fdt, int nodeoffset)
>>>>
>>>>  	return val;
>>>>  }
>>>> +
>>>> +static uint64_t _fdt_read_cells(const fdt32_t *cells, int n)
>>>
>>> This is a reasonable helper, but the name is bad.  "read_cells"
>>> suggests it can read some arbitrary number of cells, but in fact all
>>> it can do is read a 32-bit int or a 64-bit int.  Plus everything is
>>> made up of cells, but more specifically what you're doing here is
>>> interpreting several cells as an integer in the usual encoding.
>>>
>>
>> Would "cells_to_integer" be a better name? Or would you recommend something
>> else for this?
>
> cells_to_integer would be ok.  Or just fdt_read_integer().
>

Thanks for the suggestion. I changed it to fdt_read_integer()

>>
>>>> +{
>>>> +	int i;
>>>> +	uint64_t res;
>>>> +
>>>> +	/* TODO: Support values larger than 2 cells */
>>>
>>> I don't really see any way you could support >2 cells without
>>> completely changing the interface.
>>>
>>
>> True. I wanted to have the result be a 128 bit integer, but couldn't find a
>> portable way to do so. Is there a better way to go about this? Or is it fine
>> to only support at most 2 cells, even though the rest of libfdt supports 4?
>
> I think just supporting 2 cells is ok - it's useful in enough
> practical cases.  However, I'd suggest thinking of this in a more
> layered way.
>
> First, create a helper which just locates the relevant pieces of reg
> entries, returning addresses and sizes as (fdt32_t *).  That's at
> least somewhat useful for the >2 cells case, even though you have to
> then parse the address/size yourself.  In the most common case for
> this, PCI (address-cells == 3), you probably want to do that anyway.
> This may also be useful for cases which are <= 2 cells, but the
> encoding of the address is not just a plain integer.
>
> You can then polish up fdt_read_integer() a bit and export it.
>
> Finally you can add another helper which combines these to directly
> get you the addr+size as u64 for buses where that's suitable.  Make
> sure to return an error if #a or #s > 2, of course.
>

That seems like a good idea. I implemented this for the next revision.

>>>> +	if (n > 2)
>>>> +		return -FDT_ERR_BADNCELLS;
>>>> +
>>>> +	res = 0;
>>>> +	for (i = 0; i < n; i++) {
>>>> +		res <<= BITS_PER_CELL;
>>>> +		res |= fdt32_to_cpu(cells[i]);
>>>> +	}
>>>> +
>>>> +	return res;
>>>> +}
>>>> +
>>>> +int fdt_simple_addr_size(const void *fdt, int nodeoffset, int idx,
>>>> +			 uintptr_t *addr, size_t *size)
>>>> +{
>>>> +	int parent;
>>>> +	int ac, sc, reg_stride;
>>>> +	int res;
>>>> +	const fdt32_t *reg;
>>>> +
>>>> +	reg = fdt_getprop(fdt, nodeoffset, "reg", &res);
>>>> +	if (res < 0)
>>>> +		return res;
>>>> +
>>>> +	parent = fdt_parent_offset(fdt, nodeoffset);
>>>> +	if (parent < 0)
>>>> +		return res;
>>>
>>> So, fdt_parent_offset() is very expensive, I wouldn't recommend it in
>>> a function that's likely to be called a lot like this.  Instead I'd
>>> suggest a function which takes the parent offset as a parameter, and
>>> optionally a wrapper that uses fdt_parent_offset().
>>
>> Great idea, I'll do this in the next revision once we have a solution for
>> the rest of the comments.
>>

Would it be OK to pass in the number of address cells and number of 
size cells directly instead of the parent offset?

I was thinking about this in order to minimize repeated work. Plus, 
the calling function needs to know this information in order to 
interpret the results anyway.

>>>
>>>> +
>>>> +	ac = fdt_address_cells(fdt, parent);
>>>> +	if (ac < 0)
>>>> +		return ac;
>>>> +
>>>> +	sc = fdt_size_cells(fdt, parent);
>>>> +	if (sc < 0)
>>>> +		return sc;
>>>> +
>>>> +	reg_stride = ac + sc;
>>>> +	/*
>>>> +	 * res is the number of bytes read and must be an even multiple of the
>>>> +	 * sum of ac and sc.
>>>> +	 */
>>>> +	if ((res % (reg_stride * BYTES_PER_CELL)) != 0)
>>>> +		return -FDT_ERR_BADVALUE;
>>>> +
>>>> +	if (addr)
>>>> +		*addr = (uintptr_t) _fdt_read_cells(&reg[reg_stride * idx], ac);
>>>
>>> I don't think uintptr_t makes sense here.  The addresses in the device
>>> tree are in whatever bus they're in, and there are a whole stack of
>>> reasons that could be unrelated to the pointer size of environment
>>> libfdt is running in:
>>>     - The device may be on a subordinate bus whose addresses need
>>>       to be translated
>>>     - Even at the top-level, the reg properties represent
>>>       *physical* addresses, which may not be the same as virtual
>>>       addresses  in code running on the system
>>>     - libfdt may be running on a completely different system from the
>>>       one the device tree in question is aimed at (bootloaders are
>>>       only one use case for libfdt).
>>>
>>>> +	if (size)
>>>> +		*size = (size_t) _fdt_read_cells(&reg[ac + reg_stride * idx],
>>>> +						 sc);
>>>
>>> Likewise size_t isn't necessarily right here, although I suspect it's
>>> less likely to break in practice.
>>>
>>
>> Hmm... Is it fine to use uint64_t for both of these instead then?
>
> Yes, I think that's reasonable.  Or you could even use unsigned long
> or unsigned long long - as long as you error whenever #cells is too
> big for the size of that type.  uint64_t is probably clearer and more
> consistent, though.
>

Thanks, I changed it to use uint64_t

-- 
Benjamin Fair

  parent reply	other threads:[~2016-12-05 17:46 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-09 16:58 [PATCH] libfdt: add helpers to read address and size from reg Benjamin Fair
     [not found] ` <1478710712-25010-1-git-send-email-b-fair-l0cyMroinI0@public.gmane.org>
2016-11-18 17:37   ` Benjamin Fair
     [not found]     ` <99dd8a63-19bb-0d06-8bc2-f2ad575ca2cb-l0cyMroinI0@public.gmane.org>
2016-11-18 18:05       ` Nishanth Menon
     [not found]         ` <8730ced3-41c1-e515-ff93-6f719abb5800-l0cyMroinI0@public.gmane.org>
2016-11-22  3:40           ` David Gibson
2016-11-22  3:39       ` David Gibson
2016-11-25 10:51   ` David Gibson
     [not found]     ` <20161125105125.GJ12287-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2016-11-30 19:35       ` Benjamin Fair
     [not found]         ` <2f744a7f-5112-c83e-d47a-ce9fef491dde-l0cyMroinI0@public.gmane.org>
2016-12-02  3:12           ` David Gibson
     [not found]             ` <20161202031256.GB10089-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2016-12-05 17:46               ` Benjamin Fair [this message]
     [not found]                 ` <c0553cfe-b902-8fa7-e2fc-dafc0523d4b2-l0cyMroinI0@public.gmane.org>
2016-12-05 21:46                   ` David Gibson

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=c0553cfe-b902-8fa7-e2fc-dafc0523d4b2@ti.com \
    --to=b-fair-l0cymroini0@public.gmane.org \
    --cc=david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org \
    --cc=devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=jdl-CYoMK+44s/E@public.gmane.org \
    --cc=nm-l0cyMroinI0@public.gmane.org \
    --cc=robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).