From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
To: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Devicetree Compiler
<devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [PATCH 1/2] checks: add phandle with arg property checks
Date: Sat, 19 Aug 2017 17:33:33 +1000 [thread overview]
Message-ID: <20170819073333.GA12356@umbus.fritz.box> (raw)
In-Reply-To: <CAL_Jsq+yA2W=SD9zSkWxw-R16uNELeqPqJK3fVMvi0_jhEbooQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 9012 bytes --]
On Fri, Aug 18, 2017 at 11:02:01AM -0500, Rob Herring wrote:
> On Thu, Aug 17, 2017 at 11:35 PM, David Gibson
> <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> > On Mon, Aug 14, 2017 at 04:48:06PM -0500, Rob Herring wrote:
> >
> > Yay! Someone actually implementing checks.
>
> Not like it is my first. I'll celebrate when someone else does.
>
>
> >> Many common bindings follow the same pattern of client properties
> >> containing a phandle and N arg cells where N is defined in the provider
> >> with a '#<specifier>-cells' property. Add a checks for properties
> >> following this pattern.
> >
> > I think this description would be easier to follow if you led with an example.
> >
> >>
> >> Signed-off-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> >
> > Looks pretty good, though I have some suggestions.
> >
> >> ---
> >> checks.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 117 insertions(+)
> >>
> >> diff --git a/checks.c b/checks.c
> >> index afabf64337d5..c0450e118043 100644
> >> --- a/checks.c
> >> +++ b/checks.c
> >> @@ -956,6 +956,120 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
> >> WARNING(obsolete_chosen_interrupt_controller,
> >> check_obsolete_chosen_interrupt_controller, NULL);
> >>
> >> +struct provider {
> >> + const char *prop_name;
> >> + const char *cell_name;
> >> + bool optional;
> >> +};
> >> +
> >> +static void check_property_phandle_args(struct check *c,
> >> + struct dt_info *dti,
> >> + struct node *node,
> >> + struct property *prop,
> >> + const struct provider *provider)
> >> +{
> >> + struct marker *m = prop->val.markers;
> >> +
> >> + if (!m) {
> >> + FAIL(c, dti, "Missing phandles in %s:%s",
> >> + node->fullpath, prop->name);
> >> + return;
> >> + }
> >> + for_each_marker_of_type(m, REF_PHANDLE) {
> >
> > So going through the markers I think is not the best approach.
> > That'll work if the source contains a reference here, which it usually
> > will, but there are some circumstances where it could contain a "raw"
> > phandle value (the most obvious being when you're decompiling an
> > existing dtb).
> >
> > But I don't think you really need to. Instead you should be able to
> > read the actual value, look it up with get_node_by_phandle(). You can
> > make this check dependent on fixup_phandle_references to make sure
> > it's executed after the references are resolved.
>
> That's how I implemented it initially...
Ok.. why did you change?
> > That should also let you more strictly verify the property in the
> > client node, including checking for misaligned entries of extraneous bits.
> >
> >> + int cellsize;
> >> + struct node *root = dti->dt;
> >> + struct node *provider_node;
> >> + struct property *cellprop;
> >> +
> >> + provider_node = get_node_by_ref(root, m->ref);
> >> + if (!provider_node) {
> >> + FAIL(c, dti, "Could not get provider for %s:%s",
> >> + node->fullpath, prop->name);
> >> + break;
> >> + }
> >
> > AFAIK the "provider" terminology isn't standardized somewhere. It's a
> > reasonable term internally, but if can rephrase to it in the displayed
> > messages that would be a bonus.
>
> The kernel uses that at least. I guess maybe "phandle node" will work.
Hm, if the kernel uses the term, that's probably enough, actually.
> >> + cellprop = get_property(provider_node, provider->cell_name);
> >> + if (cellprop) {
> >> + cellsize = propval_cell(cellprop);
> >> + } else if (provider->optional) {
> >> + cellsize = 0;
> >> + } else {
> >> + FAIL(c, dti, "Missing %s in provider %s for %s",
> >> + provider->cell_name,
> >> + provider_node->fullpath,
> >> + node->fullpath);
> >> + break;
> >> + }
> >> +
> >> + if (prop->val.len < ((cellsize + 1) * sizeof(cell_t))) {
> >> + FAIL(c, dti, "%s property size (%d) too small for cell size %d in %s",
> >> + prop->name, prop->val.len, cellsize, node->fullpath);
> >> + }
> >> + }
> >> +}
> >> +
> >> +static const struct provider providers[] = {
> >> + { "clocks", "#clock-cells" },
> >> + { "phys", "#phy-cells" },
> >> + { "interrupts-extended", "#interrupt-cells" },
> >> + { "mboxes", "#mbox-cells" },
> >> + { "pwms", "#pwm-cells" },
> >> + { "dmas", "#dma-cells" },
> >> + { "resets", "#reset-cells" },
> >> + { "hwlocks", "#hwlock-cells" },
> >> + { "power-domains", "#power-domain-cells" },
> >> + { "io-channels", "#io-channel-cells" },
> >> + { "iommus", "#iommu-cells" },
> >> + { "mux-controls", "#mux-control-cells" },
> >> + { "cooling-device", "#cooling-cells" },
> >> + { "thermal-sensors", "#thermal-sensor-cells" },
> >> + { "sound-dais", "#sound-dai-cells" },
> >> + { "msi-parent", "#msi-cells", true },
> >> + { NULL },
> >> +};
> >
> > How hard would it be to use macros to make each of these providers
> > different check structures. I think the output would be a bit more
> > useful if errors in different types of these things was reported as a
> > different check failure rather than one big generic one.
>
> Should be doable.
Ok. Not essential, but I think it would improve the output.
> > It does mean listing everything in the check_table which is a pain. I
> > would really like to change things so that a single macro can both
> > declare the check and add it to the master list, but I haven't thought
> > of a portable way to do that so far.
>
> This is done in the kernel frequently using linker sections. Each
> check entry would get put into a specific section, then you just
> iterate through the entries. Would that work? I could imagine that
> linker magic may not be all the portable.
Right. Linker sections are the usual way to do this, but that
requires lower level knowledge of how the toolchain works than I
really want to put into dtc. At heart dtc is really a very
straightforward standard C program, so I don't want to introduce
dependencies on a specific compiler.
>
> > If you do need the providers array, ARRAY_SIZE() is preferred over a
> > terminator NULL.
>
> Okay.
>
> >> +static void check_provider_cells_property(struct check *c,
> >> + struct dt_info *dti,
> >> + struct node *node)
> >> +{
> >> + int i;
> >> +
> >> + for (i = 0; providers[i].prop_name; i++) {
> >> + struct property *prop = get_property(node, providers[i].prop_name);
> >> + if (!prop)
> >> + continue;
> >> + check_property_phandle_args(c, dti, node, prop, &providers[i]);
> >> + }
> >> +}
> >> +WARNING(provider_cells_property, check_provider_cells_property, NULL);
> >> +
> >> +static void check_gpio_cells_property(struct check *c,
> >> + struct dt_info *dti,
> >> + struct node *node)
> >> +{
> >> + struct property *prop;
> >> +
> >> + for_each_property(node, prop) {
> >> + char *str;
> >> + struct provider provider;
> >> +
> >> + /* Skip over false matches */
> >> + if (strstr(prop->name, "nr-gpio"))
> >> + continue;
> >> +
> >> + str = strrchr(prop->name, '-');
> >> + if (!str || !(streq(str, "-gpio") || streq(str, "-gpios")))
> >> + continue;
> >> +
> >> + provider.prop_name = prop->name;
> >> + provider.cell_name = "#gpio-cells";
> >> + provider.optional = false;
> >> + check_property_phandle_args(c, dti, node, prop, &provider);
> >> + }
> >> +
> >> +}
> >> +WARNING(gpio_cells_property, check_gpio_cells_property, NULL);
> >
> > Since the gpio stuff is a bit tweaker, it would be good to go into a
> > separate patch. Then the commit message can explain what the logic
> > here is for (I'm having a little trouble following it).
>
> Okay.
>
> Rob
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2017-08-19 7:33 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-14 21:48 [PATCH 1/2] checks: add phandle with arg property checks Rob Herring
[not found] ` <20170814214807.338-1-robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2017-08-14 21:48 ` [PATCH 2/2] checks: add interrupts property check Rob Herring
[not found] ` <20170814214807.338-2-robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2017-08-15 13:21 ` Rob Herring
2017-08-18 4:43 ` David Gibson
[not found] ` <20170818044303.GR5509-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2017-08-18 15:53 ` Rob Herring
[not found] ` <CAL_JsqJuUu-6FpLqQZZyVdCueV18CHRZ4qQUvacSrn2XAfpiSQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-08-19 7:42 ` David Gibson
2017-08-18 4:35 ` [PATCH 1/2] checks: add phandle with arg property checks David Gibson
[not found] ` <20170818043502.GQ5509-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2017-08-18 16:02 ` Rob Herring
[not found] ` <CAL_Jsq+yA2W=SD9zSkWxw-R16uNELeqPqJK3fVMvi0_jhEbooQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-08-19 7:33 ` David Gibson [this message]
[not found] ` <20170819073333.GA12356-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2017-08-22 14:38 ` Rob Herring
[not found] ` <CAL_JsqKynMDP2LBjPj2KSgJiVfmNM4e1=uHYUO6GcUjXt7oJbQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-08-23 0:19 ` David Gibson
2017-11-21 21:06 ` Rob Herring
[not found] ` <CAL_JsqLEwYN9eto2PRiWG7aEzBOeNeADP0miOS_jgs5cifmvOA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-11-21 22:58 ` 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=20170819073333.GA12356@umbus.fritz.box \
--to=david-xt8fgy+axnrb3ne2bgzf6laj5h9x9tb+@public.gmane.org \
--cc=devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@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 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.