diff mbox series

[SRU,E] UBUNTU: SAUCE: ASoC: SOF: Intel: fix HDA codec driver probe with multiple controllers

Message ID 20200119025533.8355-3-hui.wang@canonical.com
State New
Headers show
Series [SRU,E] UBUNTU: SAUCE: ASoC: SOF: Intel: fix HDA codec driver probe with multiple controllers | expand

Commit Message

Hui Wang Jan. 19, 2020, 2:55 a.m. UTC
From: Kai Vehmanen <kai.vehmanen@linux.intel.com>

BugLink: https://bugs.launchpad.net/bugs/1860248

In case system has multiple HDA controllers, it can happen that
same HDA codec driver is used for codecs of multiple controllers.
In this case, SOF may fail to probe the HDA driver and SOF
initialization fails.

SOF HDA code currently relies that a call to request_module() will
also run device matching logic to attach driver to the codec instance.
However if driver for another HDA controller was already loaded and it
already loaded the HDA codec driver, this breaks current logic in SOF.
In this case the request_module() SOF does becomes a no-op and HDA
Codec driver is not attached to the codec instance sitting on the HDA
bus SOF is controlling. Typical scenario would be a system with both
external and internal GPUs, with driver of the external GPU loaded
first.

Fix this by adding similar logic as is used in legacy HDA driver
where an explicit device_attach() call is done after request_module().

Also add logic to propagate errors reported by device_attach() back
to caller. This also works in the case where drivers are not built
as modules.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200110235751.3404-8-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
(cherry picked from commit 2c63bea714780f8e1fc9cb7bc10deda26fada25b
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git)
Signed-off-by: Hui Wang <hui.wang@canonical.com>
---
 sound/soc/sof/intel/hda-codec.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

Comments

Stefan Bader Jan. 24, 2020, 7:18 a.m. UTC | #1
On 19.01.20 04:55, Hui Wang wrote:
> From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1860248
> 
> In case system has multiple HDA controllers, it can happen that
> same HDA codec driver is used for codecs of multiple controllers.
> In this case, SOF may fail to probe the HDA driver and SOF
> initialization fails.
> 
> SOF HDA code currently relies that a call to request_module() will
> also run device matching logic to attach driver to the codec instance.
> However if driver for another HDA controller was already loaded and it
> already loaded the HDA codec driver, this breaks current logic in SOF.
> In this case the request_module() SOF does becomes a no-op and HDA
> Codec driver is not attached to the codec instance sitting on the HDA
> bus SOF is controlling. Typical scenario would be a system with both
> external and internal GPUs, with driver of the external GPU loaded
> first.
> 
> Fix this by adding similar logic as is used in legacy HDA driver
> where an explicit device_attach() call is done after request_module().
> 
> Also add logic to propagate errors reported by device_attach() back
> to caller. This also works in the case where drivers are not built
> as modules.
> 
> Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> Link: https://lore.kernel.org/r/20200110235751.3404-8-pierre-louis.bossart@linux.intel.com
> Signed-off-by: Mark Brown <broonie@kernel.org>
> (cherry picked from commit 2c63bea714780f8e1fc9cb7bc10deda26fada25b
> git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git)
> Signed-off-by: Hui Wang <hui.wang@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---

As Seth mentioned that this got upstream by now, we should adjust the reference
when applying to Eoan.

-Stefan

>  sound/soc/sof/intel/hda-codec.c | 19 ++++++++++++-------
>  1 file changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c
> index 0d8437b080bf..2aa98b0de002 100644
> --- a/sound/soc/sof/intel/hda-codec.c
> +++ b/sound/soc/sof/intel/hda-codec.c
> @@ -23,19 +23,18 @@
>  #define IDISP_VID_INTEL	0x80860000
>  
>  /* load the legacy HDA codec driver */
> -#ifdef MODULE
> -static void hda_codec_load_module(struct hda_codec *codec)
> +static int hda_codec_load_module(struct hda_codec *codec)
>  {
> +#ifdef MODULE
>  	char alias[MODULE_NAME_LEN];
>  	const char *module = alias;
>  
>  	snd_hdac_codec_modalias(&codec->core, alias, sizeof(alias));
>  	dev_dbg(&codec->core.dev, "loading codec module: %s\n", module);
>  	request_module(module);
> -}
> -#else
> -static void hda_codec_load_module(struct hda_codec *codec) {}
>  #endif
> +	return device_attach(hda_codec_dev(codec));
> +}
>  
>  #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */
>  
> @@ -76,10 +75,16 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address)
>  	/* use legacy bus only for HDA codecs, idisp uses ext bus */
>  	if ((resp & 0xFFFF0000) != IDISP_VID_INTEL) {
>  		hdev->type = HDA_DEV_LEGACY;
> -		hda_codec_load_module(&hda_priv->codec);
> +		ret = hda_codec_load_module(&hda_priv->codec);
> +		/*
> +		 * handle ret==0 (no driver bound) as an error, but pass
> +		 * other return codes without modification
> +		 */
> +		if (ret == 0)
> +			ret = -ENOENT;
>  	}
>  
> -	return 0;
> +	return ret;
>  #else
>  	hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);
>  	if (!hdev)
>
Marcelo Henrique Cerri Jan. 28, 2020, 10:42 p.m. UTC | #2
Acked-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>

Adding the upstream reference as already mentioned.
diff mbox series

Patch

diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c
index 0d8437b080bf..2aa98b0de002 100644
--- a/sound/soc/sof/intel/hda-codec.c
+++ b/sound/soc/sof/intel/hda-codec.c
@@ -23,19 +23,18 @@ 
 #define IDISP_VID_INTEL	0x80860000
 
 /* load the legacy HDA codec driver */
-#ifdef MODULE
-static void hda_codec_load_module(struct hda_codec *codec)
+static int hda_codec_load_module(struct hda_codec *codec)
 {
+#ifdef MODULE
 	char alias[MODULE_NAME_LEN];
 	const char *module = alias;
 
 	snd_hdac_codec_modalias(&codec->core, alias, sizeof(alias));
 	dev_dbg(&codec->core.dev, "loading codec module: %s\n", module);
 	request_module(module);
-}
-#else
-static void hda_codec_load_module(struct hda_codec *codec) {}
 #endif
+	return device_attach(hda_codec_dev(codec));
+}
 
 #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */
 
@@ -76,10 +75,16 @@  static int hda_codec_probe(struct snd_sof_dev *sdev, int address)
 	/* use legacy bus only for HDA codecs, idisp uses ext bus */
 	if ((resp & 0xFFFF0000) != IDISP_VID_INTEL) {
 		hdev->type = HDA_DEV_LEGACY;
-		hda_codec_load_module(&hda_priv->codec);
+		ret = hda_codec_load_module(&hda_priv->codec);
+		/*
+		 * handle ret==0 (no driver bound) as an error, but pass
+		 * other return codes without modification
+		 */
+		if (ret == 0)
+			ret = -ENOENT;
 	}
 
-	return 0;
+	return ret;
 #else
 	hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);
 	if (!hdev)