Messages in this thread | | | Date | Tue, 14 Apr 2020 00:29:45 +0200 | From | Sebastian Reichel <> | Subject | Re: [PATCH v1] power_supply: Add a helper function to retrieve psy array from phandle |
| |
Hi,
On Tue, Apr 07, 2020 at 02:12:43PM -0700, Badhri Jagan Sridharan wrote: > power_supply_get_by_phandle retrieves power_supply object based on > phandle. However, when multiple power_supply objects are registered > by the same parent device the first power_supply object's reference > is returned. This varies according to probe order. Add a helper to > return all the power_supply object's reference. > > The caller has to provide the power_supply pointer array. > -EOVERFLOW is returned when the size of the array is not enough to > pass back all the power_supply objects. > > Signed-off-by: Badhri Jagan Sridharan <badhri@google.com> > ---
This patchset is incomplete, it is missing a mainline user.
-- Sebastian
> drivers/power/supply/power_supply_core.c | 78 ++++++++++++++++++++++++ > include/linux/power_supply.h | 9 +++ > 2 files changed, 87 insertions(+) > > diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c > index 1a9a9fae73d32..e7bab4661ba13 100644 > --- a/drivers/power/supply/power_supply_core.c > +++ b/drivers/power/supply/power_supply_core.c > @@ -32,6 +32,13 @@ EXPORT_SYMBOL_GPL(power_supply_notifier); > > static struct device_type power_supply_dev_type; > > +struct match_device_node_array_param { > + struct device_node *parent_of_node; > + struct power_supply **psy; > + ssize_t psy_size; > + ssize_t psy_count; > +}; > + > #define POWER_SUPPLY_DEFERRED_REGISTER_TIME msecs_to_jiffies(10) > > static bool __power_supply_is_supplied_by(struct power_supply *supplier, > @@ -522,6 +529,77 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np, > } > EXPORT_SYMBOL_GPL(power_supply_get_by_phandle); > > +static int power_supply_match_device_node_array(struct device *dev, > + void *data) > +{ > + struct match_device_node_array_param *param = > + (struct match_device_node_array_param *)data; > + struct power_supply **psy = param->psy; > + ssize_t size = param->psy_size; > + ssize_t *count = ¶m->psy_count; > + > + if (!dev->parent || dev->parent->of_node != param->parent_of_node) > + return 0; > + > + if (*count >= size) > + return -EOVERFLOW; > + > + psy[*count] = dev_get_drvdata(dev); > + atomic_inc(&psy[*count]->use_cnt); > + (*count)++; > + > + return 0; > +} > + > +/** > + * power_supply_get_by_phandle_array() - Similar to > + * power_supply_get_by_phandle but returns an array of power supply > + * objects which are associated with the phandle. > + * @np: Pointer to device node holding phandle property. > + * @property: Name of property holding a power supply name. > + * @psy: Array of power_supply pointers provided by the client which is > + * filled by power_supply_get_by_phandle_array. > + * @size: size of power_supply pointer array. > + * > + * If power supply was found, it increases reference count for the > + * internal power supply's device. The user should power_supply_put() > + * after usage. > + * > + * Return: On success returns the number of power supply objects filled > + * in the @psy array. > + * -EOVERFLOW when size of @psy array is not suffice. > + * -EINVAL when @psy is NULL or @size is 0. > + * -ENODEV when matching device_node is not found. > + */ > +int power_supply_get_by_phandle_array(struct device_node *np, > + const char *property, > + struct power_supply **psy, > + ssize_t size) > +{ > + struct device_node *power_supply_np; > + int ret; > + struct match_device_node_array_param param; > + > + if (psy == NULL || size == 0) > + return -EINVAL; > + > + power_supply_np = of_parse_phandle(np, property, 0); > + if (!power_supply_np) > + return -ENODEV; > + > + param.parent_of_node = power_supply_np; > + param.psy = psy; > + param.psy_size = size; > + param.psy_count = 0; > + ret = class_for_each_device(power_supply_class, NULL, ¶m, > + power_supply_match_device_node_array); > + > + of_node_put(power_supply_np); > + > + return param.psy_count; > +} > +EXPORT_SYMBOL_GPL(power_supply_get_by_phandle_array); > + > static void devm_power_supply_put(struct device *dev, void *res) > { > struct power_supply **psy = res; > diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h > index dcd5a71e6c677..8c1478a480674 100644 > --- a/include/linux/power_supply.h > +++ b/include/linux/power_supply.h > @@ -366,12 +366,21 @@ extern void power_supply_put(struct power_supply *psy); > #ifdef CONFIG_OF > extern struct power_supply *power_supply_get_by_phandle(struct device_node *np, > const char *property); > +extern int power_supply_get_by_phandle_array(struct device_node *np, > + const char *property, > + struct power_supply **psy, > + ssize_t size); > extern struct power_supply *devm_power_supply_get_by_phandle( > struct device *dev, const char *property); > #else /* !CONFIG_OF */ > static inline struct power_supply * > power_supply_get_by_phandle(struct device_node *np, const char *property) > { return NULL; } > +static int power_supply_get_by_phandle_array(struct device_node *np, > + const char *property, > + struct power_supply **psy, > + int size) > +{ return 0; } > static inline struct power_supply * > devm_power_supply_get_by_phandle(struct device *dev, const char *property) > { return NULL; } > -- > 2.26.0.292.g33ef6b2f38-goog > [unhandled content-type:application/pgp-signature] | |