diff mbox series

[v2] ALSA: hda/tegra: enable clock during probe

Message ID 1548414418-5785-1-git-send-email-spujar@nvidia.com
State Rejected
Headers show
Series [v2] ALSA: hda/tegra: enable clock during probe | expand

Commit Message

Sameer Pujar Jan. 25, 2019, 11:06 a.m. UTC
If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
will not be ON. This could cause issue during probe, where hda init
setup is done. This patch enables clocks unconditionally during probe.

Along with above, follwoing changes are done.
  * enable runtime PM before exiting from probe work. This helps to avoid
    usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
  * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
  * runtime PM callbacks moved out of CONFIG_PM check

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
---
 sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

Comments

Jon Hunter Jan. 25, 2019, 11:42 a.m. UTC | #1
On 25/01/2019 11:06, Sameer Pujar wrote:
> If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
> will not be ON. This could cause issue during probe, where hda init
> setup is done. This patch enables clocks unconditionally during probe.
> 
> Along with above, follwoing changes are done.
>   * enable runtime PM before exiting from probe work. This helps to avoid
>     usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
>   * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
>   * runtime PM callbacks moved out of CONFIG_PM check
> 
> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
> Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>  sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
>  1 file changed, 17 insertions(+), 9 deletions(-)
> 
> diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
> index c8d18dc..ba6175f 100644
> --- a/sound/pci/hda/hda_tegra.c
> +++ b/sound/pci/hda/hda_tegra.c
> @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct hda_tegra *data)
>  	return rc;
>  }
>  
> -#ifdef CONFIG_PM_SLEEP
>  static void hda_tegra_disable_clocks(struct hda_tegra *data)
>  {
>  	clk_disable_unprepare(data->hda2hdmi_clk);
> @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
>  	clk_disable_unprepare(data->hda_clk);
>  }
>  
> +#ifdef CONFIG_PM_SLEEP
>  /*
>   * power management
>   */
> @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
>  }
>  #endif /* CONFIG_PM_SLEEP */
>  
> -#ifdef CONFIG_PM
>  static int hda_tegra_runtime_suspend(struct device *dev)
>  {
>  	struct snd_card *card = dev_get_drvdata(dev);
> @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device *dev)
>  	int rc;
>  
>  	rc = hda_tegra_enable_clocks(hda);
> -	if (rc != 0)
> +	if (rc)
>  		return rc;
>  	if (chip && chip->running) {
>  		hda_tegra_init(hda);
> @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device *dev)
>  
>  	return 0;
>  }
> -#endif /* CONFIG_PM */
>  
>  static const struct dev_pm_ops hda_tegra_pm = {
>  	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
> @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
>  
>  	dev_set_drvdata(&pdev->dev, card);
>  
> -	pm_runtime_enable(hda->dev);
> -	if (!azx_has_pm_runtime(chip))
> -		pm_runtime_forbid(hda->dev);
> +	err = hda_tegra_enable_clocks(hda);
> +	if (err)
> +		goto out_free;
>  
>  	schedule_work(&hda->probe_work);
>  
> @@ -571,7 +569,6 @@ static void hda_tegra_probe_work(struct work_struct *work)
>  	struct platform_device *pdev = to_platform_device(hda->dev);
>  	int err;
>  
> -	pm_runtime_get_sync(hda->dev);
>  	err = hda_tegra_first_init(chip, pdev);
>  	if (err < 0)
>  		goto out_free;
> @@ -592,8 +589,15 @@ static void hda_tegra_probe_work(struct work_struct *work)
>  	chip->running = 1;
>  	snd_hda_set_power_save(&chip->bus, power_save * 1000);
>  
> +	/* set device state as active */
> +	if (pm_runtime_set_active(hda->dev) < 0)
> +		goto out_free;
> +	/* enable runtime PM */
> +	pm_runtime_enable(hda->dev);
> +	if (!azx_has_pm_runtime(chip))
> +		pm_runtime_forbid(hda->dev);
> +
>   out_free:
> -	pm_runtime_put(hda->dev);
>  	return; /* no error return from async probe */
>  }
>  
> @@ -603,6 +607,10 @@ static int hda_tegra_remove(struct platform_device *pdev)
>  
>  	ret = snd_card_free(dev_get_drvdata(&pdev->dev));
>  	pm_runtime_disable(&pdev->dev);
> +	if (!pm_runtime_status_suspended(&pdev->dev)) {
> +		hda_tegra_runtime_suspend(&pdev->dev);
> +		pm_runtime_set_suspended(&pdev->dev);
> +	}

I think that we need to be consistent in the above with what is done in
the probe. If in the probe we call hda_tegra_enable_clocks(), then here
we should call hda_tegra_disable_clocks(). However, my preference is
still to all hda_tegra_runtime_resume() in probe and then leave the
above as-is. Let's see what everyone else thinks.

Cheers
Jon
Sameer Pujar Jan. 25, 2019, 12:19 p.m. UTC | #2
On 1/25/2019 5:12 PM, Jon Hunter wrote:
> On 25/01/2019 11:06, Sameer Pujar wrote:
>> If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
>> will not be ON. This could cause issue during probe, where hda init
>> setup is done. This patch enables clocks unconditionally during probe.
>>
>> Along with above, follwoing changes are done.
>>    * enable runtime PM before exiting from probe work. This helps to avoid
>>      usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
>>    * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
>>    * runtime PM callbacks moved out of CONFIG_PM check
>>
>> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
>> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
>> Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
>> ---
>>   sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
>>   1 file changed, 17 insertions(+), 9 deletions(-)
>>
>> diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
>> index c8d18dc..ba6175f 100644
>> --- a/sound/pci/hda/hda_tegra.c
>> +++ b/sound/pci/hda/hda_tegra.c
>> @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct hda_tegra *data)
>>   	return rc;
>>   }
>>   
>> -#ifdef CONFIG_PM_SLEEP
>>   static void hda_tegra_disable_clocks(struct hda_tegra *data)
>>   {
>>   	clk_disable_unprepare(data->hda2hdmi_clk);
>> @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
>>   	clk_disable_unprepare(data->hda_clk);
>>   }
>>   
>> +#ifdef CONFIG_PM_SLEEP
>>   /*
>>    * power management
>>    */
>> @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
>>   }
>>   #endif /* CONFIG_PM_SLEEP */
>>   
>> -#ifdef CONFIG_PM
>>   static int hda_tegra_runtime_suspend(struct device *dev)
>>   {
>>   	struct snd_card *card = dev_get_drvdata(dev);
>> @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device *dev)
>>   	int rc;
>>   
>>   	rc = hda_tegra_enable_clocks(hda);
>> -	if (rc != 0)
>> +	if (rc)
>>   		return rc;
>>   	if (chip && chip->running) {
>>   		hda_tegra_init(hda);
>> @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device *dev)
>>   
>>   	return 0;
>>   }
>> -#endif /* CONFIG_PM */
>>   
>>   static const struct dev_pm_ops hda_tegra_pm = {
>>   	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
>> @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
>>   
>>   	dev_set_drvdata(&pdev->dev, card);
>>   
>> -	pm_runtime_enable(hda->dev);
>> -	if (!azx_has_pm_runtime(chip))
>> -		pm_runtime_forbid(hda->dev);
>> +	err = hda_tegra_enable_clocks(hda);
>> +	if (err)
>> +		goto out_free;
>>   
>>   	schedule_work(&hda->probe_work);
>>   
>> @@ -571,7 +569,6 @@ static void hda_tegra_probe_work(struct work_struct *work)
>>   	struct platform_device *pdev = to_platform_device(hda->dev);
>>   	int err;
>>   
>> -	pm_runtime_get_sync(hda->dev);
>>   	err = hda_tegra_first_init(chip, pdev);
>>   	if (err < 0)
>>   		goto out_free;
>> @@ -592,8 +589,15 @@ static void hda_tegra_probe_work(struct work_struct *work)
>>   	chip->running = 1;
>>   	snd_hda_set_power_save(&chip->bus, power_save * 1000);
>>   
>> +	/* set device state as active */
>> +	if (pm_runtime_set_active(hda->dev) < 0)
>> +		goto out_free;
>> +	/* enable runtime PM */
>> +	pm_runtime_enable(hda->dev);
>> +	if (!azx_has_pm_runtime(chip))
>> +		pm_runtime_forbid(hda->dev);
>> +
>>    out_free:
>> -	pm_runtime_put(hda->dev);
>>   	return; /* no error return from async probe */
>>   }
>>   
>> @@ -603,6 +607,10 @@ static int hda_tegra_remove(struct platform_device *pdev)
>>   
>>   	ret = snd_card_free(dev_get_drvdata(&pdev->dev));
>>   	pm_runtime_disable(&pdev->dev);
>> +	if (!pm_runtime_status_suspended(&pdev->dev)) {
>> +		hda_tegra_runtime_suspend(&pdev->dev);
>> +		pm_runtime_set_suspended(&pdev->dev);
>> +	}
> I think that we need to be consistent in the above with what is done in
> the probe. If in the probe we call hda_tegra_enable_clocks(), then here
> we should call hda_tegra_disable_clocks(). However, my preference is
> still to all hda_tegra_runtime_resume() in probe and then leave the
> above as-is. Let's see what everyone else thinks.
Though it is good to have the handling at a single place, it is slightly 
confusing to call
runtime_resume() in probe. When runtime PM is not yet enabled, why call 
something that is related
to it(not logically but intuitively)!

What we can possibly follow is,
1. Till probe() completes, handle things explicitly.
2. Before returning from successful probe, handle control to runtime PM.

Nevertheless, shall go with the majority of the opinion.

Thanks,
Sameer.

> Cheers
> Jon
>
Jon Hunter Jan. 25, 2019, 1:15 p.m. UTC | #3
On 25/01/2019 12:19, Sameer Pujar wrote:
> 
> On 1/25/2019 5:12 PM, Jon Hunter wrote:
>> On 25/01/2019 11:06, Sameer Pujar wrote:
>>> If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
>>> will not be ON. This could cause issue during probe, where hda init
>>> setup is done. This patch enables clocks unconditionally during probe.
>>>
>>> Along with above, follwoing changes are done.
>>>    * enable runtime PM before exiting from probe work. This helps to
>>> avoid
>>>      usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
>>>    * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
>>>    * runtime PM callbacks moved out of CONFIG_PM check
>>>
>>> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
>>> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
>>> Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
>>> ---
>>>   sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
>>>   1 file changed, 17 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
>>> index c8d18dc..ba6175f 100644
>>> --- a/sound/pci/hda/hda_tegra.c
>>> +++ b/sound/pci/hda/hda_tegra.c
>>> @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct
>>> hda_tegra *data)
>>>       return rc;
>>>   }
>>>   -#ifdef CONFIG_PM_SLEEP
>>>   static void hda_tegra_disable_clocks(struct hda_tegra *data)
>>>   {
>>>       clk_disable_unprepare(data->hda2hdmi_clk);
>>> @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct
>>> hda_tegra *data)
>>>       clk_disable_unprepare(data->hda_clk);
>>>   }
>>>   +#ifdef CONFIG_PM_SLEEP
>>>   /*
>>>    * power management
>>>    */
>>> @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
>>>   }
>>>   #endif /* CONFIG_PM_SLEEP */
>>>   -#ifdef CONFIG_PM
>>>   static int hda_tegra_runtime_suspend(struct device *dev)
>>>   {
>>>       struct snd_card *card = dev_get_drvdata(dev);
>>> @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device
>>> *dev)
>>>       int rc;
>>>         rc = hda_tegra_enable_clocks(hda);
>>> -    if (rc != 0)
>>> +    if (rc)
>>>           return rc;
>>>       if (chip && chip->running) {
>>>           hda_tegra_init(hda);
>>> @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device
>>> *dev)
>>>         return 0;
>>>   }
>>> -#endif /* CONFIG_PM */
>>>     static const struct dev_pm_ops hda_tegra_pm = {
>>>       SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
>>> @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device
>>> *pdev)
>>>         dev_set_drvdata(&pdev->dev, card);
>>>   -    pm_runtime_enable(hda->dev);
>>> -    if (!azx_has_pm_runtime(chip))
>>> -        pm_runtime_forbid(hda->dev);
>>> +    err = hda_tegra_enable_clocks(hda);
>>> +    if (err)
>>> +        goto out_free;
>>>         schedule_work(&hda->probe_work);
>>>   @@ -571,7 +569,6 @@ static void hda_tegra_probe_work(struct
>>> work_struct *work)
>>>       struct platform_device *pdev = to_platform_device(hda->dev);
>>>       int err;
>>>   -    pm_runtime_get_sync(hda->dev);
>>>       err = hda_tegra_first_init(chip, pdev);
>>>       if (err < 0)
>>>           goto out_free;
>>> @@ -592,8 +589,15 @@ static void hda_tegra_probe_work(struct
>>> work_struct *work)
>>>       chip->running = 1;
>>>       snd_hda_set_power_save(&chip->bus, power_save * 1000);
>>>   +    /* set device state as active */
>>> +    if (pm_runtime_set_active(hda->dev) < 0)
>>> +        goto out_free;
>>> +    /* enable runtime PM */
>>> +    pm_runtime_enable(hda->dev);
>>> +    if (!azx_has_pm_runtime(chip))
>>> +        pm_runtime_forbid(hda->dev);
>>> +
>>>    out_free:
>>> -    pm_runtime_put(hda->dev);
>>>       return; /* no error return from async probe */
>>>   }
>>>   @@ -603,6 +607,10 @@ static int hda_tegra_remove(struct
>>> platform_device *pdev)
>>>         ret = snd_card_free(dev_get_drvdata(&pdev->dev));
>>>       pm_runtime_disable(&pdev->dev);
>>> +    if (!pm_runtime_status_suspended(&pdev->dev)) {
>>> +        hda_tegra_runtime_suspend(&pdev->dev);
>>> +        pm_runtime_set_suspended(&pdev->dev);
>>> +    }
>> I think that we need to be consistent in the above with what is done in
>> the probe. If in the probe we call hda_tegra_enable_clocks(), then here
>> we should call hda_tegra_disable_clocks(). However, my preference is
>> still to all hda_tegra_runtime_resume() in probe and then leave the
>> above as-is. Let's see what everyone else thinks.
> Though it is good to have the handling at a single place, it is slightly
> confusing to call
> runtime_resume() in probe. When runtime PM is not yet enabled, why call
> something that is related
> to it(not logically but intuitively)!

I still don't think that it is confusing, the name of the function is
called hda_tegra_runtime_resume and does what is says on the tin (ie.
resumes the device at runtime).

Furthermore, I think it is completely logical that if pm-runtime is not
enabled, we manually call it. The benefit is that we have single
function for resuming the device for all circumstances.

