2020-04-29 12:32:13

by Fabrice Gasnier

[permalink] [raw]
Subject: [PATCH v2] iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling

When the ADC is runtime suspended and starting a conversion, the stm32-adc
driver calls pm_runtime_get_sync() that gets cascaded to the parent
(e.g. runtime resume of stm32-adc-core driver). This also kicks the
autosuspend delay (e.g. 2s) of the parent.
Once the ADC is active, calling pm_runtime_get_sync() again (upon a new
capture) won't kick the autosuspend delay for the parent (stm32-adc-core
driver) as already active.

Currently, this makes the stm32-adc-core driver go in suspend state
every 2s when doing slow polling. As an example, doing a capture, e.g.
cat in_voltageY_raw at a 0.2s rate, the auto suspend delay for the parent
isn't refreshed. Once it expires, the parent immediately falls into
runtime suspended state, in between two captures, as soon as the child
driver falls into runtime suspend state:
- e.g. after 2s, + child calls pm_runtime_put_autosuspend() + 100ms
autosuspend delay of the child.
- stm32-adc-core switches off regulators, clocks and so on.
- They get switched on back again 100ms later in this example (at 2.2s).

So, use runtime_idle() callback in stm32-adc-core driver to call
pm_runtime_mark_last_busy() for the parent driver (stm32-adc-core),
to avoid this.

Fixes: 9bdbb1139ca1 ("iio: adc: stm32-adc: add power management support")

Signed-off-by: Fabrice Gasnier <[email protected]>
---
Changes in v2:
- Use runtime_idle callback in stm32-adc-core driver, instead of refreshing
last_busy from the child (for the parent) at many place. Initial patch v1
looked like "somewhat adhoc solution" as commented by Jonathan.
---
drivers/iio/adc/stm32-adc-core.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 2df88d2..ebe5dbc 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -803,6 +803,13 @@ static int stm32_adc_core_runtime_resume(struct device *dev)
{
return stm32_adc_core_hw_start(dev);
}
+
+static int stm32_adc_core_runtime_idle(struct device *dev)
+{
+ pm_runtime_mark_last_busy(dev);
+
+ return 0;
+}
#endif

static const struct dev_pm_ops stm32_adc_core_pm_ops = {
@@ -810,7 +817,7 @@ static const struct dev_pm_ops stm32_adc_core_pm_ops = {
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend,
stm32_adc_core_runtime_resume,
- NULL)
+ stm32_adc_core_runtime_idle)
};

static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
--
2.7.4


2020-05-03 11:50:03

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v2] iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling

On Wed, 29 Apr 2020 14:29:08 +0200
Fabrice Gasnier <[email protected]> wrote:

> When the ADC is runtime suspended and starting a conversion, the stm32-adc
> driver calls pm_runtime_get_sync() that gets cascaded to the parent
> (e.g. runtime resume of stm32-adc-core driver). This also kicks the
> autosuspend delay (e.g. 2s) of the parent.
> Once the ADC is active, calling pm_runtime_get_sync() again (upon a new
> capture) won't kick the autosuspend delay for the parent (stm32-adc-core
> driver) as already active.
>
> Currently, this makes the stm32-adc-core driver go in suspend state
> every 2s when doing slow polling. As an example, doing a capture, e.g.
> cat in_voltageY_raw at a 0.2s rate, the auto suspend delay for the parent
> isn't refreshed. Once it expires, the parent immediately falls into
> runtime suspended state, in between two captures, as soon as the child
> driver falls into runtime suspend state:
> - e.g. after 2s, + child calls pm_runtime_put_autosuspend() + 100ms
> autosuspend delay of the child.
> - stm32-adc-core switches off regulators, clocks and so on.
> - They get switched on back again 100ms later in this example (at 2.2s).
>
> So, use runtime_idle() callback in stm32-adc-core driver to call
> pm_runtime_mark_last_busy() for the parent driver (stm32-adc-core),
> to avoid this.
>
> Fixes: 9bdbb1139ca1 ("iio: adc: stm32-adc: add power management support")
>
> Signed-off-by: Fabrice Gasnier <[email protected]>

Whilst this seems 'sensible' to me, I really don't have a good enough grasp
of runtime pm to be sure.

I see something similar looking in the greybus driver, but not sure on the
reason it is there.

Hence, ideally looking for an ack from Rafael on this one!

Thanks,

Jonathan

