From 05c6028191da49c24e7a7d1b876dfdd109834f9b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 May 2019 14:09:19 -0500 Subject: [PATCH] FROMGIT: ASoC: SOF: core: fix error handling with the probe workqueue In some configurations, it's a requirement to split the probe in two, with a second part handled in a workqueue (e.g. for HDMI support which depends on the DRM modules). SOF already handles these configurations but the error flow is incorrect. When an error occurs in the workqueue, the probe has technically already completed. If we release the resources on errors, this generates kernel oops/use-after-free when the resources are released a second time on module removal. GitHub issue: https://github.com/thesofproject/linux/issues/945 Fixes: c16211d6226 ("ASoC: SOF: Add Sound Open Firmware driver core") Reviewed-by: Takashi Iwai Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown (cherry picked from commit 0bce512e784d137700275f7839c4547eddbd4b6a git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next) BUG=b:134688240 TEST=Test Audio use cases for CML with full SOF patch series applied. Change-Id: I78bb4807ee8534269ea04f4bc238a4a9975b2678 Signed-off-by: Ap, Kamal --- sound/soc/sof/core.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 693ad83bffc9c3..5beda47cdf9fc7 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -393,6 +393,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) return 0; +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) fw_run_err: snd_sof_fw_unload(sdev); fw_load_err: @@ -401,6 +402,21 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) snd_sof_free_debug(sdev); dbg_err: snd_sof_remove(sdev); +#else + + /* + * when the probe_continue is handled in a work queue, the + * probe does not fail so we don't release resources here. + * They will be released with an explicit call to + * snd_sof_device_remove() when the PCI/ACPI device is removed + */ + +fw_run_err: +fw_load_err: +ipc_err: +dbg_err: + +#endif return ret; }