Cheers
Jon
Jon Hunter Jan. 30, 2019, 12:45 p.m. UTC | #4
On 25/01/2019 11:06, Sameer Pujar wrote:
> If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
> will not be ON. This could cause issue during probe, where hda init
> setup is done. This patch enables clocks unconditionally during probe.
> 
> Along with above, follwoing changes are done.
>   * enable runtime PM before exiting from probe work. This helps to avoid
>     usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
>   * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
>   * runtime PM callbacks moved out of CONFIG_PM check
> 
> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
> Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>  sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
>  1 file changed, 17 insertions(+), 9 deletions(-)
> 
> diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
> index c8d18dc..ba6175f 100644
> --- a/sound/pci/hda/hda_tegra.c
> +++ b/sound/pci/hda/hda_tegra.c
> @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct hda_tegra *data)
>  	return rc;
>  }
>  
> -#ifdef CONFIG_PM_SLEEP
>  static void hda_tegra_disable_clocks(struct hda_tegra *data)
>  {
>  	clk_disable_unprepare(data->hda2hdmi_clk);
> @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
>  	clk_disable_unprepare(data->hda_clk);
>  }
>  
> +#ifdef CONFIG_PM_SLEEP
>  /*
>   * power management
>   */
> @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
>  }
>  #endif /* CONFIG_PM_SLEEP */
>  
> -#ifdef CONFIG_PM
>  static int hda_tegra_runtime_suspend(struct device *dev)
>  {
>  	struct snd_card *card = dev_get_drvdata(dev);
> @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device *dev)
>  	int rc;
>  
>  	rc = hda_tegra_enable_clocks(hda);
> -	if (rc != 0)
> +	if (rc)
>  		return rc;
>  	if (chip && chip->running) {
>  		hda_tegra_init(hda);
> @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device *dev)
>  
>  	return 0;
>  }
> -#endif /* CONFIG_PM */
>  
>  static const struct dev_pm_ops hda_tegra_pm = {
>  	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
> @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
>  
>  	dev_set_drvdata(&pdev->dev, card);
>  
> -	pm_runtime_enable(hda->dev);
> -	if (!azx_has_pm_runtime(chip))
> -		pm_runtime_forbid(hda->dev);
> +	err = hda_tegra_enable_clocks(hda);
> +	if (err)
> +		goto out_free;

We also need to think about power-domains here. Enabling the clocks
might not be enough as the appropriate power-domain needs to be enabled.
For 64-bit Tegra runtime-pm will handle the power-domains (assuming they
are populated in device-tree). So I still think it is better we call
pm_runtime_get_sync() at some point rather than just replying on
enabling the clocks.

Cheers
Jon
Takashi Iwai Jan. 30, 2019, 4:40 p.m. UTC | #5
On Wed, 30 Jan 2019 13:45:49 +0100,
Jon Hunter wrote:
> 
> 
> On 25/01/2019 11:06, Sameer Pujar wrote:
> > If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
> > will not be ON. This could cause issue during probe, where hda init
> > setup is done. This patch enables clocks unconditionally during probe.
> > 
> > Along with above, follwoing changes are done.
> >   * enable runtime PM before exiting from probe work. This helps to avoid
> >     usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
> >   * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
> >   * runtime PM callbacks moved out of CONFIG_PM check
> > 
> > Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> > Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
> > Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
> > ---
> >  sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
> >  1 file changed, 17 insertions(+), 9 deletions(-)
> > 
> > diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
> > index c8d18dc..ba6175f 100644
> > --- a/sound/pci/hda/hda_tegra.c
> > +++ b/sound/pci/hda/hda_tegra.c
> > @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct hda_tegra *data)
> >  	return rc;
> >  }
> >  
> > -#ifdef CONFIG_PM_SLEEP
> >  static void hda_tegra_disable_clocks(struct hda_tegra *data)
> >  {
> >  	clk_disable_unprepare(data->hda2hdmi_clk);
> > @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
> >  	clk_disable_unprepare(data->hda_clk);
> >  }
> >  
> > +#ifdef CONFIG_PM_SLEEP
> >  /*
> >   * power management
> >   */
> > @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
> >  }
> >  #endif /* CONFIG_PM_SLEEP */
> >  
> > -#ifdef CONFIG_PM
> >  static int hda_tegra_runtime_suspend(struct device *dev)
> >  {
> >  	struct snd_card *card = dev_get_drvdata(dev);
> > @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device *dev)
> >  	int rc;
> >  
> >  	rc = hda_tegra_enable_clocks(hda);
> > -	if (rc != 0)
> > +	if (rc)
> >  		return rc;
> >  	if (chip && chip->running) {
> >  		hda_tegra_init(hda);
> > @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device *dev)
> >  
> >  	return 0;
> >  }
> > -#endif /* CONFIG_PM */
> >  
> >  static const struct dev_pm_ops hda_tegra_pm = {
> >  	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
> > @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
> >  
> >  	dev_set_drvdata(&pdev->dev, card);
> >  
> > -	pm_runtime_enable(hda->dev);
> > -	if (!azx_has_pm_runtime(chip))
> > -		pm_runtime_forbid(hda->dev);
> > +	err = hda_tegra_enable_clocks(hda);
> > +	if (err)
> > +		goto out_free;
> 
> We also need to think about power-domains here. Enabling the clocks
> might not be enough as the appropriate power-domain needs to be enabled.
> For 64-bit Tegra runtime-pm will handle the power-domains (assuming they
> are populated in device-tree). So I still think it is better we call
> pm_runtime_get_sync() at some point rather than just replying on
> enabling the clocks.

If I understand correctly the code, the pm domain is already activated
at calling driver's probe callback.


thanks,

Takashi
Sameer Pujar Jan. 31, 2019, 9:36 a.m. UTC | #6
On 1/30/2019 10:10 PM, Takashi Iwai wrote:
> On Wed, 30 Jan 2019 13:45:49 +0100,
> Jon Hunter wrote:
>>
>> On 25/01/2019 11:06, Sameer Pujar wrote:
>>> If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
>>> will not be ON. This could cause issue during probe, where hda init
>>> setup is done. This patch enables clocks unconditionally during probe.
>>>
>>> Along with above, follwoing changes are done.
>>>    * enable runtime PM before exiting from probe work. This helps to avoid
>>>      usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
>>>    * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
>>>    * runtime PM callbacks moved out of CONFIG_PM check
>>>
>>> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
>>> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
>>> Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
>>> ---
>>>   sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
>>>   1 file changed, 17 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
>>> index c8d18dc..ba6175f 100644
>>> --- a/sound/pci/hda/hda_tegra.c
>>> +++ b/sound/pci/hda/hda_tegra.c
>>> @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct hda_tegra *data)
>>>   	return rc;
>>>   }
>>>   
>>> -#ifdef CONFIG_PM_SLEEP
>>>   static void hda_tegra_disable_clocks(struct hda_tegra *data)
>>>   {
>>>   	clk_disable_unprepare(data->hda2hdmi_clk);
>>> @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
>>>   	clk_disable_unprepare(data->hda_clk);
>>>   }
>>>   
>>> +#ifdef CONFIG_PM_SLEEP
>>>   /*
>>>    * power management
>>>    */
>>> @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
>>>   }
>>>   #endif /* CONFIG_PM_SLEEP */
>>>   
>>> -#ifdef CONFIG_PM
>>>   static int hda_tegra_runtime_suspend(struct device *dev)
>>>   {
>>>   	struct snd_card *card = dev_get_drvdata(dev);
>>> @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device *dev)
>>>   	int rc;
>>>   
>>>   	rc = hda_tegra_enable_clocks(hda);
>>> -	if (rc != 0)
>>> +	if (rc)
>>>   		return rc;
>>>   	if (chip && chip->running) {
>>>   		hda_tegra_init(hda);
>>> @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device *dev)
>>>   
>>>   	return 0;
>>>   }
>>> -#endif /* CONFIG_PM */
>>>   
>>>   static const struct dev_pm_ops hda_tegra_pm = {
>>>   	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
>>> @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
>>>   
>>>   	dev_set_drvdata(&pdev->dev, card);
>>>   
>>> -	pm_runtime_enable(hda->dev);
>>> -	if (!azx_has_pm_runtime(chip))
>>> -		pm_runtime_forbid(hda->dev);
>>> +	err = hda_tegra_enable_clocks(hda);
>>> +	if (err)
>>> +		goto out_free;
>> We also need to think about power-domains here. Enabling the clocks
>> might not be enough as the appropriate power-domain needs to be enabled.
>> For 64-bit Tegra runtime-pm will handle the power-domains (assuming they
>> are populated in device-tree). So I still think it is better we call
>> pm_runtime_get_sync() at some point rather than just replying on
>> enabling the clocks.
> If I understand correctly the code, the pm domain is already activated
> at calling driver's probe callback.

If there are no further concerns, can we consider this for approval?

Thanks,
Sameer.

>
> thanks,
>
> Takashi
Thierry Reding Jan. 31, 2019, 11:05 a.m. UTC | #7
On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> On Wed, 30 Jan 2019 13:45:49 +0100,
> Jon Hunter wrote:
> > 
> > 
> > On 25/01/2019 11:06, Sameer Pujar wrote:
> > > If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
> > > will not be ON. This could cause issue during probe, where hda init
> > > setup is done. This patch enables clocks unconditionally during probe.
> > > 
> > > Along with above, follwoing changes are done.
> > >   * enable runtime PM before exiting from probe work. This helps to avoid
> > >     usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
> > >   * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
> > >   * runtime PM callbacks moved out of CONFIG_PM check
> > > 
> > > Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> > > Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
> > > Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
> > > ---
> > >  sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
> > >  1 file changed, 17 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
> > > index c8d18dc..ba6175f 100644
> > > --- a/sound/pci/hda/hda_tegra.c
> > > +++ b/sound/pci/hda/hda_tegra.c
> > > @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct hda_tegra *data)
> > >  	return rc;
> > >  }
> > >  
> > > -#ifdef CONFIG_PM_SLEEP
> > >  static void hda_tegra_disable_clocks(struct hda_tegra *data)
> > >  {
> > >  	clk_disable_unprepare(data->hda2hdmi_clk);
> > > @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
> > >  	clk_disable_unprepare(data->hda_clk);
> > >  }
> > >  
> > > +#ifdef CONFIG_PM_SLEEP
> > >  /*
> > >   * power management
> > >   */
> > > @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
> > >  }
> > >  #endif /* CONFIG_PM_SLEEP */
> > >  
> > > -#ifdef CONFIG_PM
> > >  static int hda_tegra_runtime_suspend(struct device *dev)
> > >  {
> > >  	struct snd_card *card = dev_get_drvdata(dev);
> > > @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device *dev)
> > >  	int rc;
> > >  
> > >  	rc = hda_tegra_enable_clocks(hda);
> > > -	if (rc != 0)
> > > +	if (rc)
> > >  		return rc;
> > >  	if (chip && chip->running) {
> > >  		hda_tegra_init(hda);
> > > @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device *dev)
> > >  
> > >  	return 0;
> > >  }
> > > -#endif /* CONFIG_PM */
> > >  
> > >  static const struct dev_pm_ops hda_tegra_pm = {
> > >  	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
> > > @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
> > >  
> > >  	dev_set_drvdata(&pdev->dev, card);
> > >  
> > > -	pm_runtime_enable(hda->dev);
> > > -	if (!azx_has_pm_runtime(chip))
> > > -		pm_runtime_forbid(hda->dev);
> > > +	err = hda_tegra_enable_clocks(hda);
> > > +	if (err)
> > > +		goto out_free;
> > 
> > We also need to think about power-domains here. Enabling the clocks
> > might not be enough as the appropriate power-domain needs to be enabled.
> > For 64-bit Tegra runtime-pm will handle the power-domains (assuming they
> > are populated in device-tree). So I still think it is better we call
> > pm_runtime_get_sync() at some point rather than just replying on
> > enabling the clocks.
> 
> If I understand correctly the code, the pm domain is already activated
> at calling driver's probe callback.

As far as I can tell, the domain will also be powered off again after
probe finished, unless the device grabs a runtime PM reference. This is
what happens via the dev->pm_domain->sync() call after successful probe
of a driver.

It seems to me like it's not a very well defined case what to do when a
device needs to be powered up but runtime PM is not enabled.

Adding Rafael and linux-pm, maybe they can provide some guidance on what
to do in these situations.

To summarize, what we're debating here is how to handle powering up a
device if the pm_runtime infrastructure doesn't take care of it. Jon's
proposal here was, and we use this elsewhere, to do something like this:

	pm_runtime_enable(dev);
	if (!pm_runtime_enabled(dev)) {
		err = foo_runtime_resume(dev);
		if (err < 0)
			goto fail;
	}

So basically when runtime PM is not available, we explicitly "resume"
the device to power it up.

It seems to me like that's a fairly common problem, so I'm wondering if
there's something that the runtime PM core could do to help with this.
Or perhaps there's already a way to achieve this that we're all
overlooking?

Rafael, any suggestions?

Thanks,
Thierry
Takashi Iwai Jan. 31, 2019, 11:21 a.m. UTC | #8
On Thu, 31 Jan 2019 12:05:30 +0100,
Thierry Reding wrote:
> 
> On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> > On Wed, 30 Jan 2019 13:45:49 +0100,
> > Jon Hunter wrote:
> > > 
> > > 
> > > On 25/01/2019 11:06, Sameer Pujar wrote:
> > > > If CONFIG_PM is disabled or runtime PM calls are forbidden, the clocks
> > > > will not be ON. This could cause issue during probe, where hda init
> > > > setup is done. This patch enables clocks unconditionally during probe.
> > > > 
> > > > Along with above, follwoing changes are done.
> > > >   * enable runtime PM before exiting from probe work. This helps to avoid
> > > >     usage of pm_runtime_get_sync/pm_runtime_put() in probe work.
> > > >   * hda_tegra_disable_clocks() is moved out of CONFIG_PM_SLEEP check.
> > > >   * runtime PM callbacks moved out of CONFIG_PM check
> > > > 
> > > > Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> > > > Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
> > > > Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
> > > > ---
> > > >  sound/pci/hda/hda_tegra.c | 26 +++++++++++++++++---------
> > > >  1 file changed, 17 insertions(+), 9 deletions(-)
> > > > 
> > > > diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
> > > > index c8d18dc..ba6175f 100644
> > > > --- a/sound/pci/hda/hda_tegra.c
> > > > +++ b/sound/pci/hda/hda_tegra.c
> > > > @@ -219,7 +219,6 @@ static int hda_tegra_enable_clocks(struct hda_tegra *data)
> > > >  	return rc;
> > > >  }
> > > >  
> > > > -#ifdef CONFIG_PM_SLEEP
> > > >  static void hda_tegra_disable_clocks(struct hda_tegra *data)
> > > >  {
> > > >  	clk_disable_unprepare(data->hda2hdmi_clk);
> > > > @@ -227,6 +226,7 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
> > > >  	clk_disable_unprepare(data->hda_clk);
> > > >  }
> > > >  
> > > > +#ifdef CONFIG_PM_SLEEP
> > > >  /*
> > > >   * power management
> > > >   */
> > > > @@ -257,7 +257,6 @@ static int hda_tegra_resume(struct device *dev)
> > > >  }
> > > >  #endif /* CONFIG_PM_SLEEP */
> > > >  
> > > > -#ifdef CONFIG_PM
> > > >  static int hda_tegra_runtime_suspend(struct device *dev)
> > > >  {
> > > >  	struct snd_card *card = dev_get_drvdata(dev);
> > > > @@ -283,7 +282,7 @@ static int hda_tegra_runtime_resume(struct device *dev)
> > > >  	int rc;
> > > >  
> > > >  	rc = hda_tegra_enable_clocks(hda);
> > > > -	if (rc != 0)
> > > > +	if (rc)
> > > >  		return rc;
> > > >  	if (chip && chip->running) {
> > > >  		hda_tegra_init(hda);
> > > > @@ -292,7 +291,6 @@ static int hda_tegra_runtime_resume(struct device *dev)
> > > >  
> > > >  	return 0;
> > > >  }
> > > > -#endif /* CONFIG_PM */
> > > >  
> > > >  static const struct dev_pm_ops hda_tegra_pm = {
> > > >  	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
> > > > @@ -551,9 +549,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
> > > >  
> > > >  	dev_set_drvdata(&pdev->dev, card);
> > > >  
> > > > -	pm_runtime_enable(hda->dev);
> > > > -	if (!azx_has_pm_runtime(chip))
> > > > -		pm_runtime_forbid(hda->dev);
> > > > +	err = hda_tegra_enable_clocks(hda);
> > > > +	if (err)
> > > > +		goto out_free;
> > > 
> > > We also need to think about power-domains here. Enabling the clocks
> > > might not be enough as the appropriate power-domain needs to be enabled.
> > > For 64-bit Tegra runtime-pm will handle the power-domains (assuming they
> > > are populated in device-tree). So I still think it is better we call
> > > pm_runtime_get_sync() at some point rather than just replying on
> > > enabling the clocks.
> > 
> > If I understand correctly the code, the pm domain is already activated
> > at calling driver's probe callback.
> 
> As far as I can tell, the domain will also be powered off again after
> probe finished, unless the device grabs a runtime PM reference. This is
> what happens via the dev->pm_domain->sync() call after successful probe
> of a driver.

Ah, a good point.  This can be a problem with a probe work like this
case.

> It seems to me like it's not a very well defined case what to do when a
> device needs to be powered up but runtime PM is not enabled.
> 
> Adding Rafael and linux-pm, maybe they can provide some guidance on what
> to do in these situations.
> 
> To summarize, what we're debating here is how to handle powering up a
> device if the pm_runtime infrastructure doesn't take care of it. Jon's
> proposal here was, and we use this elsewhere, to do something like this:
> 
> 	pm_runtime_enable(dev);
> 	if (!pm_runtime_enabled(dev)) {
> 		err = foo_runtime_resume(dev);
> 		if (err < 0)
> 			goto fail;
> 	}
> 
> So basically when runtime PM is not available, we explicitly "resume"
> the device to power it up.
> 
> It seems to me like that's a fairly common problem, so I'm wondering if
> there's something that the runtime PM core could do to help with this.
> Or perhaps there's already a way to achieve this that we're all
> overlooking?
> 
> Rafael, any suggestions?

If any, a common helper would be appreciated, indeed.


thanks,

Takashi
Rafael J. Wysocki Jan. 31, 2019, 11:46 a.m. UTC | #9
On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
>
> On Thu, 31 Jan 2019 12:05:30 +0100,
> Thierry Reding wrote:
> >
> > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:

[cut]

> > > If I understand correctly the code, the pm domain is already activated
> > > at calling driver's probe callback.
> >
> > As far as I can tell, the domain will also be powered off again after
> > probe finished, unless the device grabs a runtime PM reference. This is
> > what happens via the dev->pm_domain->sync() call after successful probe
> > of a driver.
>
> Ah, a good point.  This can be a problem with a probe work like this
> case.
>
> > It seems to me like it's not a very well defined case what to do when a
> > device needs to be powered up but runtime PM is not enabled.
> >
> > Adding Rafael and linux-pm, maybe they can provide some guidance on what
> > to do in these situations.
> >
> > To summarize, what we're debating here is how to handle powering up a
> > device if the pm_runtime infrastructure doesn't take care of it. Jon's
> > proposal here was, and we use this elsewhere, to do something like this:
> >
> >       pm_runtime_enable(dev);
> >       if (!pm_runtime_enabled(dev)) {
> >               err = foo_runtime_resume(dev);
> >               if (err < 0)
> >                       goto fail;
> >       }
> >
> > So basically when runtime PM is not available, we explicitly "resume"
> > the device to power it up.
> >
> > It seems to me like that's a fairly common problem, so I'm wondering if
> > there's something that the runtime PM core could do to help with this.
> > Or perhaps there's already a way to achieve this that we're all
> > overlooking?
> >
> > Rafael, any suggestions?
>
> If any, a common helper would be appreciated, indeed.

I'm not sure that I understand the problem correctly, so let me
restate it the way I understand it.

What we're talking about is a driver ->probe() callback.  Runtime PM
is disabled initially and the device is off.  It needs to be powered
up, but the way to do that depends on some configuration of the board
etc., so ideally

pm_runtime_enable(dev);
ret = pm_runtime_resume(dev);

should just work, but the question is what to do if runtime PM doesn't
work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
else?
Rafael J. Wysocki Jan. 31, 2019, 11:50 a.m. UTC | #10
On Thu, Jan 31, 2019 at 12:46 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
> >
> > On Thu, 31 Jan 2019 12:05:30 +0100,
> > Thierry Reding wrote:
> > >
> > > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
>
> [cut]
>
> > > > If I understand correctly the code, the pm domain is already activated
> > > > at calling driver's probe callback.
> > >
> > > As far as I can tell, the domain will also be powered off again after
> > > probe finished, unless the device grabs a runtime PM reference. This is
> > > what happens via the dev->pm_domain->sync() call after successful probe
> > > of a driver.
> >
> > Ah, a good point.  This can be a problem with a probe work like this
> > case.
> >
> > > It seems to me like it's not a very well defined case what to do when a
> > > device needs to be powered up but runtime PM is not enabled.
> > >
> > > Adding Rafael and linux-pm, maybe they can provide some guidance on what
> > > to do in these situations.
> > >
> > > To summarize, what we're debating here is how to handle powering up a
> > > device if the pm_runtime infrastructure doesn't take care of it. Jon's
> > > proposal here was, and we use this elsewhere, to do something like this:
> > >
> > >       pm_runtime_enable(dev);
> > >       if (!pm_runtime_enabled(dev)) {
> > >               err = foo_runtime_resume(dev);
> > >               if (err < 0)
> > >                       goto fail;
> > >       }
> > >
> > > So basically when runtime PM is not available, we explicitly "resume"
> > > the device to power it up.
> > >
> > > It seems to me like that's a fairly common problem, so I'm wondering if
> > > there's something that the runtime PM core could do to help with this.
> > > Or perhaps there's already a way to achieve this that we're all
> > > overlooking?
> > >
> > > Rafael, any suggestions?
> >
> > If any, a common helper would be appreciated, indeed.
>
> I'm not sure that I understand the problem correctly, so let me
> restate it the way I understand it.
>
> What we're talking about is a driver ->probe() callback.  Runtime PM
> is disabled initially and the device is off.  It needs to be powered
> up, but the way to do that depends on some configuration of the board
> etc., so ideally
>
> pm_runtime_enable(dev);
> ret = pm_runtime_resume(dev);
>
> should just work, but the question is what to do if runtime PM doesn't
> work as expected.  That is, CONFIG_PM_RUNTIME is unset?

Well, we got rid of CONFIG_PM_RUNTIME, so that would be CONFIG_PM unset rather.

>  Or something else?
Takashi Iwai Jan. 31, 2019, 11:59 a.m. UTC | #11
On Thu, 31 Jan 2019 12:46:54 +0100,
Rafael J. Wysocki wrote:
> 
> On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
> >
> > On Thu, 31 Jan 2019 12:05:30 +0100,
> > Thierry Reding wrote:
> > >
> > > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> 
> [cut]
> 
> > > > If I understand correctly the code, the pm domain is already activated
> > > > at calling driver's probe callback.
> > >
> > > As far as I can tell, the domain will also be powered off again after
> > > probe finished, unless the device grabs a runtime PM reference. This is
> > > what happens via the dev->pm_domain->sync() call after successful probe
> > > of a driver.
> >
> > Ah, a good point.  This can be a problem with a probe work like this
> > case.
> >
> > > It seems to me like it's not a very well defined case what to do when a
> > > device needs to be powered up but runtime PM is not enabled.
> > >
> > > Adding Rafael and linux-pm, maybe they can provide some guidance on what
> > > to do in these situations.
> > >
> > > To summarize, what we're debating here is how to handle powering up a
> > > device if the pm_runtime infrastructure doesn't take care of it. Jon's
> > > proposal here was, and we use this elsewhere, to do something like this:
> > >
> > >       pm_runtime_enable(dev);
> > >       if (!pm_runtime_enabled(dev)) {
> > >               err = foo_runtime_resume(dev);
> > >               if (err < 0)
> > >                       goto fail;
> > >       }
> > >
> > > So basically when runtime PM is not available, we explicitly "resume"
> > > the device to power it up.
> > >
> > > It seems to me like that's a fairly common problem, so I'm wondering if
> > > there's something that the runtime PM core could do to help with this.
> > > Or perhaps there's already a way to achieve this that we're all
> > > overlooking?
> > >
> > > Rafael, any suggestions?
> >
> > If any, a common helper would be appreciated, indeed.
> 
> I'm not sure that I understand the problem correctly, so let me
> restate it the way I understand it.
> 
> What we're talking about is a driver ->probe() callback.  Runtime PM
> is disabled initially and the device is off.  It needs to be powered
> up, but the way to do that depends on some configuration of the board
> etc., so ideally
> 
> pm_runtime_enable(dev);
> ret = pm_runtime_resume(dev);
> 
> should just work, but the question is what to do if runtime PM doesn't
> work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
> else?

Yes, the question is how to write the code for both with and without
CONFIG_PM (or CONFIG_PM_RUNTIME).

Right now, we have a code like below, pushing the initialization in an
async work and let the probe returning quickly.

	hda_tegra_probe() {
		....
		pm_runtime_enable();
		schedule_work();
		return;
	}

	hda_tegra_probe_work() {
		pm_runtime_get_sync();
		....
		pm_runtime_put_sync();
	}

Then it truned outhis code lacks of the clock initialization when
runtime PM isn't enabled.  Normally it's done via runtime resume

	hda_tegra_runtime_resume() {
		hda_tegra_enable_clocks();
		....
	}

And now the question is what is the standard idiom in such a case.

IMO, calling pm_runtime_resume() inside the probe function looks
weird, and my preference was to initialize the clocks explicitly, then
enable runtime PM.  But if using pm_runtime_resume() in the proc
should be seen as a standard procedure, I'm fine with that.


thanks,

Takashi
Rafael J. Wysocki Jan. 31, 2019, 12:10 p.m. UTC | #12
On Thu, Jan 31, 2019 at 12:59 PM Takashi Iwai <tiwai@suse.de> wrote:
>
> On Thu, 31 Jan 2019 12:46:54 +0100,
> Rafael J. Wysocki wrote:
> >
> > On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
> > >
> > > On Thu, 31 Jan 2019 12:05:30 +0100,
> > > Thierry Reding wrote:
> > > >
> > > > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> >
> > [cut]
> >
> > > > > If I understand correctly the code, the pm domain is already activated
> > > > > at calling driver's probe callback.
> > > >
> > > > As far as I can tell, the domain will also be powered off again after
> > > > probe finished, unless the device grabs a runtime PM reference. This is
> > > > what happens via the dev->pm_domain->sync() call after successful probe
> > > > of a driver.
> > >
> > > Ah, a good point.  This can be a problem with a probe work like this
> > > case.
> > >
> > > > It seems to me like it's not a very well defined case what to do when a
> > > > device needs to be powered up but runtime PM is not enabled.
> > > >
> > > > Adding Rafael and linux-pm, maybe they can provide some guidance on what
> > > > to do in these situations.
> > > >
> > > > To summarize, what we're debating here is how to handle powering up a
> > > > device if the pm_runtime infrastructure doesn't take care of it. Jon's
> > > > proposal here was, and we use this elsewhere, to do something like this:
> > > >
> > > >       pm_runtime_enable(dev);
> > > >       if (!pm_runtime_enabled(dev)) {
> > > >               err = foo_runtime_resume(dev);
> > > >               if (err < 0)
> > > >                       goto fail;
> > > >       }
> > > >
> > > > So basically when runtime PM is not available, we explicitly "resume"
> > > > the device to power it up.
> > > >
> > > > It seems to me like that's a fairly common problem, so I'm wondering if
> > > > there's something that the runtime PM core could do to help with this.
> > > > Or perhaps there's already a way to achieve this that we're all
> > > > overlooking?
> > > >
> > > > Rafael, any suggestions?
> > >
> > > If any, a common helper would be appreciated, indeed.
> >
> > I'm not sure that I understand the problem correctly, so let me
> > restate it the way I understand it.
> >
> > What we're talking about is a driver ->probe() callback.  Runtime PM
> > is disabled initially and the device is off.  It needs to be powered
> > up, but the way to do that depends on some configuration of the board
> > etc., so ideally
> >
> > pm_runtime_enable(dev);
> > ret = pm_runtime_resume(dev);
> >
> > should just work, but the question is what to do if runtime PM doesn't
> > work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
> > else?
>
> Yes, the question is how to write the code for both with and without
> CONFIG_PM (or CONFIG_PM_RUNTIME).

This basically is about setup, because after that point all should
just work in both cases.

Personally, I would do

if (IS_ENABLED(CONFIG_PM)) {
  do setup based on pm-runtime
} else {
  do manual setup
}

> Right now, we have a code like below, pushing the initialization in an
> async work and let the probe returning quickly.
>
>         hda_tegra_probe() {
>                 ....

So why don't you do

if (!IS_ENABLED(CONFIG_PM)) {
  do manual clock setup
}

here?

>                 pm_runtime_enable();
>                 schedule_work();
>                 return;
>         }
>
>         hda_tegra_probe_work() {
>                 pm_runtime_get_sync();
>                 ....
>                 pm_runtime_put_sync();
>         }
>
> Then it truned outhis code lacks of the clock initialization when
> runtime PM isn't enabled.  Normally it's done via runtime resume
>
>         hda_tegra_runtime_resume() {
>                 hda_tegra_enable_clocks();
>                 ....
>         }
>
> And now the question is what is the standard idiom in such a case.
>
> IMO, calling pm_runtime_resume() inside the probe function looks
> weird, and my preference was to initialize the clocks explicitly, then
> enable runtime PM.  But if using pm_runtime_resume() in the proc
> should be seen as a standard procedure, I'm fine with that.

Well, people do pm_runtime_resume() in ->probe() too, but
pm_runtime_resume() returns 1 for CONFIG_PM unset, so that won't give
you what you want anyway. :-)

Cheers,
Rafael
Sameer Pujar Jan. 31, 2019, 2:21 p.m. UTC | #13
On 1/31/2019 5:40 PM, Rafael J. Wysocki wrote:
> On Thu, Jan 31, 2019 at 12:59 PM Takashi Iwai <tiwai@suse.de> wrote:
>> On Thu, 31 Jan 2019 12:46:54 +0100,
>> Rafael J. Wysocki wrote:
>>> On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
>>>> On Thu, 31 Jan 2019 12:05:30 +0100,
>>>> Thierry Reding wrote:
>>>>> On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
>>> [cut]
>>>
>>>>>> If I understand correctly the code, the pm domain is already activated
>>>>>> at calling driver's probe callback.
>>>>> As far as I can tell, the domain will also be powered off again after
>>>>> probe finished, unless the device grabs a runtime PM reference. This is
>>>>> what happens via the dev->pm_domain->sync() call after successful probe
>>>>> of a driver.
>>>> Ah, a good point.  This can be a problem with a probe work like this
>>>> case.

Are you suggesting, whether runtime PM is enabled/disabled, after 
successful probe the
domain would be powered off?
For CONFIG_PM enabled case, probe() can call get_sync() and put_sync() 
can be in probe_work.
How this needs to be handled for CONFG_PM disabled case? (just calling 
clock_enable() may
not be sufficient as per previous comments)

>>>>> It seems to me like it's not a very well defined case what to do when a
>>>>> device needs to be powered up but runtime PM is not enabled.
>>>>>
>>>>> Adding Rafael and linux-pm, maybe they can provide some guidance on what
>>>>> to do in these situations.
>>>>>
>>>>> To summarize, what we're debating here is how to handle powering up a
>>>>> device if the pm_runtime infrastructure doesn't take care of it. Jon's
>>>>> proposal here was, and we use this elsewhere, to do something like this:
>>>>>
>>>>>        pm_runtime_enable(dev);
>>>>>        if (!pm_runtime_enabled(dev)) {
>>>>>                err = foo_runtime_resume(dev);
>>>>>                if (err < 0)
>>>>>                        goto fail;
>>>>>        }
>>>>>
>>>>> So basically when runtime PM is not available, we explicitly "resume"
>>>>> the device to power it up.
>>>>>
>>>>> It seems to me like that's a fairly common problem, so I'm wondering if
>>>>> there's something that the runtime PM core could do to help with this.
>>>>> Or perhaps there's already a way to achieve this that we're all
>>>>> overlooking?
>>>>>
>>>>> Rafael, any suggestions?
>>>> If any, a common helper would be appreciated, indeed.
>>> I'm not sure that I understand the problem correctly, so let me
>>> restate it the way I understand it.
>>>
>>> What we're talking about is a driver ->probe() callback.  Runtime PM
>>> is disabled initially and the device is off.  It needs to be powered
>>> up, but the way to do that depends on some configuration of the board
>>> etc., so ideally
>>>
>>> pm_runtime_enable(dev);
>>> ret = pm_runtime_resume(dev);
>>>
>>> should just work, but the question is what to do if runtime PM doesn't
>>> work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
>>> else?
>> Yes, the question is how to write the code for both with and without
>> CONFIG_PM (or CONFIG_PM_RUNTIME).
> This basically is about setup, because after that point all should
> just work in both cases.
>
> Personally, I would do
>
> if (IS_ENABLED(CONFIG_PM)) {
>    do setup based on pm-runtime
> } else {
>    do manual setup
> }

do we really need config check here?
The debate was, whether to call hda_tegra_runtime_resume() or 
hda_tegra_enable_clocks() unconditionally here.
It would take care of both CONFIG_PM enabled/disabled cases. Then enable 
runtime PM.

>> Right now, we have a code like below, pushing the initialization in an
>> async work and let the probe returning quickly.
>>
>>          hda_tegra_probe() {
>>                  ....
> So why don't you do
>
> if (!IS_ENABLED(CONFIG_PM)) {
>    do manual clock setup
> }
>
> here?
>
>>                  pm_runtime_enable();
>>                  schedule_work();
>>                  return;
>>          }
>>
>>          hda_tegra_probe_work() {
>>                  pm_runtime_get_sync();
>>                  ....
>>                  pm_runtime_put_sync();
>>          }
>>
>> Then it truned outhis code lacks of the clock initialization when
>> runtime PM isn't enabled.  Normally it's done via runtime resume
>>
>>          hda_tegra_runtime_resume() {
>>                  hda_tegra_enable_clocks();
>>                  ....
>>          }
>>
>> And now the question is what is the standard idiom in such a case.
>>
>> IMO, calling pm_runtime_resume() inside the probe function looks
>> weird, and my preference was to initialize the clocks explicitly, then
>> enable runtime PM.  But if using pm_runtime_resume() in the proc
>> should be seen as a standard procedure, I'm fine with that.

I think reference here is, whether calling hda_tegra_runtime_resume() in 
probe() is
a standard procedure or not.

> Well, people do pm_runtime_resume() in ->probe() too, but
> pm_runtime_resume() returns 1 for CONFIG_PM unset, so that won't give
> you what you want anyway. :-)
>
> Cheers,
> Rafael
Thierry Reding Jan. 31, 2019, 2:30 p.m. UTC | #14
On Thu, Jan 31, 2019 at 01:10:01PM +0100, Rafael J. Wysocki wrote:
> On Thu, Jan 31, 2019 at 12:59 PM Takashi Iwai <tiwai@suse.de> wrote:
> >
> > On Thu, 31 Jan 2019 12:46:54 +0100,
> > Rafael J. Wysocki wrote:
> > >
> > > On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
> > > >
> > > > On Thu, 31 Jan 2019 12:05:30 +0100,
> > > > Thierry Reding wrote:
> > > > >
> > > > > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> > >
> > > [cut]
> > >
> > > > > > If I understand correctly the code, the pm domain is already activated
> > > > > > at calling driver's probe callback.
> > > > >
> > > > > As far as I can tell, the domain will also be powered off again after
> > > > > probe finished, unless the device grabs a runtime PM reference. This is
> > > > > what happens via the dev->pm_domain->sync() call after successful probe
> > > > > of a driver.
> > > >
> > > > Ah, a good point.  This can be a problem with a probe work like this
> > > > case.
> > > >
> > > > > It seems to me like it's not a very well defined case what to do when a
> > > > > device needs to be powered up but runtime PM is not enabled.
> > > > >
> > > > > Adding Rafael and linux-pm, maybe they can provide some guidance on what
> > > > > to do in these situations.
> > > > >
> > > > > To summarize, what we're debating here is how to handle powering up a
> > > > > device if the pm_runtime infrastructure doesn't take care of it. Jon's
> > > > > proposal here was, and we use this elsewhere, to do something like this:
> > > > >
> > > > >       pm_runtime_enable(dev);
> > > > >       if (!pm_runtime_enabled(dev)) {
> > > > >               err = foo_runtime_resume(dev);
> > > > >               if (err < 0)
> > > > >                       goto fail;
> > > > >       }
> > > > >
> > > > > So basically when runtime PM is not available, we explicitly "resume"
> > > > > the device to power it up.
> > > > >
> > > > > It seems to me like that's a fairly common problem, so I'm wondering if
> > > > > there's something that the runtime PM core could do to help with this.
> > > > > Or perhaps there's already a way to achieve this that we're all
> > > > > overlooking?
> > > > >
> > > > > Rafael, any suggestions?
> > > >
> > > > If any, a common helper would be appreciated, indeed.
> > >
> > > I'm not sure that I understand the problem correctly, so let me
> > > restate it the way I understand it.
> > >
> > > What we're talking about is a driver ->probe() callback.  Runtime PM
> > > is disabled initially and the device is off.  It needs to be powered
> > > up, but the way to do that depends on some configuration of the board
> > > etc., so ideally
> > >
> > > pm_runtime_enable(dev);
> > > ret = pm_runtime_resume(dev);
> > >
> > > should just work, but the question is what to do if runtime PM doesn't
> > > work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
> > > else?
> >
> > Yes, the question is how to write the code for both with and without
> > CONFIG_PM (or CONFIG_PM_RUNTIME).
> 
> This basically is about setup, because after that point all should
> just work in both cases.
> 
> Personally, I would do
> 
> if (IS_ENABLED(CONFIG_PM)) {
>   do setup based on pm-runtime
> } else {
>   do manual setup
> }
> 
> > Right now, we have a code like below, pushing the initialization in an
> > async work and let the probe returning quickly.
> >
> >         hda_tegra_probe() {
> >                 ....
> 
> So why don't you do
> 
> if (!IS_ENABLED(CONFIG_PM)) {
>   do manual clock setup
> }
> 
> here?

I think that's exactly what Jon and Sameer were proposing, although the
discussion started primarily because of the way it was done.

So basically the idea was to do:

	pm_runtime_enable()
	if (!pm_runtime_enabled())  /* basically !IS_ENABLED(CONFIG_PM) */
		hda_runtime_resume()

So we're not calling pm_runtime_resume() but rather the driver's
implementation of it. This is to avoid duplicating the code, which under
some circumstances can be fairly long. Duplicating is also error prone
because both instances may not always be in sync.

My understanding is that Takashi had reservations about using this kind
of construct because, well, frankly, it looks a little weird. We'd also
likely want to have a similar construct again in the ->remove() callback
to make sure we properly power off the device when it is no longer
needed. I'm just wondering if perhaps there should be a mechanism in the
core to take care of this, because this is basically something that we'd
need to do for every single driver.

For example, if !CONFIG_PM couldn't the pm_runtime_enable() function be
modified to do the above? This would be somewhat tricky because drivers
usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
that would result in an empty structure if !CONFIG_PM, but we could
probably work around that by adding a __SET_RUNTIME_PM_OPS that would
never be compiled out for this kind of case. Or such drivers could even
manually set .runtime_suspend and .runtime_resume to make sure they're
always populated.

Another way out of this would be to make sure we never run into the case
where runtime PM is disabled. If we always "select PM" on Tegra, then PM
should always be available. But is it guaranteed that runtime PM for the
devices is functional in that case? From a cursory look at the code it
would seem that way.

Thierry
Rafael J. Wysocki Jan. 31, 2019, 11:24 p.m. UTC | #15
On Thursday, January 31, 2019 3:30:24 PM CET Thierry Reding wrote:
> 
> --Pk/CTwBz1VvfPIDp
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: inline
> Content-Transfer-Encoding: quoted-printable
> 
> On Thu, Jan 31, 2019 at 01:10:01PM +0100, Rafael J. Wysocki wrote:
> > On Thu, Jan 31, 2019 at 12:59 PM Takashi Iwai <tiwai@suse.de> wrote:
> > >
> > > On Thu, 31 Jan 2019 12:46:54 +0100,
> > > Rafael J. Wysocki wrote:
> > > >
> > > > On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
> > > > >
> > > > > On Thu, 31 Jan 2019 12:05:30 +0100,
> > > > > Thierry Reding wrote:
> > > > > >
> > > > > > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> > > >
> > > > [cut]
> > > >
> > > > > > > If I understand correctly the code, the pm domain is already ac=
> tivated
> > > > > > > at calling driver's probe callback.
> > > > > >
> > > > > > As far as I can tell, the domain will also be powered off again a=
> fter
> > > > > > probe finished, unless the device grabs a runtime PM reference. T=
> his is
> > > > > > what happens via the dev->pm_domain->sync() call after successful=
>  probe
> > > > > > of a driver.
> > > > >
> > > > > Ah, a good point.  This can be a problem with a probe work like this
> > > > > case.
> > > > >
> > > > > > It seems to me like it's not a very well defined case what to do =
> when a
> > > > > > device needs to be powered up but runtime PM is not enabled.
> > > > > >
> > > > > > Adding Rafael and linux-pm, maybe they can provide some guidance =
> on what
> > > > > > to do in these situations.
> > > > > >
> > > > > > To summarize, what we're debating here is how to handle powering =
> up a
> > > > > > device if the pm_runtime infrastructure doesn't take care of it. =
> Jon's
> > > > > > proposal here was, and we use this elsewhere, to do something lik=
> e this:
> > > > > >
> > > > > >       pm_runtime_enable(dev);
> > > > > >       if (!pm_runtime_enabled(dev)) {
> > > > > >               err =3D foo_runtime_resume(dev);
> > > > > >               if (err < 0)
> > > > > >                       goto fail;
> > > > > >       }
> > > > > >
> > > > > > So basically when runtime PM is not available, we explicitly "res=
> ume"
> > > > > > the device to power it up.
> > > > > >
> > > > > > It seems to me like that's a fairly common problem, so I'm wonder=
> ing if
> > > > > > there's something that the runtime PM core could do to help with =
> this.
> > > > > > Or perhaps there's already a way to achieve this that we're all
> > > > > > overlooking?
> > > > > >
> > > > > > Rafael, any suggestions?
> > > > >
> > > > > If any, a common helper would be appreciated, indeed.
> > > >
> > > > I'm not sure that I understand the problem correctly, so let me
> > > > restate it the way I understand it.
> > > >
> > > > What we're talking about is a driver ->probe() callback.  Runtime PM
> > > > is disabled initially and the device is off.  It needs to be powered
> > > > up, but the way to do that depends on some configuration of the board
> > > > etc., so ideally
> > > >
> > > > pm_runtime_enable(dev);
> > > > ret =3D pm_runtime_resume(dev);
> > > >
> > > > should just work, but the question is what to do if runtime PM doesn't
> > > > work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
> > > > else?
> > >
> > > Yes, the question is how to write the code for both with and without
> > > CONFIG_PM (or CONFIG_PM_RUNTIME).
> >=20
> > This basically is about setup, because after that point all should
> > just work in both cases.
> >=20
> > Personally, I would do
> >=20
> > if (IS_ENABLED(CONFIG_PM)) {
> >   do setup based on pm-runtime
> > } else {
> >   do manual setup
> > }
> >=20
> > > Right now, we have a code like below, pushing the initialization in an
> > > async work and let the probe returning quickly.
> > >
> > >         hda_tegra_probe() {
> > >                 ....
> >=20
> > So why don't you do
> >=20
> > if (!IS_ENABLED(CONFIG_PM)) {
> >   do manual clock setup
> > }
> >=20
> > here?
> 
> I think that's exactly what Jon and Sameer were proposing, although the
> discussion started primarily because of the way it was done.
> 
> So basically the idea was to do:
> 
> 	pm_runtime_enable()
> 	if (!pm_runtime_enabled())  /* basically !IS_ENABLED(CONFIG_PM) */

But why is it any better than checking !IS_ENABLED(CONFIG_PM) directly?

> 		hda_runtime_resume()
> 
> So we're not calling pm_runtime_resume() but rather the driver's
> implementation of it. This is to avoid duplicating the code, which under
> some circumstances can be fairly long. Duplicating is also error prone
> because both instances may not always be in sync.
> 
> My understanding is that Takashi had reservations about using this kind
> of construct because, well, frankly, it looks a little weird.

Yes, the way it was originally written above was weird, but is checking
IS_ENABLED(CONFIG_PM) directly really so weird?

> We'd also likely want to have a similar construct again in the ->remove()
> callback to make sure we properly power off the device when it is no longer
> needed.

Sure.  Again, why don't you make it conditional on IS_ENABLED(CONFIG_PM)?

> I'm just wondering if perhaps there should be a mechanism in the
> core to take care of this,

How exactly?  How's the core going to know what to do when CONFIG_PM is
disabled?

> because this is basically something that we'd need to do for every single
> driver.

That is not true.  If the device is alwyas "on" to start with, you don't
need to do anything.  That's the case on many systems.

> For example, if !CONFIG_PM couldn't the pm_runtime_enable() function be
> modified to do the above?

But you'd need to pass a pointer to your hda_runtime_resume() to it at least
and how's that simpler than using a simple conditional directly?

> This would be somewhat tricky because drivers
> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
> that would result in an empty structure if !CONFIG_PM, but we could
> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
> never be compiled out for this kind of case. Or such drivers could even
> manually set .runtime_suspend and .runtime_resume to make sure they're
> always populated.
> 
> Another way out of this would be to make sure we never run into the case
> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
> should always be available. But is it guaranteed that runtime PM for the
> devices is functional in that case? From a cursory look at the code it
> would seem that way.

If you select PM, then all of the requisite code should be there.

Alternatively, you can make the driver depend on PM.

Cheers,
Rafael
Sameer Pujar Feb. 4, 2019, 8:16 a.m. UTC | #16
On 2/1/2019 4:54 AM, Rafael J. Wysocki wrote:
> On Thursday, January 31, 2019 3:30:24 PM CET Thierry Reding wrote:
>> --Pk/CTwBz1VvfPIDp
>> Content-Type: text/plain; charset=us-ascii
>> Content-Disposition: inline
>> Content-Transfer-Encoding: quoted-printable
>>
>> On Thu, Jan 31, 2019 at 01:10:01PM +0100, Rafael J. Wysocki wrote:
>>> On Thu, Jan 31, 2019 at 12:59 PM Takashi Iwai <tiwai@suse.de> wrote:
>>>> On Thu, 31 Jan 2019 12:46:54 +0100,
>>>> Rafael J. Wysocki wrote:
>>>>> On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
>>>>>> On Thu, 31 Jan 2019 12:05:30 +0100,
>>>>>> Thierry Reding wrote:
>>>>>>> On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
>>>>> [cut]
>>>>>
>>>>>>>> If I understand correctly the code, the pm domain is already ac=
>> tivated
>>>>>>>> at calling driver's probe callback.
>>>>>>> As far as I can tell, the domain will also be powered off again a=
>> fter
>>>>>>> probe finished, unless the device grabs a runtime PM reference. T=
>> his is
>>>>>>> what happens via the dev->pm_domain->sync() call after successful=
>>   probe
>>>>>>> of a driver.
>>>>>> Ah, a good point.  This can be a problem with a probe work like this
>>>>>> case.
>>>>>>
>>>>>>> It seems to me like it's not a very well defined case what to do =
>> when a
>>>>>>> device needs to be powered up but runtime PM is not enabled.
>>>>>>>
>>>>>>> Adding Rafael and linux-pm, maybe they can provide some guidance =
>> on what
>>>>>>> to do in these situations.
>>>>>>>
>>>>>>> To summarize, what we're debating here is how to handle powering =
>> up a
>>>>>>> device if the pm_runtime infrastructure doesn't take care of it. =
>> Jon's
>>>>>>> proposal here was, and we use this elsewhere, to do something lik=
>> e this:
>>>>>>>        pm_runtime_enable(dev);
>>>>>>>        if (!pm_runtime_enabled(dev)) {
>>>>>>>                err =3D foo_runtime_resume(dev);
>>>>>>>                if (err < 0)
>>>>>>>                        goto fail;
>>>>>>>        }
>>>>>>>
>>>>>>> So basically when runtime PM is not available, we explicitly "res=
>> ume"
>>>>>>> the device to power it up.
>>>>>>>
>>>>>>> It seems to me like that's a fairly common problem, so I'm wonder=
>> ing if
>>>>>>> there's something that the runtime PM core could do to help with =
>> this.
>>>>>>> Or perhaps there's already a way to achieve this that we're all
>>>>>>> overlooking?
>>>>>>>
>>>>>>> Rafael, any suggestions?
>>>>>> If any, a common helper would be appreciated, indeed.
>>>>> I'm not sure that I understand the problem correctly, so let me
>>>>> restate it the way I understand it.
>>>>>
>>>>> What we're talking about is a driver ->probe() callback.  Runtime PM
>>>>> is disabled initially and the device is off.  It needs to be powered
>>>>> up, but the way to do that depends on some configuration of the board
>>>>> etc., so ideally
>>>>>
>>>>> pm_runtime_enable(dev);
>>>>> ret =3D pm_runtime_resume(dev);
>>>>>
>>>>> should just work, but the question is what to do if runtime PM doesn't
>>>>> work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
>>>>> else?
>>>> Yes, the question is how to write the code for both with and without
>>>> CONFIG_PM (or CONFIG_PM_RUNTIME).
>>> =20
>>> This basically is about setup, because after that point all should
>>> just work in both cases.
>>> =20
>>> Personally, I would do
>>> =20
>>> if (IS_ENABLED(CONFIG_PM)) {
>>>    do setup based on pm-runtime
>>> } else {
>>>    do manual setup
>>> }
>>> =20
>>>> Right now, we have a code like below, pushing the initialization in an
>>>> async work and let the probe returning quickly.
>>>>
>>>>          hda_tegra_probe() {
>>>>                  ....
>>> =20
>>> So why don't you do
>>> =20
>>> if (!IS_ENABLED(CONFIG_PM)) {
>>>    do manual clock setup
>>> }
>>> =20
>>> here?
>> I think that's exactly what Jon and Sameer were proposing, although the
>> discussion started primarily because of the way it was done.
>>
>> So basically the idea was to do:
>>
>> 	pm_runtime_enable()
>> 	if (!pm_runtime_enabled())  /* basically !IS_ENABLED(CONFIG_PM) */
> But why is it any better than checking !IS_ENABLED(CONFIG_PM) directly?
>
>> 		hda_runtime_resume()
>>
>> So we're not calling pm_runtime_resume() but rather the driver's
>> implementation of it. This is to avoid duplicating the code, which under
>> some circumstances can be fairly long. Duplicating is also error prone
>> because both instances may not always be in sync.
>>
>> My understanding is that Takashi had reservations about using this kind
>> of construct because, well, frankly, it looks a little weird.
> Yes, the way it was originally written above was weird, but is checking
> IS_ENABLED(CONFIG_PM) directly really so weird?
>
>> We'd also likely want to have a similar construct again in the ->remove()
>> callback to make sure we properly power off the device when it is no longer
>> needed.
> Sure.  Again, why don't you make it conditional on IS_ENABLED(CONFIG_PM)?
>
>> I'm just wondering if perhaps there should be a mechanism in the
>> core to take care of this,
> How exactly?  How's the core going to know what to do when CONFIG_PM is
> disabled?
>
>> because this is basically something that we'd need to do for every single
>> driver.
> That is not true.  If the device is alwyas "on" to start with, you don't
> need to do anything.  That's the case on many systems.
>
>> For example, if !CONFIG_PM couldn't the pm_runtime_enable() function be
>> modified to do the above?
> But you'd need to pass a pointer to your hda_runtime_resume() to it at least
> and how's that simpler than using a simple conditional directly?
>
>> This would be somewhat tricky because drivers
>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
>> that would result in an empty structure if !CONFIG_PM, but we could
>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
>> never be compiled out for this kind of case. Or such drivers could even
>> manually set .runtime_suspend and .runtime_resume to make sure they're
>> always populated.
>>
>> Another way out of this would be to make sure we never run into the case
>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
>> should always be available. But is it guaranteed that runtime PM for the
>> devices is functional in that case? From a cursory look at the code it
>> would seem that way.
> If you select PM, then all of the requisite code should be there.
>
> Alternatively, you can make the driver depend on PM.
Objective is to have things working with or without CONFIG_PM enabled.
 From previous comments and discussions it appears that there is mixed 
response
for calling hda_tegra_runtime_resume() or runtime PM APIs in probe() 
call. Need
to have consensus regarding the best practice to be followed, which 
would eventually
can be used in other drivers too.

Rafael is suggesting to use CONFIG_PM check to do manual setup or 
runtime PM setup in probe,
which would bring back the earlier above mentioned concern.

if (IS_ENABLED(CONFIG_PM)) {
do setup based on pm-runtime
} else {
     do manual setup
}
Both if/else might end up doing the same here.
Do we really need CONFIG_PM check here?

Instead does below proposal appear fine?

probe() {
     hda_tegra_enable_clock();
}

probe_work() {
     /* hda setup */
     . . .
     pm_runtime_set_active(); /* initial state as active */
     pm_runtime_enable();
     return;
}

remove() {
     pm_runtime_disable();
     if (!pm_runtime_status_suspended())
         hda_tegra_runtime_suspend(); /* takes care of both CONFIG_PM 
enable/disable case */
}

One of the other concern was, remove() and probe() do not appear to be 
in sync, because in probe() hda_tegra_enable_clock()
is called and in remove() there is hda_tegra_runtime_suspend() to 
effectively disable clock.
IMO, this should be ok since it can avoid duplication and proper comment 
can be added here for clarity.
Alternatively we can call hda_tegra_runtime_resume() in probe() 
unconditionally to avoid confusion.

Another point Thierry mentioned was, after successful probe() 
power-domain would be turned OFF. It seems Rafael had a different
view. I am little confused here. Kindly clarify if above proposal seems 
fine.

Thanks,
Sameer.

> Cheers,
> Rafael
>
Thierry Reding Feb. 4, 2019, 8:45 a.m. UTC | #17
On Fri, Feb 01, 2019 at 12:24:31AM +0100, Rafael J. Wysocki wrote:
> On Thursday, January 31, 2019 3:30:24 PM CET Thierry Reding wrote:
> > 
> > --Pk/CTwBz1VvfPIDp
> > Content-Type: text/plain; charset=us-ascii
> > Content-Disposition: inline
> > Content-Transfer-Encoding: quoted-printable
> > 
> > On Thu, Jan 31, 2019 at 01:10:01PM +0100, Rafael J. Wysocki wrote:
> > > On Thu, Jan 31, 2019 at 12:59 PM Takashi Iwai <tiwai@suse.de> wrote:
> > > >
> > > > On Thu, 31 Jan 2019 12:46:54 +0100,
> > > > Rafael J. Wysocki wrote:
> > > > >
> > > > > On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
> > > > > >
> > > > > > On Thu, 31 Jan 2019 12:05:30 +0100,
> > > > > > Thierry Reding wrote:
> > > > > > >
> > > > > > > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> > > > >
> > > > > [cut]
> > > > >
> > > > > > > > If I understand correctly the code, the pm domain is already ac=
> > tivated
> > > > > > > > at calling driver's probe callback.
> > > > > > >
> > > > > > > As far as I can tell, the domain will also be powered off again a=
> > fter
> > > > > > > probe finished, unless the device grabs a runtime PM reference. T=
> > his is
> > > > > > > what happens via the dev->pm_domain->sync() call after successful=
> >  probe
> > > > > > > of a driver.
> > > > > >
> > > > > > Ah, a good point.  This can be a problem with a probe work like this
> > > > > > case.
> > > > > >
> > > > > > > It seems to me like it's not a very well defined case what to do =
> > when a
> > > > > > > device needs to be powered up but runtime PM is not enabled.
> > > > > > >
> > > > > > > Adding Rafael and linux-pm, maybe they can provide some guidance =
> > on what
> > > > > > > to do in these situations.
> > > > > > >
> > > > > > > To summarize, what we're debating here is how to handle powering =
> > up a
> > > > > > > device if the pm_runtime infrastructure doesn't take care of it. =
> > Jon's
> > > > > > > proposal here was, and we use this elsewhere, to do something lik=
> > e this:
> > > > > > >
> > > > > > >       pm_runtime_enable(dev);
> > > > > > >       if (!pm_runtime_enabled(dev)) {
> > > > > > >               err =3D foo_runtime_resume(dev);
> > > > > > >               if (err < 0)
> > > > > > >                       goto fail;
> > > > > > >       }
> > > > > > >
> > > > > > > So basically when runtime PM is not available, we explicitly "res=
> > ume"
> > > > > > > the device to power it up.
> > > > > > >
> > > > > > > It seems to me like that's a fairly common problem, so I'm wonder=
> > ing if
> > > > > > > there's something that the runtime PM core could do to help with =
> > this.
> > > > > > > Or perhaps there's already a way to achieve this that we're all
> > > > > > > overlooking?
> > > > > > >
> > > > > > > Rafael, any suggestions?
> > > > > >
> > > > > > If any, a common helper would be appreciated, indeed.
> > > > >
> > > > > I'm not sure that I understand the problem correctly, so let me
> > > > > restate it the way I understand it.
> > > > >
> > > > > What we're talking about is a driver ->probe() callback.  Runtime PM
> > > > > is disabled initially and the device is off.  It needs to be powered
> > > > > up, but the way to do that depends on some configuration of the board
> > > > > etc., so ideally
> > > > >
> > > > > pm_runtime_enable(dev);
> > > > > ret =3D pm_runtime_resume(dev);
> > > > >
> > > > > should just work, but the question is what to do if runtime PM doesn't
> > > > > work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
> > > > > else?
> > > >
> > > > Yes, the question is how to write the code for both with and without
> > > > CONFIG_PM (or CONFIG_PM_RUNTIME).
> > >=20
> > > This basically is about setup, because after that point all should
> > > just work in both cases.
> > >=20
> > > Personally, I would do
> > >=20
> > > if (IS_ENABLED(CONFIG_PM)) {
> > >   do setup based on pm-runtime
> > > } else {
> > >   do manual setup
> > > }
> > >=20
> > > > Right now, we have a code like below, pushing the initialization in an
> > > > async work and let the probe returning quickly.
> > > >
> > > >         hda_tegra_probe() {
> > > >                 ....
> > >=20
> > > So why don't you do
> > >=20
> > > if (!IS_ENABLED(CONFIG_PM)) {
> > >   do manual clock setup
> > > }
> > >=20
> > > here?
> > 
> > I think that's exactly what Jon and Sameer were proposing, although the
> > discussion started primarily because of the way it was done.
> > 
> > So basically the idea was to do:
> > 
> > 	pm_runtime_enable()
> > 	if (!pm_runtime_enabled())  /* basically !IS_ENABLED(CONFIG_PM) */
> 
> But why is it any better than checking !IS_ENABLED(CONFIG_PM) directly?

I guess the intention here was to avoid the conditional. This may also
have been cargo-culted from a time when we didn't have IS_ENABLED, and
the ifdefery required would've made this a lot worse.

> > 		hda_runtime_resume()
> > 
> > So we're not calling pm_runtime_resume() but rather the driver's
> > implementation of it. This is to avoid duplicating the code, which under
> > some circumstances can be fairly long. Duplicating is also error prone
> > because both instances may not always be in sync.
> > 
> > My understanding is that Takashi had reservations about using this kind
> > of construct because, well, frankly, it looks a little weird.
> 
> Yes, the way it was originally written above was weird, but is checking
> IS_ENABLED(CONFIG_PM) directly really so weird?
> 
> > We'd also likely want to have a similar construct again in the ->remove()
> > callback to make sure we properly power off the device when it is no longer
> > needed.
> 
> Sure.  Again, why don't you make it conditional on IS_ENABLED(CONFIG_PM)?
> 
> > I'm just wondering if perhaps there should be a mechanism in the
> > core to take care of this,
> 
> How exactly?  How's the core going to know what to do when CONFIG_PM is
> disabled?
> 
> > because this is basically something that we'd need to do for every single
> > driver.
> 
> That is not true.  If the device is alwyas "on" to start with, you don't
> need to do anything.  That's the case on many systems.
> 
> > For example, if !CONFIG_PM couldn't the pm_runtime_enable() function be
> > modified to do the above?
> 
> But you'd need to pass a pointer to your hda_runtime_resume() to it at least
> and how's that simpler than using a simple conditional directly?

The idea was, as I was saying below, to reuse dev_pm_ops even if
!CONFIG_PM. So pm_runtime_enable() could be something like this:

	pm_runtime_enable(dev)
	{
		if (!CONFIG_PM)
			if (dev->pm_ops->resume)
				dev->pm_ops->resume(dev);

		...
	}

But that's admittedly somewhat of a stretch. This could of course be
made somewhat nicer by adding an explicit variant, say:

	pm_runtime_enable_foo(dev)
	{
		if (!CONFIG_PM && dev->pm_ops->resume)
			return dev->pm_ops->resume(dev);

		return 0;
	}

Maybe the fact that I couldn't come up with a good name is a good
indication that this is a bad idea...

> > This would be somewhat tricky because drivers
> > usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
> > that would result in an empty structure if !CONFIG_PM, but we could
> > probably work around that by adding a __SET_RUNTIME_PM_OPS that would
> > never be compiled out for this kind of case. Or such drivers could even
> > manually set .runtime_suspend and .runtime_resume to make sure they're
> > always populated.
> > 
> > Another way out of this would be to make sure we never run into the case
> > where runtime PM is disabled. If we always "select PM" on Tegra, then PM
> > should always be available. But is it guaranteed that runtime PM for the
> > devices is functional in that case? From a cursory look at the code it
> > would seem that way.
> 
> If you select PM, then all of the requisite code should be there.

We do this on 64-bit ARM, but there had been some pushback when we had
proposed to do the same thing on 32-bit ARM. I think there were two
concerns:

	1) select PM would force the setting for all platforms on multi-
	   platforms builds

	2) prevents anyone from disabling PM for debugging purposes

1) no longer seems to be valid because Rockchip already selects PM
unconditionally. I'm not sure if 2) is valid anymore either. I haven't
run a build with !PM in a very long time and I wouldn't be surprised if
that was completely broken.

Maybe we need to try this again since a couple of years have elapsed and
runtime PM support on Tegra is much more mature at this point.

> Alternatively, you can make the driver depend on PM.

That's probably the easiest way out, but to be honest I think I'd prefer
to just enforce PM and keep things simple.

Jon, any objections?

Thierry
Thierry Reding Feb. 4, 2019, 8:51 a.m. UTC | #18
On Mon, Feb 04, 2019 at 01:46:20PM +0530, Sameer Pujar wrote:
> 
> On 2/1/2019 4:54 AM, Rafael J. Wysocki wrote:
> > On Thursday, January 31, 2019 3:30:24 PM CET Thierry Reding wrote:
> > > --Pk/CTwBz1VvfPIDp
> > > Content-Type: text/plain; charset=us-ascii
> > > Content-Disposition: inline
> > > Content-Transfer-Encoding: quoted-printable
> > > 
> > > On Thu, Jan 31, 2019 at 01:10:01PM +0100, Rafael J. Wysocki wrote:
> > > > On Thu, Jan 31, 2019 at 12:59 PM Takashi Iwai <tiwai@suse.de> wrote:
> > > > > On Thu, 31 Jan 2019 12:46:54 +0100,
> > > > > Rafael J. Wysocki wrote:
> > > > > > On Thu, Jan 31, 2019 at 12:21 PM Takashi Iwai <tiwai@suse.de> wrote:
> > > > > > > On Thu, 31 Jan 2019 12:05:30 +0100,
> > > > > > > Thierry Reding wrote:
> > > > > > > > On Wed, Jan 30, 2019 at 05:40:42PM +0100, Takashi Iwai wrote:
> > > > > > [cut]
> > > > > > 
> > > > > > > > > If I understand correctly the code, the pm domain is already ac=
> > > tivated
> > > > > > > > > at calling driver's probe callback.
> > > > > > > > As far as I can tell, the domain will also be powered off again a=
> > > fter
> > > > > > > > probe finished, unless the device grabs a runtime PM reference. T=
> > > his is
> > > > > > > > what happens via the dev->pm_domain->sync() call after successful=
> > >   probe
> > > > > > > > of a driver.
> > > > > > > Ah, a good point.  This can be a problem with a probe work like this
> > > > > > > case.
> > > > > > > 
> > > > > > > > It seems to me like it's not a very well defined case what to do =
> > > when a
> > > > > > > > device needs to be powered up but runtime PM is not enabled.
> > > > > > > > 
> > > > > > > > Adding Rafael and linux-pm, maybe they can provide some guidance =
> > > on what
> > > > > > > > to do in these situations.
> > > > > > > > 
> > > > > > > > To summarize, what we're debating here is how to handle powering =
> > > up a
> > > > > > > > device if the pm_runtime infrastructure doesn't take care of it. =
> > > Jon's
> > > > > > > > proposal here was, and we use this elsewhere, to do something lik=
> > > e this:
> > > > > > > >        pm_runtime_enable(dev);
> > > > > > > >        if (!pm_runtime_enabled(dev)) {
> > > > > > > >                err =3D foo_runtime_resume(dev);
> > > > > > > >                if (err < 0)
> > > > > > > >                        goto fail;
> > > > > > > >        }
> > > > > > > > 
> > > > > > > > So basically when runtime PM is not available, we explicitly "res=
> > > ume"
> > > > > > > > the device to power it up.
> > > > > > > > 
> > > > > > > > It seems to me like that's a fairly common problem, so I'm wonder=
> > > ing if
> > > > > > > > there's something that the runtime PM core could do to help with =
> > > this.
> > > > > > > > Or perhaps there's already a way to achieve this that we're all
> > > > > > > > overlooking?
> > > > > > > > 
> > > > > > > > Rafael, any suggestions?
> > > > > > > If any, a common helper would be appreciated, indeed.
> > > > > > I'm not sure that I understand the problem correctly, so let me
> > > > > > restate it the way I understand it.
> > > > > > 
> > > > > > What we're talking about is a driver ->probe() callback.  Runtime PM
> > > > > > is disabled initially and the device is off.  It needs to be powered
> > > > > > up, but the way to do that depends on some configuration of the board
> > > > > > etc., so ideally
> > > > > > 
> > > > > > pm_runtime_enable(dev);
> > > > > > ret =3D pm_runtime_resume(dev);
> > > > > > 
> > > > > > should just work, but the question is what to do if runtime PM doesn't
> > > > > > work as expected.  That is, CONFIG_PM_RUNTIME is unset?  Or something
> > > > > > else?
> > > > > Yes, the question is how to write the code for both with and without
> > > > > CONFIG_PM (or CONFIG_PM_RUNTIME).
> > > > =20
> > > > This basically is about setup, because after that point all should
> > > > just work in both cases.
> > > > =20
> > > > Personally, I would do
> > > > =20
> > > > if (IS_ENABLED(CONFIG_PM)) {
> > > >    do setup based on pm-runtime
> > > > } else {
> > > >    do manual setup
> > > > }
> > > > =20
> > > > > Right now, we have a code like below, pushing the initialization in an
> > > > > async work and let the probe returning quickly.
> > > > > 
> > > > >          hda_tegra_probe() {
> > > > >                  ....
> > > > =20
> > > > So why don't you do
> > > > =20
> > > > if (!IS_ENABLED(CONFIG_PM)) {
> > > >    do manual clock setup
> > > > }
> > > > =20
> > > > here?
> > > I think that's exactly what Jon and Sameer were proposing, although the
> > > discussion started primarily because of the way it was done.
> > > 
> > > So basically the idea was to do:
> > > 
> > > 	pm_runtime_enable()
> > > 	if (!pm_runtime_enabled())  /* basically !IS_ENABLED(CONFIG_PM) */
> > But why is it any better than checking !IS_ENABLED(CONFIG_PM) directly?
> > 
> > > 		hda_runtime_resume()
> > > 
> > > So we're not calling pm_runtime_resume() but rather the driver's
> > > implementation of it. This is to avoid duplicating the code, which under
> > > some circumstances can be fairly long. Duplicating is also error prone
> > > because both instances may not always be in sync.
> > > 
> > > My understanding is that Takashi had reservations about using this kind
> > > of construct because, well, frankly, it looks a little weird.
> > Yes, the way it was originally written above was weird, but is checking
> > IS_ENABLED(CONFIG_PM) directly really so weird?
> > 
> > > We'd also likely want to have a similar construct again in the ->remove()
> > > callback to make sure we properly power off the device when it is no longer
> > > needed.
> > Sure.  Again, why don't you make it conditional on IS_ENABLED(CONFIG_PM)?
> > 
> > > I'm just wondering if perhaps there should be a mechanism in the
> > > core to take care of this,
> > How exactly?  How's the core going to know what to do when CONFIG_PM is
> > disabled?
> > 
> > > because this is basically something that we'd need to do for every single
> > > driver.
> > That is not true.  If the device is alwyas "on" to start with, you don't
> > need to do anything.  That's the case on many systems.
> > 
> > > For example, if !CONFIG_PM couldn't the pm_runtime_enable() function be
> > > modified to do the above?
> > But you'd need to pass a pointer to your hda_runtime_resume() to it at least
> > and how's that simpler than using a simple conditional directly?
> > 
> > > This would be somewhat tricky because drivers
> > > usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
> > > that would result in an empty structure if !CONFIG_PM, but we could
> > > probably work around that by adding a __SET_RUNTIME_PM_OPS that would
> > > never be compiled out for this kind of case. Or such drivers could even
> > > manually set .runtime_suspend and .runtime_resume to make sure they're
> > > always populated.
> > > 
> > > Another way out of this would be to make sure we never run into the case
> > > where runtime PM is disabled. If we always "select PM" on Tegra, then PM
> > > should always be available. But is it guaranteed that runtime PM for the
> > > devices is functional in that case? From a cursory look at the code it
> > > would seem that way.
> > If you select PM, then all of the requisite code should be there.
> > 
> > Alternatively, you can make the driver depend on PM.
> Objective is to have things working with or without CONFIG_PM enabled.
> From previous comments and discussions it appears that there is mixed
> response
> for calling hda_tegra_runtime_resume() or runtime PM APIs in probe() call.
> Need
> to have consensus regarding the best practice to be followed, which would
> eventually
> can be used in other drivers too.
> 
> Rafael is suggesting to use CONFIG_PM check to do manual setup or runtime PM
> setup in probe,
> which would bring back the earlier above mentioned concern.
> 
> if (IS_ENABLED(CONFIG_PM)) {
> do setup based on pm-runtime
> } else {
>     do manual setup
> }
> Both if/else might end up doing the same here.
> Do we really need CONFIG_PM check here?
> 
> Instead does below proposal appear fine?
> 
> probe() {
>     hda_tegra_enable_clock();
> }
> 
> probe_work() {
>     /* hda setup */
>     . . .
>     pm_runtime_set_active(); /* initial state as active */
>     pm_runtime_enable();
>     return;
> }
> 
> remove() {
>     pm_runtime_disable();
>     if (!pm_runtime_status_suspended())
>         hda_tegra_runtime_suspend(); /* takes care of both CONFIG_PM
> enable/disable case */
> }
> 
> One of the other concern was, remove() and probe() do not appear to be in
> sync, because in probe() hda_tegra_enable_clock()
> is called and in remove() there is hda_tegra_runtime_suspend() to
> effectively disable clock.
> IMO, this should be ok since it can avoid duplication and proper comment can
> be added here for clarity.
> Alternatively we can call hda_tegra_runtime_resume() in probe()
> unconditionally to avoid confusion.
> 
> Another point Thierry mentioned was, after successful probe() power-domain
> would be turned OFF. It seems Rafael had a different
> view. I am little confused here. Kindly clarify if above proposal seems
> fine.

We're wasting an awful lot of time over the discussion of something that
I think is of questionable usefulness. I propose we do the below and can
forget about this once and for all.

Thierry

--- >8 ---
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 7f3b83e0d324..51a8fa3566ef 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -10,6 +10,7 @@ menuconfig ARCH_TEGRA
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select PINCTRL
+	select PM
 	select PM_OPP
 	select ARCH_HAS_RESET_CONTROLLER
 	select RESET_CONTROLLER
Jon Hunter Feb. 4, 2019, 9:53 a.m. UTC | #19
On 04/02/2019 08:45, Thierry Reding wrote:

...

> The idea was, as I was saying below, to reuse dev_pm_ops even if
> !CONFIG_PM. So pm_runtime_enable() could be something like this:
> 
> 	pm_runtime_enable(dev)
> 	{
> 		if (!CONFIG_PM)
> 			if (dev->pm_ops->resume)
> 				dev->pm_ops->resume(dev);
> 
> 		...
> 	}
> 
> But that's admittedly somewhat of a stretch. This could of course be
> made somewhat nicer by adding an explicit variant, say:
> 
> 	pm_runtime_enable_foo(dev)
> 	{
> 		if (!CONFIG_PM && dev->pm_ops->resume)
> 			return dev->pm_ops->resume(dev);
> 
> 		return 0;
> 	}
> 
> Maybe the fact that I couldn't come up with a good name is a good
> indication that this is a bad idea...

How about some new APIs called ...

pm_runtime_enable_get()
pm_runtime_enable_get_sync()
pm_runtime_put_disable() (implies a put_sync)

... and in these APIs we add ...

pm_runtime_enable_get(dev)
{
	if (!CONFIG_PM && dev->pm_ops->resume)
		return dev->pm_ops->resume(dev);

	pm_runtime_enable(dev);
	return pm_runtime_get(dev);
}

>>> This would be somewhat tricky because drivers
>>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
>>> that would result in an empty structure if !CONFIG_PM, but we could
>>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
>>> never be compiled out for this kind of case. Or such drivers could even
>>> manually set .runtime_suspend and .runtime_resume to make sure they're
>>> always populated.
>>>
>>> Another way out of this would be to make sure we never run into the case
>>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
>>> should always be available. But is it guaranteed that runtime PM for the
>>> devices is functional in that case? From a cursory look at the code it
>>> would seem that way.
>>
>> If you select PM, then all of the requisite code should be there.
> 
> We do this on 64-bit ARM, but there had been some pushback when we had
> proposed to do the same thing on 32-bit ARM. I think there were two
> concerns:
> 
> 	1) select PM would force the setting for all platforms on multi-
> 	   platforms builds
> 
> 	2) prevents anyone from disabling PM for debugging purposes
> 
> 1) no longer seems to be valid because Rockchip already selects PM
> unconditionally. I'm not sure if 2) is valid anymore either. I haven't
> run a build with !PM in a very long time and I wouldn't be surprised if
> that was completely broken.
> 
> Maybe we need to try this again since a couple of years have elapsed and
> runtime PM support on Tegra is much more mature at this point.
> 
>> Alternatively, you can make the driver depend on PM.
> 
> That's probably the easiest way out, but to be honest I think I'd prefer
> to just enforce PM and keep things simple.
> 
> Jon, any objections?

