On Mon, 11 Feb 2013 12:26:15 +0100, Andreas Larsson <[email protected]> wrote:
> On 2013-02-11 00:58, Grant Likely wrote:
> > diff --git a/drivers/of/base.c b/drivers/of/base.c
> > index 2390ddb..e1120a2 100644
> > --- a/drivers/of/base.c
> > +++ b/drivers/of/base.c
> > @@ -1025,12 +1025,13 @@ EXPORT_SYMBOL(of_parse_phandle);
> >    * To get a device_node of the `node2' node you may call this:
> >    * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
> >    */
> > -int of_parse_phandle_with_args(const struct device_node *np, const char 
> > *list_name,
> > -                           const char *cells_name, int index,
> > -                           struct of_phandle_args *out_args)
> > +static int __of_parse_phandle_with_args(const struct device_node *np,
> > +                                   const char *list_name,
> > +                                   const char *cells_name, int index,
> > +                                   struct of_phandle_args *out_args)
> >   {
> >     const __be32 *list, *list_end;
> > -   int size, cur_index = 0;
> > +   int rc = 0, size, cur_index = 0;
> >     uint32_t count = 0;
> >     struct device_node *node = NULL;
> >     phandle phandle;
> > @@ -1059,12 +1060,14 @@ int of_parse_phandle_with_args(const struct 
> > device_node *np, const char *list_na
> >                     if (!node) {
> >                             pr_err("%s: could not find phandle\n",
> >                                      np->full_name);
> > +                           rc = -EINVAL;
> >                             break;
> >                     }
> >                     if (of_property_read_u32(node, cells_name, &count)) {
> >                             pr_err("%s: could not get %s for %s\n",
> >                                      np->full_name, cells_name,
> >                                      node->full_name);
> > +                           rc = -EINVAL;
> >                             break;
> >                     }
> >
> > @@ -1075,6 +1078,7 @@ int of_parse_phandle_with_args(const struct 
> > device_node *np, const char *list_na
> >                     if (list + count > list_end) {
> >                             pr_err("%s: arguments longer than property\n",
> >                                      np->full_name);
> > +                           rc = -EINVAL;
> >                             break;
> >                     }
> >             }
> > @@ -1086,8 +1090,10 @@ int of_parse_phandle_with_args(const struct 
> > device_node *np, const char *list_na
> >              * or return -ENOENT for an empty entry.
> >              */
> >             if (cur_index == index) {
> > -                   if (!phandle)
> > -                           return -ENOENT;
> > +                   if (!phandle) {
> > +                           rc = -ENOENT;
> > +                           break;
> > +                   }
> >
> >                     if (out_args) {
> >                             int i;
> > @@ -1098,22 +1104,54 @@ int of_parse_phandle_with_args(const struct 
> > device_node *np, const char *list_na
> >                             for (i = 0; i < count; i++)
> >                                     out_args->args[i] = 
> > be32_to_cpup(list++);
> >                     }
> > -                   return 0;
> > +
> > +                   rc = 0;
> > +                   break;
> >             }
> >
> >             of_node_put(node);
> >             node = NULL;
> >             list += count;
> >             cur_index++;
> > +           rc = cur_index;
> >     }
> >
> >     /* Loop exited without finding a valid entry; return an error */
> >     if (node)
> >             of_node_put(node);
> > -   return -EINVAL;
> > +   return rc;
> > +}
> > +
> > +int of_parse_phandle_with_args(const struct device_node *np, const char 
> > *list_name,
> > +                           const char *cells_name, int index,
> > +                           struct of_phandle_args *out_args)
> > +{
> > +   return __of_parse_phandle_with_args(np, list_name, cells_name, index, 
> > out_args);
> >   }
> >   EXPORT_SYMBOL(of_parse_phandle_with_args);
> 
> Will this not result in a situation where a call to 
> of_parse_phandle_with_args with an out of bounds index returns the 
> number of tuples instead of an error code and possibly some caller that 
> uses the this count as a phandle instead of handling an error?

Yes, you are right about the out of bounds index. I had meant to write
the following in __of_parse_phandle_with_args:

        return (index < 0) ? rc : -ENOENT;

Which should solve that problem.

> 
> Of course of_count_phandle_with_args can be used to make sure that no 
> such call is made in the first place, but that is another story.

Not really, the __ function still has to test for a negative index.
However, it can at least make sure the index passed is not negative so
you can't get count behaviour when calling for a parse. How about:

int of_parse_phandle_with_args(const struct device_node *np, const char 
*list_name,
                                const char *cells_name, int index,
                                struct of_phandle_args *out_args)
{
        if (index < 0)
                return -EINVAL;
        return __of_parse_phandle_with_args(np, list_name, cells_name, index, 
out_args);
}


> 
> Related to this is that Case 7 in of_selftest_parse_phandle_with_args 
> never gets exercised as far as I can see.

You're right. Also a bug. Fixed now.

> 
> 
> > diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
> > index c454f57..bdbe0f3 100644
> > --- a/include/linux/of_gpio.h
> > +++ b/include/linux/of_gpio.h
> > @@ -50,8 +50,28 @@ static inline struct of_mm_gpio_chip 
> > *to_of_mm_gpio_chip(struct gpio_chip *gc)
> >   extern int of_get_named_gpio_flags(struct device_node *np,
> >             const char *list_name, int index, enum of_gpio_flags *flags);
> >
> > -extern unsigned int of_gpio_named_count(struct device_node *np,
> > -                                   const char* propname);
> > +/**
> > + * of_gpio_named_count - Count GPIOs for a device
> > + * @np:            device node to count GPIOs for
> > + * @propname:      property name containing gpio specifier(s)
> > + *
> > + * The function returns the count of GPIOs specified for a node.
> > + *
> > + * Note that the empty GPIO specifiers counts too. For example,
> > + *
> > + * gpios = <0
> > + *          &pio1 1 2
> > + *          0
> > + *          &pio2 3 4>;
> > + *
> > + * defines four GPIOs (so this function will return 4), two of which
> > + * are not specified. Returns -EINVAL for an incorrectly formed gpios
> > + * property.
> > + */
> > +static int of_gpio_named_count(struct device_node *np, const char* 
> > propname)
> > +{
> > +   return of_count_phandle_with_args(np, propname, "#gpio-cells");
> > +}
> 
> Should this be static inline int?

Yes.

> 
> I think it would be good to also document that it also returns -ENOENT 
> when the propname property is missing, which might be an important case 
> to distinguish from the -EINVAL case.

Done. I'll post a new version shortly.

g.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to