adsp: Fix crash in fe_widget_event after pcm close

Dangling reference to pcm runtime data in app->private_data was
leading to a kernel crash. Assigning null in pcm close callback
and validating appropriately in fe_widget_event() solves the
problem.

Bug 2402965

Change-Id: I72b9008fde83ac55d032670b9ecd95560ef89e3a
Signed-off-by: Niranjan Dighe <ndighe@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1979759
(cherry picked from commit d03c2843e9376d0e674236b40bf516b91f808820)
Reviewed-on: https://git-master.nvidia.com/r/2126291
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Hariharan Sivaraman <hariharans@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Uday Gupta <udayg@nvidia.com>
Reviewed-by: Dipesh Gandhi <dipeshg@nvidia.com>
Reviewed-by: Nitin Pai <npai@nvidia.com>
Tested-by: Nitin Pai <npai@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Niranjan Dighe
2018-12-19 22:53:24 +05:30
committed by Sameer Pujar
parent 281827694d
commit f0c6c418c5

View File

@@ -1821,6 +1821,8 @@ static int tegra210_adsp_pcm_close(struct snd_pcm_substream *substream)
prtd->fe_apm->msg_handler =
tegra210_adsp_app_default_msg_handler;
prtd->fe_apm->private_data = NULL;
spin_unlock_irqrestore(&prtd->fe_apm->lock, flags);
prtd->fe_apm->fe = 1;
@@ -2689,10 +2691,10 @@ static int tegra210_adsp_fe_widget_event(struct snd_soc_dapm_widget *w,
}
} else if (event == SND_SOC_DAPM_POST_PMD) {
unsigned long flags;
dev_info(adsp->dev, "disconnect event on APM %d, ADSP-FE %d\n",
(i + 1) - APM_IN_START, w->reg);
prtd = apm->private_data;
runtime = prtd->substream->runtime;
ret = tegra210_adsp_send_state_msg(apm, nvfx_state_inactive,
TEGRA210_ADSP_MSG_FLAG_SEND | TEGRA210_ADSP_MSG_FLAG_NEED_ACK);
@@ -2701,6 +2703,16 @@ static int tegra210_adsp_fe_widget_event(struct snd_soc_dapm_widget *w,
goto err_put;
}
spin_lock_irqsave(&apm->lock, flags);
prtd = apm->private_data;
if (!prtd) {
dev_dbg(adsp->dev, "PCM close caused this widget event\n");
spin_unlock_irqrestore(&apm->lock, flags);
goto err_put;
}
runtime = prtd->substream->runtime;
runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
if (!(prtd->substream->f_flags & O_NONBLOCK)) {
if (IS_MMAP_ACCESS(runtime->access))
@@ -2708,6 +2720,9 @@ static int tegra210_adsp_fe_widget_event(struct snd_soc_dapm_widget *w,
else
wake_up(&runtime->tsleep);
}
spin_unlock_irqrestore(&apm->lock, flags);
} else {
pr_err("%s: error. unknown event: %d\n", __func__, event);
ret = -1;