None, but seems overkill just for this case.

Cheers
Jon
Jon Hunter Feb. 4, 2019, 10:04 a.m. UTC | #20
On 04/02/2019 08:16, Sameer Pujar wrote:

...

> Objective is to have things working with or without CONFIG_PM enabled.
> From previous comments and discussions it appears that there is mixed
> response
> for calling hda_tegra_runtime_resume() or runtime PM APIs in probe()
> call. Need
> to have consensus regarding the best practice to be followed, which
> would eventually
> can be used in other drivers too.
> 
> Rafael is suggesting to use CONFIG_PM check to do manual setup or
> runtime PM setup in probe,
> which would bring back the earlier above mentioned concern.
> 
> if (IS_ENABLED(CONFIG_PM)) {
> do setup based on pm-runtime
> } else {
>     do manual setup
> }
> Both if/else might end up doing the same here.
> Do we really need CONFIG_PM check here?
> 
> Instead does below proposal appear fine?
> 
> probe() {
>     hda_tegra_enable_clock();
> }
> 
> probe_work() {
>     /* hda setup */
>     . . .
>     pm_runtime_set_active(); /* initial state as active */
>     pm_runtime_enable();
>     return;
> }

I believe that this still does not work, because if there is a
power-domain that needs to be turned on, this does not guarantee this.
So I think that you need to call pm_runtime_get ...

 probe() {
 	if (!IS_ENABLED(CONFIG_PM))
 		hda_tegra_enable_clock();
 }


 probe_work() {
    	/* hda setup */
    	. . .
	pm_runtime_enable();
	pm_runtime_get_sync();
	return;
 }

