Re: [PATCH] ALSA: hda/tegra: enable clock during probe

From: Takashi Iwai
Date: Thu Jan 24 2019 - 14:08:27 EST


On Thu, 24 Jan 2019 18:36:43 +0100,
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 checks whether runtime PM is enabled or not.
> If disabled, clocks are enabled in probe() and disabled in remove()
>
> This patch does following minor changes as cleanup,
> * return code check for pm_runtime_get_sync() to take care of failure
> and exit gracefully.
> * In remove path runtime PM is disabled before calling snd_card_free().
> * 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@xxxxxxxxxx>
> Reviewed-by: Ravindra Lokhande <rlokhande@xxxxxxxxxx>
> Reviewed-by: Jon Hunter <jonathanh@xxxxxxxxxx>
(snip)
> @@ -555,6 +553,13 @@ static int hda_tegra_probe(struct platform_device *pdev)
> if (!azx_has_pm_runtime(chip))
> pm_runtime_forbid(hda->dev);
>
> + /* explicit resume if runtime PM is disabled */
> + if (!pm_runtime_enabled(hda->dev)) {
> + err = hda_tegra_runtime_resume(hda->dev);
> + if (err)
> + goto out_free;
> + }
> +
> schedule_work(&hda->probe_work);

Calling runtime_resume here is really confusing...


> @@ -571,7 +576,14 @@ 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 = pm_runtime_get_sync(hda->dev);
> + if (err < 0) {
> + dev_err(hda->dev,
> + "failed in pm_runtime_get_syc with err = %d\n",
> + err);
> + return;
> + }

This pm_runtime_get_sync() is needed just because you enabled runtime
PM before probe_work. Why not deferring the runtime PM enablement
after probing done?

That is what we need is the hda_tegra_enable_clocks() call at probe
unconditionally before enabling runtime PM.

> err = hda_tegra_first_init(chip, pdev);
> if (err < 0)
> goto out_free;
> @@ -599,12 +611,13 @@ static void hda_tegra_probe_work(struct work_struct *work)
>
> static int hda_tegra_remove(struct platform_device *pdev)
> {
> - int ret;
> -
> - 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;
> + return snd_card_free(dev_get_drvdata(&pdev->dev));


Forcing the suspend *before* snd_card_free() doesn't sound right.
It's the point before the disconnect and release procedure of all the
rest. That is, the other hardware components are still active at this
point.


thanks,

Takashi