[PATCH] regulator: implement basic reference counter

Eugen Hristev eugen.hristev at collabora.com
Mon Mar 27 17:42:35 CEST 2023


On 3/18/23 22:20, Simon Glass wrote:
> Hi Eugen,
> 
> On Thu, 16 Mar 2023 at 07:53, Eugen Hristev <eugen.hristev at collabora.com> wrote:
>>
>> Some devices share a regulator supply, when the first one will request
>> regulator disable, the second device will have it's supply cut off before
>> graciously shutting down. Hence there will be timeouts and other failed
>> operations.
>> Implement a reference counter mechanism similar with what is done in
>> Linux, to keep track of enable and disable requests, and only disable the
>> regulator when the last of the consumers has requested shutdown.
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev at collabora.com>
>> ---
>>   drivers/power/regulator/regulator_common.c | 22 ++++++++++++++++++++++
>>   drivers/power/regulator/regulator_common.h |  1 +
>>   2 files changed, 23 insertions(+)
> 
> This seems reasonable to me. I mostly worry about visibility, since it
> returns 0 in all cases so if you do actually want to shut it down, it
> silently ignored you in some situations. I've made some suggestions
> below.
> 
>>
>> diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c
>> index 93d8196b381e..edda25336176 100644
>> --- a/drivers/power/regulator/regulator_common.c
>> +++ b/drivers/power/regulator/regulator_common.c
>> @@ -73,6 +73,23 @@ int regulator_common_set_enable(const struct udevice *dev,
> 
> Please update the docs for this function in the header file.

Okay
> 
>>                  return 0;
>>          }
>>
>> +       /* If previously enabled, increase count */
>> +       if (enable && dev_pdata->enable_count > 0) {
>> +               dev_pdata->enable_count++;
>> +               return 0;
> 
> Should we return -EALREADY ?

I think not. It's not an error, we should just increase count, the 
caller should be told that there is no error happening.

> 
>> +       }
>> +
>> +       if (!enable) {
>> +               if (dev_pdata->enable_count > 1) {
>> +                       /* If enabled multiple times, decrease count */
>> +                       dev_pdata->enable_count--;
> 
> Return -EBUSY ?

Same goes here. The disable was successful, hence no error, but the 
regulator is not turned off , because someone else is still using it.

> 
>> +                       return 0;
>> +               } else if (!dev_pdata->enable_count) {
>> +                       /* If already disabled, do nothing */
> 
> Is this case an error? Should we return -EPERM ?

Maybe here we could return an error, saying that it's already disabled, 
but since it's a shared resource, this could tell the caller whether 
someone else is using the resource, and I don't think we should leak 
this information. It might be used in a way to find out information 
about the state of the system which might be a security problem ?
I think that a shared resource usage should be transparent to the caller 
, such that only the driver should manage it's power on/off and know who 
is using it.

Do you agree ?
> 
>> +                       return 0;
>> +               }
>> +       }
>> +
>>          ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
>>          if (ret) {
>>                  pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
>> @@ -87,5 +104,10 @@ int regulator_common_set_enable(const struct udevice *dev,
>>          if (!enable && dev_pdata->off_on_delay_us)
>>                  udelay(dev_pdata->off_on_delay_us);
>>
>> +       if (enable)
>> +               dev_pdata->enable_count++;
>> +       else
>> +               dev_pdata->enable_count--;
>> +
>>          return 0;
>>   }
>> diff --git a/drivers/power/regulator/regulator_common.h b/drivers/power/regulator/regulator_common.h
>> index c10492f01675..8167bc866261 100644
>> --- a/drivers/power/regulator/regulator_common.h
>> +++ b/drivers/power/regulator/regulator_common.h
>> @@ -13,6 +13,7 @@ struct regulator_common_plat {
>>          struct gpio_desc gpio; /* GPIO for regulator enable control */
>>          unsigned int startup_delay_us;
>>          unsigned int off_on_delay_us;
>> +       unsigned int enable_count;
>>   };
>>
>>   int regulator_common_of_to_plat(struct udevice *dev,
>> --
>> 2.34.1
>>
> 
> Also I would appreciate a patch to rename dev_pdata to plat if you have time.

I will have a look
> 
> Regards,
> Simon



More information about the U-Boot mailing list