The alternative here could just be ...

 probe() {
	pm_runtime_enable();
 	if (!pm_runtime_enabled())
 		ret = hda_tegra_enable_clock();
	else
		ret = pm_runtime_get_sync();

	if (ret < 0) {
		...
	}
 }

Very similar to what I was saying to begin with but not call the
pm_runtime_resume handler directly. Which I believe was Iwai-san's dislike.

Cheers
Jon
Takashi Iwai Feb. 4, 2019, 10:13 a.m. UTC | #21
On Mon, 04 Feb 2019 11:04:50 +0100,
Jon Hunter wrote:
> 
> 
> On 04/02/2019 08:16, Sameer Pujar wrote:
> 
> ...
> 
> > Objective is to have things working with or without CONFIG_PM enabled.
> > From previous comments and discussions it appears that there is mixed
> > response
> > for calling hda_tegra_runtime_resume() or runtime PM APIs in probe()
> > call. Need
> > to have consensus regarding the best practice to be followed, which
> > would eventually
> > can be used in other drivers too.
> > 
> > Rafael is suggesting to use CONFIG_PM check to do manual setup or
> > runtime PM setup in probe,
> > which would bring back the earlier above mentioned concern.
> > 
> > if (IS_ENABLED(CONFIG_PM)) {
> > do setup based on pm-runtime
> > } else {
> >     do manual setup
> > }
> > Both if/else might end up doing the same here.
> > Do we really need CONFIG_PM check here?
> > 
> > Instead does below proposal appear fine?
> > 
> > probe() {
> >     hda_tegra_enable_clock();
> > }
> > 
> > probe_work() {
> >     /* hda setup */
> >     . . .
> >     pm_runtime_set_active(); /* initial state as active */
> >     pm_runtime_enable();
> >     return;
> > }
> 
> I believe that this still does not work, because if there is a
> power-domain that needs to be turned on, this does not guarantee this.
> So I think that you need to call pm_runtime_get ...
> 
>  probe() {
>  	if (!IS_ENABLED(CONFIG_PM))
>  		hda_tegra_enable_clock();
>  }
> 
> 
>  probe_work() {
>     	/* hda setup */
>     	. . .
> 	pm_runtime_enable();
> 	pm_runtime_get_sync();
> 	return;
>  }
> 
> The alternative here could just be ...
> 
>  probe() {
> 	pm_runtime_enable();
>  	if (!pm_runtime_enabled())
>  		ret = hda_tegra_enable_clock();
> 	else
> 		ret = pm_runtime_get_sync();
> 
> 	if (ret < 0) {
> 		...
> 	}
>  }
> 
> Very similar to what I was saying to begin with but not call the
> pm_runtime_resume handler directly. Which I believe was Iwai-san's dislike.