> ---
> Changes in v2:
> - Use runtime_idle callback in stm32-adc-core driver, instead of refreshing
> last_busy from the child (for the parent) at many place. Initial patch v1
> looked like "somewhat adhoc solution" as commented by Jonathan.
> ---
> drivers/iio/adc/stm32-adc-core.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
> index 2df88d2..ebe5dbc 100644
> --- a/drivers/iio/adc/stm32-adc-core.c
> +++ b/drivers/iio/adc/stm32-adc-core.c
> @@ -803,6 +803,13 @@ static int stm32_adc_core_runtime_resume(struct device *dev)
> {
> return stm32_adc_core_hw_start(dev);
> }
> +
> +static int stm32_adc_core_runtime_idle(struct device *dev)
> +{
> + pm_runtime_mark_last_busy(dev);
> +
> + return 0;
> +}
> #endif
>
> static const struct dev_pm_ops stm32_adc_core_pm_ops = {
> @@ -810,7 +817,7 @@ static const struct dev_pm_ops stm32_adc_core_pm_ops = {
> pm_runtime_force_resume)
> SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend,
> stm32_adc_core_runtime_resume,
> - NULL)
> + stm32_adc_core_runtime_idle)
> };
>
> static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {

2020-06-11 10:14:11

by Fabrice Gasnier

[permalink] [raw]
Subject: Re: [PATCH v2] iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling

On 5/3/20 1:48 PM, Jonathan Cameron wrote:
> On Wed, 29 Apr 2020 14:29:08 +0200
> Fabrice Gasnier <[email protected]> wrote:
>
>> When the ADC is runtime suspended and starting a conversion, the stm32-adc
>> driver calls pm_runtime_get_sync() that gets cascaded to the parent
>> (e.g. runtime resume of stm32-adc-core driver). This also kicks the
>> autosuspend delay (e.g. 2s) of the parent.
>> Once the ADC is active, calling pm_runtime_get_sync() again (upon a new
>> capture) won't kick the autosuspend delay for the parent (stm32-adc-core
>> driver) as already active.
>>
>> Currently, this makes the stm32-adc-core driver go in suspend state
>> every 2s when doing slow polling. As an example, doing a capture, e.g.
>> cat in_voltageY_raw at a 0.2s rate, the auto suspend delay for the parent
>> isn't refreshed. Once it expires, the parent immediately falls into
>> runtime suspended state, in between two captures, as soon as the child
>> driver falls into runtime suspend state:
>> - e.g. after 2s, + child calls pm_runtime_put_autosuspend() + 100ms
>> autosuspend delay of the child.
>> - stm32-adc-core switches off regulators, clocks and so on.
>> - They get switched on back again 100ms later in this example (at 2.2s).
>>
>> So, use runtime_idle() callback in stm32-adc-core driver to call
>> pm_runtime_mark_last_busy() for the parent driver (stm32-adc-core),
>> to avoid this.
>>
>> Fixes: 9bdbb1139ca1 ("iio: adc: stm32-adc: add power management support")
>>
>> Signed-off-by: Fabrice Gasnier <[email protected]>
>
> Whilst this seems 'sensible' to me, I really don't have a good enough grasp
> of runtime pm to be sure.
>
> I see something similar looking in the greybus driver, but not sure on the
> reason it is there.
>
> Hence, ideally looking for an ack from Rafael on this one!

Hi,

Gentle reminder, I'm not sure how to progress on this patch.

Rafael, or maybe Ulf, could take a look at it ?

Thanks in advance,
Best Regards,
Fabrice

>
> Thanks,
>
> Jonathan
>
>> ---
>> Changes in v2:
>> - Use runtime_idle callback in stm32-adc-core driver, instead of refreshing
>> last_busy from the child (for the parent) at many place. Initial patch v1
>> looked like "somewhat adhoc solution" as commented by Jonathan.
>> ---
>> drivers/iio/adc/stm32-adc-core.c | 9 ++++++++-
>> 1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
>> index 2df88d2..ebe5dbc 100644
>> --- a/drivers/iio/adc/stm32-adc-core.c
>> +++ b/drivers/iio/adc/stm32-adc-core.c
>> @@ -803,6 +803,13 @@ static int stm32_adc_core_runtime_resume(struct device *dev)
>> {
>> return stm32_adc_core_hw_start(dev);
>> }
>> +
>> +static int stm32_adc_core_runtime_idle(struct device *dev)
>> +{
>> + pm_runtime_mark_last_busy(dev);
>> +
>> + return 0;
>> +}
>> #endif
>>
>> static const struct dev_pm_ops stm32_adc_core_pm_ops = {
>> @@ -810,7 +817,7 @@ static const struct dev_pm_ops stm32_adc_core_pm_ops = {
>> pm_runtime_force_resume)
>> SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend,
>> stm32_adc_core_runtime_resume,
>> - NULL)
>> + stm32_adc_core_runtime_idle)
>> };
>>
>> static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
>