Message ID | 20200119025533.8355-5-hui.wang@canonical.com |
---|---|
State | New |
Headers | show |
Series | [SRU,unstable] UBUNTU: SAUCE: ASoC: SOF: Intel: fix HDA codec driver probe with multiple controllers | expand |
On Sun, Jan 19, 2020 at 10:55:33AM +0800, 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> This patch is already in 5.5, so it is not needed in unstable.
diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 827f84a0722e..fbfa225d1c5a 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -24,19 +24,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)); +} /* enable controller wake up event for all codecs with jack connectors */ void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) @@ -129,10 +128,16 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) if ((mach_params && mach_params->common_hdmi_codec_drv) || (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)