Yes, exactly, what bothered me was really a nuance: calling
hda_tegra_runtime_resume() there makes the code misleading (or
confusing) as if the runtime PM were mandatory.

I hoped there could be some standard idiom for this expression, but
apparently there isn't any, so far...

Obviously the easiest option is to enforce the dependency on
CONFIG_PM.  Would there be any platform that needs to run without PM,
practically seen...?

But, now after lengthy discussions and the clarification of the
current situation, I have no strong opinion on this any longer.
So I leave the decision to you guys, and I'll apply it as-is.


thanks,

Takashi
Thierry Reding Feb. 4, 2019, 11:05 a.m. UTC | #22
On Mon, Feb 04, 2019 at 09:53:32AM +0000, Jon Hunter wrote:
> 
> 
> On 04/02/2019 08:45, Thierry Reding wrote:
> 
> ...
> 
> > The idea was, as I was saying below, to reuse dev_pm_ops even if
> > !CONFIG_PM. So pm_runtime_enable() could be something like this:
> > 
> > 	pm_runtime_enable(dev)
> > 	{
> > 		if (!CONFIG_PM)
> > 			if (dev->pm_ops->resume)
> > 				dev->pm_ops->resume(dev);
> > 
> > 		...
> > 	}
> > 
> > But that's admittedly somewhat of a stretch. This could of course be
> > made somewhat nicer by adding an explicit variant, say:
> > 
> > 	pm_runtime_enable_foo(dev)
> > 	{
> > 		if (!CONFIG_PM && dev->pm_ops->resume)
> > 			return dev->pm_ops->resume(dev);
> > 
> > 		return 0;
> > 	}
> > 
> > Maybe the fact that I couldn't come up with a good name is a good
> > indication that this is a bad idea...
> 
> How about some new APIs called ...
> 
> pm_runtime_enable_get()
> pm_runtime_enable_get_sync()
> pm_runtime_put_disable() (implies a put_sync)
> 
> ... and in these APIs we add ...
> 
> pm_runtime_enable_get(dev)
> {
> 	if (!CONFIG_PM && dev->pm_ops->resume)
> 		return dev->pm_ops->resume(dev);
> 
> 	pm_runtime_enable(dev);
> 	return pm_runtime_get(dev);
> }

