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 |
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) >
Acked-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Adding the upstream reference as already mentioned.
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)