mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
ANDROID: power_supply: Add a helper function to retrieve psy array from phandle
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 returned power_supply object's reference 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. Patch was sent to mainline linux, however, was deemed incomplete due to lack of mainline user. Link: https://lore.kernel.org/linux-pm/20200407211243.247362-1-badhri@google.com/T/ Bug: 161416774 Bug: 167486462 Signed-off-by: Badhri Jagan Sridharan <badhri@google.com> Change-Id: I6d9c52edb4472e73fc2d3c8eb32a41bec8bbde2a
This commit is contained in:
parent
2bd29a1007
commit
dea1a925f6
|
|
@ -32,6 +32,13 @@ EXPORT_SYMBOL_GPL(power_supply_notifier);
|
||||||
|
|
||||||
static struct device_type power_supply_dev_type;
|
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)
|
#define POWER_SUPPLY_DEFERRED_REGISTER_TIME msecs_to_jiffies(10)
|
||||||
|
|
||||||
static bool __power_supply_is_supplied_by(struct power_supply *supplier,
|
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);
|
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 || !size)
|
||||||
|
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)
|
static void devm_power_supply_put(struct device *dev, void *res)
|
||||||
{
|
{
|
||||||
struct power_supply **psy = res;
|
struct power_supply **psy = res;
|
||||||
|
|
|
||||||
|
|
@ -379,12 +379,21 @@ extern void power_supply_put(struct power_supply *psy);
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
extern struct power_supply *power_supply_get_by_phandle(struct device_node *np,
|
extern struct power_supply *power_supply_get_by_phandle(struct device_node *np,
|
||||||
const char *property);
|
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(
|
extern struct power_supply *devm_power_supply_get_by_phandle(
|
||||||
struct device *dev, const char *property);
|
struct device *dev, const char *property);
|
||||||
#else /* !CONFIG_OF */
|
#else /* !CONFIG_OF */
|
||||||
static inline struct power_supply *
|
static inline struct power_supply *
|
||||||
power_supply_get_by_phandle(struct device_node *np, const char *property)
|
power_supply_get_by_phandle(struct device_node *np, const char *property)
|
||||||
{ return NULL; }
|
{ 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 *
|
static inline struct power_supply *
|
||||||
devm_power_supply_get_by_phandle(struct device *dev, const char *property)
|
devm_power_supply_get_by_phandle(struct device *dev, const char *property)
|
||||||
{ return NULL; }
|
{ return NULL; }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user