Yeah, those sound sensible. I'm still a bit torn between this and just
enforcing PM. At least on the display side I think we already require PM
and with all the power domain work that you did we'd be much better off
if we could just get rid of the !PM workarounds.

> >>> This would be somewhat tricky because drivers
> >>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
> >>> that would result in an empty structure if !CONFIG_PM, but we could
> >>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
> >>> never be compiled out for this kind of case. Or such drivers could even
> >>> manually set .runtime_suspend and .runtime_resume to make sure they're
> >>> always populated.
> >>>
> >>> Another way out of this would be to make sure we never run into the case
> >>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
> >>> should always be available. But is it guaranteed that runtime PM for the
> >>> devices is functional in that case? From a cursory look at the code it
> >>> would seem that way.
> >>
> >> If you select PM, then all of the requisite code should be there.
> > 
> > We do this on 64-bit ARM, but there had been some pushback when we had
> > proposed to do the same thing on 32-bit ARM. I think there were two
> > concerns:
> > 
> > 	1) select PM would force the setting for all platforms on multi-
> > 	   platforms builds
> > 
> > 	2) prevents anyone from disabling PM for debugging purposes
> > 
> > 1) no longer seems to be valid because Rockchip already selects PM
> > unconditionally. I'm not sure if 2) is valid anymore either. I haven't
> > run a build with !PM in a very long time and I wouldn't be surprised if
> > that was completely broken.
> > 
> > Maybe we need to try this again since a couple of years have elapsed and
> > runtime PM support on Tegra is much more mature at this point.
> > 
> >> Alternatively, you can make the driver depend on PM.
> > 
> > That's probably the easiest way out, but to be honest I think I'd prefer
> > to just enforce PM and keep things simple.
> > 
> > Jon, any objections?
> 
> None, but seems overkill just for this case.

But that's precisely the point. It's not just about this case. We've
already got some drivers where we do a similar dance just to be able to
support the, let's admit it, exotic case where somebody turns off PM. I
think supporting !PM might have made sense at a point where we had no
support for power management at all. But I think we've come a long way
since then, and while we may still have some ways to go in some areas,
we do fairly decent runtime PM most of the time, to the point where I no
longer see any benefits in !PM.

Thierry
Dmitry Osipenko Feb. 4, 2019, 12:03 p.m. UTC | #23
04.02.2019 14:05, Thierry Reding пишет:
> On Mon, Feb 04, 2019 at 09:53:32AM +0000, Jon Hunter wrote:
>>
>>
>> On 04/02/2019 08:45, Thierry Reding wrote:
>>
>> ...
>>
>>> The idea was, as I was saying below, to reuse dev_pm_ops even if
>>> !CONFIG_PM. So pm_runtime_enable() could be something like this:
>>>
>>> 	pm_runtime_enable(dev)
>>> 	{
>>> 		if (!CONFIG_PM)
>>> 			if (dev->pm_ops->resume)
>>> 				dev->pm_ops->resume(dev);
>>>
>>> 		...
>>> 	}
>>>
>>> But that's admittedly somewhat of a stretch. This could of course be
>>> made somewhat nicer by adding an explicit variant, say:
>>>
>>> 	pm_runtime_enable_foo(dev)
>>> 	{
>>> 		if (!CONFIG_PM && dev->pm_ops->resume)
>>> 			return dev->pm_ops->resume(dev);
>>>
>>> 		return 0;
>>> 	}
>>>
>>> Maybe the fact that I couldn't come up with a good name is a good
>>> indication that this is a bad idea...
>>
>> How about some new APIs called ...
>>
>> pm_runtime_enable_get()
>> pm_runtime_enable_get_sync()
>> pm_runtime_put_disable() (implies a put_sync)
>>
>> ... and in these APIs we add ...
>>
>> pm_runtime_enable_get(dev)
>> {
>> 	if (!CONFIG_PM && dev->pm_ops->resume)
>> 		return dev->pm_ops->resume(dev);
>>
>> 	pm_runtime_enable(dev);
>> 	return pm_runtime_get(dev);
>> }
> 
> Yeah, those sound sensible. I'm still a bit torn between this and just
> enforcing PM. At least on the display side I think we already require PM
> and with all the power domain work that you did we'd be much better off
> if we could just get rid of the !PM workarounds.
> 
>>>>> This would be somewhat tricky because drivers
>>>>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
>>>>> that would result in an empty structure if !CONFIG_PM, but we could
>>>>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
>>>>> never be compiled out for this kind of case. Or such drivers could even
>>>>> manually set .runtime_suspend and .runtime_resume to make sure they're
>>>>> always populated.
>>>>>
>>>>> Another way out of this would be to make sure we never run into the case
>>>>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
>>>>> should always be available. But is it guaranteed that runtime PM for the
>>>>> devices is functional in that case? From a cursory look at the code it
>>>>> would seem that way.
>>>>
>>>> If you select PM, then all of the requisite code should be there.
>>>
>>> We do this on 64-bit ARM, but there had been some pushback when we had
>>> proposed to do the same thing on 32-bit ARM. I think there were two
>>> concerns:
>>>
>>> 	1) select PM would force the setting for all platforms on multi-
>>> 	   platforms builds
>>>
>>> 	2) prevents anyone from disabling PM for debugging purposes
>>>
>>> 1) no longer seems to be valid because Rockchip already selects PM
>>> unconditionally. I'm not sure if 2) is valid anymore either. I haven't
>>> run a build with !PM in a very long time and I wouldn't be surprised if
>>> that was completely broken.
>>>
>>> Maybe we need to try this again since a couple of years have elapsed and
>>> runtime PM support on Tegra is much more mature at this point.
>>>
>>>> Alternatively, you can make the driver depend on PM.
>>>
>>> That's probably the easiest way out, but to be honest I think I'd prefer
>>> to just enforce PM and keep things simple.
>>>
>>> Jon, any objections?
>>
>> None, but seems overkill just for this case.
> 
> But that's precisely the point. It's not just about this case. We've
> already got some drivers where we do a similar dance just to be able to
> support the, let's admit it, exotic case where somebody turns off PM. I
> think supporting !PM might have made sense at a point where we had no
> support for power management at all. But I think we've come a long way
> since then, and while we may still have some ways to go in some areas,
> we do fairly decent runtime PM most of the time, to the point where I no
> longer see any benefits in !PM.

I'm requesting PM_DEBUG_ALWAYS_ON option then! Disabling PM is a useful debug feature, it can't just go away.
Thierry Reding Feb. 4, 2019, 2 p.m. UTC | #24
On Mon, Feb 04, 2019 at 03:03:49PM +0300, Dmitry Osipenko wrote:
> 04.02.2019 14:05, Thierry Reding пишет:
> > On Mon, Feb 04, 2019 at 09:53:32AM +0000, Jon Hunter wrote:
> >>
> >>
> >> On 04/02/2019 08:45, Thierry Reding wrote:
> >>
> >> ...
> >>
> >>> The idea was, as I was saying below, to reuse dev_pm_ops even if
> >>> !CONFIG_PM. So pm_runtime_enable() could be something like this:
> >>>
> >>> 	pm_runtime_enable(dev)
> >>> 	{
> >>> 		if (!CONFIG_PM)
> >>> 			if (dev->pm_ops->resume)
> >>> 				dev->pm_ops->resume(dev);
> >>>
> >>> 		...
> >>> 	}
> >>>
> >>> But that's admittedly somewhat of a stretch. This could of course be
> >>> made somewhat nicer by adding an explicit variant, say:
> >>>
> >>> 	pm_runtime_enable_foo(dev)
> >>> 	{
> >>> 		if (!CONFIG_PM && dev->pm_ops->resume)
> >>> 			return dev->pm_ops->resume(dev);
> >>>
> >>> 		return 0;
> >>> 	}
> >>>
> >>> Maybe the fact that I couldn't come up with a good name is a good
> >>> indication that this is a bad idea...
> >>
> >> How about some new APIs called ...
> >>
> >> pm_runtime_enable_get()
> >> pm_runtime_enable_get_sync()
> >> pm_runtime_put_disable() (implies a put_sync)
> >>
> >> ... and in these APIs we add ...
> >>
> >> pm_runtime_enable_get(dev)
> >> {
> >> 	if (!CONFIG_PM && dev->pm_ops->resume)
> >> 		return dev->pm_ops->resume(dev);
> >>
> >> 	pm_runtime_enable(dev);
> >> 	return pm_runtime_get(dev);
> >> }
> > 
> > Yeah, those sound sensible. I'm still a bit torn between this and just
> > enforcing PM. At least on the display side I think we already require PM
> > and with all the power domain work that you did we'd be much better off
> > if we could just get rid of the !PM workarounds.
> > 
> >>>>> This would be somewhat tricky because drivers
> >>>>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
> >>>>> that would result in an empty structure if !CONFIG_PM, but we could
> >>>>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
> >>>>> never be compiled out for this kind of case. Or such drivers could even
> >>>>> manually set .runtime_suspend and .runtime_resume to make sure they're
> >>>>> always populated.
> >>>>>
> >>>>> Another way out of this would be to make sure we never run into the case
> >>>>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
> >>>>> should always be available. But is it guaranteed that runtime PM for the
> >>>>> devices is functional in that case? From a cursory look at the code it
> >>>>> would seem that way.
> >>>>
> >>>> If you select PM, then all of the requisite code should be there.
> >>>
> >>> We do this on 64-bit ARM, but there had been some pushback when we had
> >>> proposed to do the same thing on 32-bit ARM. I think there were two
> >>> concerns:
> >>>
> >>> 	1) select PM would force the setting for all platforms on multi-
> >>> 	   platforms builds
> >>>
> >>> 	2) prevents anyone from disabling PM for debugging purposes
> >>>
> >>> 1) no longer seems to be valid because Rockchip already selects PM
> >>> unconditionally. I'm not sure if 2) is valid anymore either. I haven't
> >>> run a build with !PM in a very long time and I wouldn't be surprised if
> >>> that was completely broken.
> >>>
> >>> Maybe we need to try this again since a couple of years have elapsed and
> >>> runtime PM support on Tegra is much more mature at this point.
> >>>
> >>>> Alternatively, you can make the driver depend on PM.
> >>>
> >>> That's probably the easiest way out, but to be honest I think I'd prefer
> >>> to just enforce PM and keep things simple.
> >>>
> >>> Jon, any objections?
> >>
> >> None, but seems overkill just for this case.
> > 
> > But that's precisely the point. It's not just about this case. We've
> > already got some drivers where we do a similar dance just to be able to
> > support the, let's admit it, exotic case where somebody turns off PM. I
> > think supporting !PM might have made sense at a point where we had no
> > support for power management at all. But I think we've come a long way
> > since then, and while we may still have some ways to go in some areas,
> > we do fairly decent runtime PM most of the time, to the point where I no
> > longer see any benefits in !PM.
> 
> I'm requesting PM_DEBUG_ALWAYS_ON option then! Disabling PM is a
> useful debug feature, it can't just go away. 

What is it about disabling PM that you consider useful? I can understand
why you'd want that option if power management is broken, but as far as
I can tell, power management on Tegra is in pretty good state, and it's
more likely that !PM would actually be broken (though I haven't built a
configuration like that in a couple of years, so I'm speculating). We
already can't disable PM on 64-bit ARM, so I don't understand why 32-bit
ARM should be treated any differently.

Thierry
Dmitry Osipenko Feb. 4, 2019, 2:28 p.m. UTC | #25
04.02.2019 17:00, Thierry Reding пишет:
> On Mon, Feb 04, 2019 at 03:03:49PM +0300, Dmitry Osipenko wrote:
>> 04.02.2019 14:05, Thierry Reding пишет:
>>> On Mon, Feb 04, 2019 at 09:53:32AM +0000, Jon Hunter wrote:
>>>>
>>>>
>>>> On 04/02/2019 08:45, Thierry Reding wrote:
>>>>
>>>> ...
>>>>
>>>>> The idea was, as I was saying below, to reuse dev_pm_ops even if
>>>>> !CONFIG_PM. So pm_runtime_enable() could be something like this:
>>>>>
>>>>> 	pm_runtime_enable(dev)
>>>>> 	{
>>>>> 		if (!CONFIG_PM)
>>>>> 			if (dev->pm_ops->resume)
>>>>> 				dev->pm_ops->resume(dev);
>>>>>
>>>>> 		...
>>>>> 	}
>>>>>
>>>>> But that's admittedly somewhat of a stretch. This could of course be
>>>>> made somewhat nicer by adding an explicit variant, say:
>>>>>
>>>>> 	pm_runtime_enable_foo(dev)
>>>>> 	{
>>>>> 		if (!CONFIG_PM && dev->pm_ops->resume)
>>>>> 			return dev->pm_ops->resume(dev);
>>>>>
>>>>> 		return 0;
>>>>> 	}
>>>>>
>>>>> Maybe the fact that I couldn't come up with a good name is a good
>>>>> indication that this is a bad idea...
>>>>
>>>> How about some new APIs called ...
>>>>
>>>> pm_runtime_enable_get()
>>>> pm_runtime_enable_get_sync()
>>>> pm_runtime_put_disable() (implies a put_sync)
>>>>
>>>> ... and in these APIs we add ...
>>>>
>>>> pm_runtime_enable_get(dev)
>>>> {
>>>> 	if (!CONFIG_PM && dev->pm_ops->resume)
>>>> 		return dev->pm_ops->resume(dev);
>>>>
>>>> 	pm_runtime_enable(dev);
>>>> 	return pm_runtime_get(dev);
>>>> }
>>>
>>> Yeah, those sound sensible. I'm still a bit torn between this and just
>>> enforcing PM. At least on the display side I think we already require PM
>>> and with all the power domain work that you did we'd be much better off
>>> if we could just get rid of the !PM workarounds.
>>>
>>>>>>> This would be somewhat tricky because drivers
>>>>>>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
>>>>>>> that would result in an empty structure if !CONFIG_PM, but we could
>>>>>>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
>>>>>>> never be compiled out for this kind of case. Or such drivers could even
>>>>>>> manually set .runtime_suspend and .runtime_resume to make sure they're
>>>>>>> always populated.
>>>>>>>
>>>>>>> Another way out of this would be to make sure we never run into the case
>>>>>>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
>>>>>>> should always be available. But is it guaranteed that runtime PM for the
>>>>>>> devices is functional in that case? From a cursory look at the code it
>>>>>>> would seem that way.
>>>>>>
>>>>>> If you select PM, then all of the requisite code should be there.
>>>>>
>>>>> We do this on 64-bit ARM, but there had been some pushback when we had
>>>>> proposed to do the same thing on 32-bit ARM. I think there were two
>>>>> concerns:
>>>>>
>>>>> 	1) select PM would force the setting for all platforms on multi-
>>>>> 	   platforms builds
>>>>>
>>>>> 	2) prevents anyone from disabling PM for debugging purposes
>>>>>
>>>>> 1) no longer seems to be valid because Rockchip already selects PM
>>>>> unconditionally. I'm not sure if 2) is valid anymore either. I haven't
>>>>> run a build with !PM in a very long time and I wouldn't be surprised if
>>>>> that was completely broken.
>>>>>
>>>>> Maybe we need to try this again since a couple of years have elapsed and
>>>>> runtime PM support on Tegra is much more mature at this point.
>>>>>
>>>>>> Alternatively, you can make the driver depend on PM.
>>>>>
>>>>> That's probably the easiest way out, but to be honest I think I'd prefer
>>>>> to just enforce PM and keep things simple.
>>>>>
>>>>> Jon, any objections?
>>>>
>>>> None, but seems overkill just for this case.
>>>
>>> But that's precisely the point. It's not just about this case. We've
>>> already got some drivers where we do a similar dance just to be able to
>>> support the, let's admit it, exotic case where somebody turns off PM. I
>>> think supporting !PM might have made sense at a point where we had no
>>> support for power management at all. But I think we've come a long way
>>> since then, and while we may still have some ways to go in some areas,
>>> we do fairly decent runtime PM most of the time, to the point where I no
>>> longer see any benefits in !PM.
>>
>> I'm requesting PM_DEBUG_ALWAYS_ON option then! Disabling PM is a
>> useful debug feature, it can't just go away. 
> 
> What is it about disabling PM that you consider useful? I can understand
> why you'd want that option if power management is broken, but as far as
> I can tell, power management on Tegra is in pretty good state, and it's
> more likely that !PM would actually be broken (though I haven't built a
> configuration like that in a couple of years, so I'm speculating). We
> already can't disable PM on 64-bit ARM, so I don't understand why 32-bit
> ARM should be treated any differently.

Yes, I want an option for debugging of a broken PM. It doesn't matter that there are no known PM-related issues on Tegra today, it could become a problem tomorrow. Probably a kernel boot parameter like pm_debug_always_on would suit even better here. 

Or maybe PM API already provides such debug options and I'm just not aware about them?

Do you know what's the exact reason for ARM64 to not support !PM?
Thierry Reding Feb. 4, 2019, 4:17 p.m. UTC | #26
On Mon, Feb 04, 2019 at 05:28:23PM +0300, Dmitry Osipenko wrote:
> 04.02.2019 17:00, Thierry Reding пишет:
> > On Mon, Feb 04, 2019 at 03:03:49PM +0300, Dmitry Osipenko wrote:
> >> 04.02.2019 14:05, Thierry Reding пишет:
> >>> On Mon, Feb 04, 2019 at 09:53:32AM +0000, Jon Hunter wrote:
> >>>>
> >>>>
> >>>> On 04/02/2019 08:45, Thierry Reding wrote:
> >>>>
> >>>> ...
> >>>>
> >>>>> The idea was, as I was saying below, to reuse dev_pm_ops even if
> >>>>> !CONFIG_PM. So pm_runtime_enable() could be something like this:
> >>>>>
> >>>>> 	pm_runtime_enable(dev)
> >>>>> 	{
> >>>>> 		if (!CONFIG_PM)
> >>>>> 			if (dev->pm_ops->resume)
> >>>>> 				dev->pm_ops->resume(dev);
> >>>>>
> >>>>> 		...
> >>>>> 	}
> >>>>>
> >>>>> But that's admittedly somewhat of a stretch. This could of course be
> >>>>> made somewhat nicer by adding an explicit variant, say:
> >>>>>
> >>>>> 	pm_runtime_enable_foo(dev)
> >>>>> 	{
> >>>>> 		if (!CONFIG_PM && dev->pm_ops->resume)
> >>>>> 			return dev->pm_ops->resume(dev);
> >>>>>
> >>>>> 		return 0;
> >>>>> 	}
> >>>>>
> >>>>> Maybe the fact that I couldn't come up with a good name is a good
> >>>>> indication that this is a bad idea...
> >>>>
> >>>> How about some new APIs called ...
> >>>>
> >>>> pm_runtime_enable_get()
> >>>> pm_runtime_enable_get_sync()
> >>>> pm_runtime_put_disable() (implies a put_sync)
> >>>>
> >>>> ... and in these APIs we add ...
> >>>>
> >>>> pm_runtime_enable_get(dev)
> >>>> {
> >>>> 	if (!CONFIG_PM && dev->pm_ops->resume)
> >>>> 		return dev->pm_ops->resume(dev);
> >>>>
> >>>> 	pm_runtime_enable(dev);
> >>>> 	return pm_runtime_get(dev);
> >>>> }
> >>>
> >>> Yeah, those sound sensible. I'm still a bit torn between this and just
> >>> enforcing PM. At least on the display side I think we already require PM
> >>> and with all the power domain work that you did we'd be much better off
> >>> if we could just get rid of the !PM workarounds.
> >>>
> >>>>>>> This would be somewhat tricky because drivers
> >>>>>>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
> >>>>>>> that would result in an empty structure if !CONFIG_PM, but we could
> >>>>>>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
> >>>>>>> never be compiled out for this kind of case. Or such drivers could even
> >>>>>>> manually set .runtime_suspend and .runtime_resume to make sure they're
> >>>>>>> always populated.
> >>>>>>>
> >>>>>>> Another way out of this would be to make sure we never run into the case
> >>>>>>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
> >>>>>>> should always be available. But is it guaranteed that runtime PM for the
> >>>>>>> devices is functional in that case? From a cursory look at the code it
> >>>>>>> would seem that way.
> >>>>>>
> >>>>>> If you select PM, then all of the requisite code should be there.
> >>>>>
> >>>>> We do this on 64-bit ARM, but there had been some pushback when we had
> >>>>> proposed to do the same thing on 32-bit ARM. I think there were two
> >>>>> concerns:
> >>>>>
> >>>>> 	1) select PM would force the setting for all platforms on multi-
> >>>>> 	   platforms builds
> >>>>>
> >>>>> 	2) prevents anyone from disabling PM for debugging purposes
> >>>>>
> >>>>> 1) no longer seems to be valid because Rockchip already selects PM
> >>>>> unconditionally. I'm not sure if 2) is valid anymore either. I haven't
> >>>>> run a build with !PM in a very long time and I wouldn't be surprised if
> >>>>> that was completely broken.
> >>>>>
> >>>>> Maybe we need to try this again since a couple of years have elapsed and
> >>>>> runtime PM support on Tegra is much more mature at this point.
> >>>>>
> >>>>>> Alternatively, you can make the driver depend on PM.
> >>>>>
> >>>>> That's probably the easiest way out, but to be honest I think I'd prefer
> >>>>> to just enforce PM and keep things simple.
> >>>>>
> >>>>> Jon, any objections?
> >>>>
> >>>> None, but seems overkill just for this case.
> >>>
> >>> But that's precisely the point. It's not just about this case. We've
> >>> already got some drivers where we do a similar dance just to be able to
> >>> support the, let's admit it, exotic case where somebody turns off PM. I
> >>> think supporting !PM might have made sense at a point where we had no
> >>> support for power management at all. But I think we've come a long way
> >>> since then, and while we may still have some ways to go in some areas,
> >>> we do fairly decent runtime PM most of the time, to the point where I no
> >>> longer see any benefits in !PM.
> >>
> >> I'm requesting PM_DEBUG_ALWAYS_ON option then! Disabling PM is a
> >> useful debug feature, it can't just go away. 
> > 
> > What is it about disabling PM that you consider useful? I can understand
> > why you'd want that option if power management is broken, but as far as
> > I can tell, power management on Tegra is in pretty good state, and it's
> > more likely that !PM would actually be broken (though I haven't built a
> > configuration like that in a couple of years, so I'm speculating). We
> > already can't disable PM on 64-bit ARM, so I don't understand why 32-bit
> > ARM should be treated any differently.
> 
> Yes, I want an option for debugging of a broken PM. It doesn't matter
> that there are no known PM-related issues on Tegra today, it could
> become a problem tomorrow. Probably a kernel boot parameter like
> pm_debug_always_on would suit even better here. 
> 
> Or maybe PM API already provides such debug options and I'm just not
> aware about them?

I'm not sure I understand what you're trying to do. If you want to use
!PM as a way to debug broken PM, how would that help? Presumably if you
disable !PM then the problem would be gone? In other words, in order to
reproduce a PM related issue don't you have to enable PM first?

I'm not aware of an alternate mechanism to force PM to off once built
into the kernel.

> Do you know what's the exact reason for ARM64 to not support !PM?

There's no reason per se not to support PM. It's just that at the time
we made the decision that we didn't want to. I vaguely remember that we
tried to do the same thing for 32-bit ARM, but at the time we would've
been the only platform to select PM, and that would've meant enabling
PM for all subarchitectures and therefore forcing PM in multi-platform
builds. Today if you build multi-platform kernels, at least Rockchip
will also forcibly enable PM for everyone.

I think you may also have objected at the time for similar reasons. But
this was a long time ago (at least 2 to 3 years I would guess) and much
has changed since then. Power management has gotten a lot better on
Tegra, to the point where we actually need it in order to properly
function. For example, Tegra DRM is not going to work with !PM because
we rely on runtime PM while disabling and enabling display pipelines.

Thierry
Dmitry Osipenko Feb. 4, 2019, 6:46 p.m. UTC | #27
04.02.2019 19:17, Thierry Reding пишет:
> On Mon, Feb 04, 2019 at 05:28:23PM +0300, Dmitry Osipenko wrote:
>> 04.02.2019 17:00, Thierry Reding пишет:
>>> On Mon, Feb 04, 2019 at 03:03:49PM +0300, Dmitry Osipenko wrote:
>>>> 04.02.2019 14:05, Thierry Reding пишет:
>>>>> On Mon, Feb 04, 2019 at 09:53:32AM +0000, Jon Hunter wrote:
>>>>>>
>>>>>>
>>>>>> On 04/02/2019 08:45, Thierry Reding wrote:
>>>>>>
>>>>>> ...
>>>>>>
>>>>>>> The idea was, as I was saying below, to reuse dev_pm_ops even if
>>>>>>> !CONFIG_PM. So pm_runtime_enable() could be something like this:
>>>>>>>
>>>>>>> 	pm_runtime_enable(dev)
>>>>>>> 	{
>>>>>>> 		if (!CONFIG_PM)
>>>>>>> 			if (dev->pm_ops->resume)
>>>>>>> 				dev->pm_ops->resume(dev);
>>>>>>>
>>>>>>> 		...
>>>>>>> 	}
>>>>>>>
>>>>>>> But that's admittedly somewhat of a stretch. This could of course be
>>>>>>> made somewhat nicer by adding an explicit variant, say:
>>>>>>>
>>>>>>> 	pm_runtime_enable_foo(dev)
>>>>>>> 	{
>>>>>>> 		if (!CONFIG_PM && dev->pm_ops->resume)
>>>>>>> 			return dev->pm_ops->resume(dev);
>>>>>>>
>>>>>>> 		return 0;
>>>>>>> 	}
>>>>>>>
>>>>>>> Maybe the fact that I couldn't come up with a good name is a good
>>>>>>> indication that this is a bad idea...
>>>>>>
>>>>>> How about some new APIs called ...
>>>>>>
>>>>>> pm_runtime_enable_get()
>>>>>> pm_runtime_enable_get_sync()
>>>>>> pm_runtime_put_disable() (implies a put_sync)
>>>>>>
>>>>>> ... and in these APIs we add ...
>>>>>>
>>>>>> pm_runtime_enable_get(dev)
>>>>>> {
>>>>>> 	if (!CONFIG_PM && dev->pm_ops->resume)
>>>>>> 		return dev->pm_ops->resume(dev);
>>>>>>
>>>>>> 	pm_runtime_enable(dev);
>>>>>> 	return pm_runtime_get(dev);
>>>>>> }
>>>>>
>>>>> Yeah, those sound sensible. I'm still a bit torn between this and just
>>>>> enforcing PM. At least on the display side I think we already require PM
>>>>> and with all the power domain work that you did we'd be much better off
>>>>> if we could just get rid of the !PM workarounds.
>>>>>
>>>>>>>>> This would be somewhat tricky because drivers
>>>>>>>>> usually use SET_RUNTIME_PM_OPS to populate the struct dev_pm_ops and
>>>>>>>>> that would result in an empty structure if !CONFIG_PM, but we could
>>>>>>>>> probably work around that by adding a __SET_RUNTIME_PM_OPS that would
>>>>>>>>> never be compiled out for this kind of case. Or such drivers could even
>>>>>>>>> manually set .runtime_suspend and .runtime_resume to make sure they're
>>>>>>>>> always populated.
>>>>>>>>>
>>>>>>>>> Another way out of this would be to make sure we never run into the case
>>>>>>>>> where runtime PM is disabled. If we always "select PM" on Tegra, then PM
>>>>>>>>> should always be available. But is it guaranteed that runtime PM for the
>>>>>>>>> devices is functional in that case? From a cursory look at the code it
>>>>>>>>> would seem that way.
>>>>>>>>
>>>>>>>> If you select PM, then all of the requisite code should be there.
>>>>>>>
>>>>>>> We do this on 64-bit ARM, but there had been some pushback when we had
>>>>>>> proposed to do the same thing on 32-bit ARM. I think there were two
>>>>>>> concerns:
>>>>>>>
>>>>>>> 	1) select PM would force the setting for all platforms on multi-
>>>>>>> 	   platforms builds
>>>>>>>
>>>>>>> 	2) prevents anyone from disabling PM for debugging purposes
>>>>>>>
>>>>>>> 1) no longer seems to be valid because Rockchip already selects PM
>>>>>>> unconditionally. I'm not sure if 2) is valid anymore either. I haven't
>>>>>>> run a build with !PM in a very long time and I wouldn't be surprised if
>>>>>>> that was completely broken.
>>>>>>>
>>>>>>> Maybe we need to try this again since a couple of years have elapsed and
>>>>>>> runtime PM support on Tegra is much more mature at this point.
>>>>>>>
>>>>>>>> Alternatively, you can make the driver depend on PM.
>>>>>>>
>>>>>>> That's probably the easiest way out, but to be honest I think I'd prefer
>>>>>>> to just enforce PM and keep things simple.
>>>>>>>
>>>>>>> Jon, any objections?
>>>>>>
>>>>>> None, but seems overkill just for this case.
>>>>>
>>>>> But that's precisely the point. It's not just about this case. We've
>>>>> already got some drivers where we do a similar dance just to be able to
>>>>> support the, let's admit it, exotic case where somebody turns off PM. I
>>>>> think supporting !PM might have made sense at a point where we had no
>>>>> support for power management at all. But I think we've come a long way
>>>>> since then, and while we may still have some ways to go in some areas,
>>>>> we do fairly decent runtime PM most of the time, to the point where I no
>>>>> longer see any benefits in !PM.
>>>>
>>>> I'm requesting PM_DEBUG_ALWAYS_ON option then! Disabling PM is a
>>>> useful debug feature, it can't just go away. 
>>>
>>> What is it about disabling PM that you consider useful? I can understand
>>> why you'd want that option if power management is broken, but as far as
>>> I can tell, power management on Tegra is in pretty good state, and it's
>>> more likely that !PM would actually be broken (though I haven't built a
>>> configuration like that in a couple of years, so I'm speculating). We
>>> already can't disable PM on 64-bit ARM, so I don't understand why 32-bit
>>> ARM should be treated any differently.
>>
>> Yes, I want an option for debugging of a broken PM. It doesn't matter
>> that there are no known PM-related issues on Tegra today, it could
>> become a problem tomorrow. Probably a kernel boot parameter like
>> pm_debug_always_on would suit even better here. 
>>
>> Or maybe PM API already provides such debug options and I'm just not
>> aware about them?
> 
> I'm not sure I understand what you're trying to do. If you want to use
> !PM as a way to debug broken PM, how would that help? Presumably if you
> disable !PM then the problem would be gone? In other words, in order to
> reproduce a PM related issue don't you have to enable PM first?

Disabling PM globally is one of first diagnostics steps, at least it gives an idea about source of a problem.

> I'm not aware of an alternate mechanism to force PM to off once built
> into the kernel.

I think runtime PM could be disabled per-device. That's probably what tools like powertop use to tune power management.

>> Do you know what's the exact reason for ARM64 to not support !PM?
> 
> There's no reason per se not to support PM. It's just that at the time
> we made the decision that we didn't want to. I vaguely remember that we
> tried to do the same thing for 32-bit ARM, but at the time we would've
> been the only platform to select PM, and that would've meant enabling
> PM for all subarchitectures and therefore forcing PM in multi-platform
> builds. Today if you build multi-platform kernels, at least Rockchip
> will also forcibly enable PM for everyone.
> 
> I think you may also have objected at the time for similar reasons. But
> this was a long time ago (at least 2 to 3 years I would guess) and much
> has changed since then. Power management has gotten a lot better on
> Tegra, to the point where we actually need it in order to properly
> function. For example, Tegra DRM is not going to work with !PM because
> we rely on runtime PM while disabling and enabling display pipelines.

I also know that people are disabling PM for performance reasons, sometime it's more important to reduce system's response latency than to care about power savings. But that probably not very relevant to Tegra usages. Okay, I guess in general it should be fine to enforce PM requirement and improve debug-ability later on by as-needed basis.
Rafael J. Wysocki Feb. 5, 2019, 11:34 a.m. UTC | #28
On Monday, February 4, 2019 11:04:50 AM CET Jon Hunter wrote:
> 
> On 04/02/2019 08:16, Sameer Pujar wrote:
> 
> ...
> 
> > Objective is to have things working with or without CONFIG_PM enabled.
> > From previous comments and discussions it appears that there is mixed
> > response
> > for calling hda_tegra_runtime_resume() or runtime PM APIs in probe()
> > call. Need
> > to have consensus regarding the best practice to be followed, which
> > would eventually
> > can be used in other drivers too.
> > 
> > Rafael is suggesting to use CONFIG_PM check to do manual setup or
> > runtime PM setup in probe,
> > which would bring back the earlier above mentioned concern.
> > 
> > if (IS_ENABLED(CONFIG_PM)) {
> > do setup based on pm-runtime
> > } else {
> >     do manual setup
> > }
> > Both if/else might end up doing the same here.
> > Do we really need CONFIG_PM check here?
> > 
> > Instead does below proposal appear fine?
> > 
> > probe() {
> >     hda_tegra_enable_clock();
> > }
> > 
> > probe_work() {
> >     /* hda setup */
> >     . . .
> >     pm_runtime_set_active(); /* initial state as active */
> >     pm_runtime_enable();
> >     return;
> > }
> 
> I believe that this still does not work, because if there is a
> power-domain that needs to be turned on, this does not guarantee this.
> So I think that you need to call pm_runtime_get ...
> 
>  probe() {
>  	if (!IS_ENABLED(CONFIG_PM))
>  		hda_tegra_enable_clock();
>  }
> 

But alas, there are no PM domains with CONFIG_PM unset.

CONFIG_PM unset means that the *driver* has to know how to turn on the
device and that has to be sufficient.

Which basically is my point when I'm saying that this information is
not available to the core and it cannot do anything to handle this
case without the extra knowledge.

Thanks,
Rafael
Rafael J. Wysocki Feb. 5, 2019, 11:52 a.m. UTC | #29
On Monday, February 4, 2019 12:05:10 PM CET Thierry Reding wrote:
> 
> --FCuugMFkClbJLl1L
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: inline
> Content-Transfer-Encoding: quoted-printable
> 
> On Mon, Feb 04, 2019 at 09:53:32AM +0000, Jon Hunter wrote:
> >=20
> >=20
> > On 04/02/2019 08:45, Thierry Reding wrote:
> >=20
> > ...
> >=20
> > > The idea was, as I was saying below, to reuse dev_pm_ops even if
> > > !CONFIG_PM. So pm_runtime_enable() could be something like this:
> > >=20
> > > 	pm_runtime_enable(dev)
> > > 	{
> > > 		if (!CONFIG_PM)
> > > 			if (dev->pm_ops->resume)
> > > 				dev->pm_ops->resume(dev);
> > >=20
> > > 		...
> > > 	}
> > >=20
> > > But that's admittedly somewhat of a stretch. This could of course be
> > > made somewhat nicer by adding an explicit variant, say:
> > >=20
> > > 	pm_runtime_enable_foo(dev)
> > > 	{
> > > 		if (!CONFIG_PM && dev->pm_ops->resume)
> > > 			return dev->pm_ops->resume(dev);
> > >=20
> > > 		return 0;
> > > 	}
> > >=20
> > > Maybe the fact that I couldn't come up with a good name is a good
> > > indication that this is a bad idea...
> >=20
> > How about some new APIs called ...
> >=20
> > pm_runtime_enable_get()
> > pm_runtime_enable_get_sync()
> > pm_runtime_put_disable() (implies a put_sync)
> >=20
> > ... and in these APIs we add ...
> >=20
> > pm_runtime_enable_get(dev)
> > {
> > 	if (!CONFIG_PM && dev->pm_ops->resume)
> > 		return dev->pm_ops->resume(dev);

No, we're not adding this to the core.

While in principle you could provide a set of pointers to the routines
you want to be called when CONFIG_PM is unset, IMO it is just cleaner
and more straightforward (and fewer lines of code for that matter) to add
a simple conditional to each ->probe() and ->remove().

[cut]

> > None, but seems overkill just for this case.
> 
> But that's precisely the point. It's not just about this case. We've
> already got some drivers where we do a similar dance just to be able to
> support the, let's admit it, exotic case where somebody turns off PM. I
> think supporting !PM might have made sense at a point where we had no
> support for power management at all. But I think we've come a long way
> since then, and while we may still have some ways to go in some areas,
> we do fairly decent runtime PM most of the time, to the point where I no
> longer see any benefits in !PM.

This IMO is an excellent point.

Trying to handle the !CONFIG_PM case only really makes sense if you know
what to do to turn the device on without relying on things like PM domains
etc which are not even available if CONFIG_PM is not set.

IOW, if any of the platforms your driver is expected to work with require
something like genpd to even make the device functional, I wouldn't bother.

Thanks,
Rafael
diff mbox series

Patch

diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index c8d18dc..ba6175f 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -219,7 +219,6 @@  static int hda_tegra_enable_clocks(struct hda_tegra *data)
 	return rc;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static void hda_tegra_disable_clocks(struct hda_tegra *data)
 {
 	clk_disable_unprepare(data->hda2hdmi_clk);
@@ -227,6 +226,7 @@  static void hda_tegra_disable_clocks(struct hda_tegra *data)
 	clk_disable_unprepare(data->hda_clk);
 }
 
+#ifdef CONFIG_PM_SLEEP
 /*
  * power management
  */
@@ -257,7 +257,6 @@  static int hda_tegra_resume(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-#ifdef CONFIG_PM
 static int hda_tegra_runtime_suspend(struct device *dev)
 {
 	struct snd_card *card = dev_get_drvdata(dev);
@@ -283,7 +282,7 @@  static int hda_tegra_runtime_resume(struct device *dev)
 	int rc;
 
 	rc = hda_tegra_enable_clocks(hda);
-	if (rc != 0)
+	if (rc)
 		return rc;
 	if (chip && chip->running) {
 		hda_tegra_init(hda);
@@ -292,7 +291,6 @@  static int hda_tegra_runtime_resume(struct device *dev)
 
 	return 0;
 }
-#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops hda_tegra_pm = {
 	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
@@ -551,9 +549,9 @@  static int hda_tegra_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(&pdev->dev, card);
 
-	pm_runtime_enable(hda->dev);
-	if (!azx_has_pm_runtime(chip))
-		pm_runtime_forbid(hda->dev);
+	err = hda_tegra_enable_clocks(hda);
+	if (err)
+		goto out_free;
 
 	schedule_work(&hda->probe_work);
 
@@ -571,7 +569,6 @@  static void hda_tegra_probe_work(struct work_struct *work)
 	struct platform_device *pdev = to_platform_device(hda->dev);
 	int err;
 
-	pm_runtime_get_sync(hda->dev);
 	err = hda_tegra_first_init(chip, pdev);
 	if (err < 0)
 		goto out_free;
@@ -592,8 +589,15 @@  static void hda_tegra_probe_work(struct work_struct *work)
 	chip->running = 1;
 	snd_hda_set_power_save(&chip->bus, power_save * 1000);
 
+	/* set device state as active */
+	if (pm_runtime_set_active(hda->dev) < 0)
+		goto out_free;
+	/* enable runtime PM */
+	pm_runtime_enable(hda->dev);
+	if (!azx_has_pm_runtime(chip))
+		pm_runtime_forbid(hda->dev);
+
  out_free:
-	pm_runtime_put(hda->dev);
 	return; /* no error return from async probe */
 }
 
@@ -603,6 +607,10 @@  static int hda_tegra_remove(struct platform_device *pdev)
 
 	ret = snd_card_free(dev_get_drvdata(&pdev->dev));
 	pm_runtime_disable(&pdev->dev);
+	if (!pm_runtime_status_suspended(&pdev->dev)) {
+		hda_tegra_runtime_suspend(&pdev->dev);
+		pm_runtime_set_suspended(&pdev->dev);
+	}
 
 	return ret;
 }