[Intel-gfx] [PATCH] BUG-REPORT: snd-hda: hacked-together EPROBE_DEFER support

Daniel Vetter daniel.vetter at ffwll.ch
Wed Jun 21 15:08:54 UTC 2017


So back when the i915 power well support landed in

commit 99a2008d0b32d72dfc2a54e7be1eb698dd2e3bd6
Author: Wang Xingchao <xingchao.wang at linux.intel.com>
Date:   Thu May 30 22:07:10 2013 +0800

    ALSA: hda - Add power-welll support for haswell HDA

the logic to handle the cross-module depencies was hand-rolled using a
async work item, and that just doesn't work.

The correct way to handle cross-module deps is either:
- request_module + failing when the other module isn't there

OR

- failing the module load with EPROBE_DEFER.

You can't mix them, if you do then the entire load path just
busy-spins blowing through cpu cycles forever with no way to stop
this.

snd-hda-intel does mix it, because the hda codec drivers are loaded
using request_module, but the i915 depency is handled using
PROBE_DEFER (or well, should be, but I haven't found any code at all).
This is a major pain when trying to debug i915 load failures.

This patch here is a horrible hackish attempt at somewhat correctly
wriing EPROBE_DEFER through. Stuff that's missing:
- Check all the other places where load errors are conveniently
  dropped on the floor.
- Also fix up the firmware_cb path.
- Drop the debug noise I've left in to make it clear this isn't
  anything for merging.

Cheers, Daniel

Cc: Jaroslav Kysela <perex at perex.cz>
Cc: Takashi Iwai <tiwai at suse.com>
Cc: "GitAuthor: Daniel Vetter" <daniel.vetter at ffwll.ch>
Cc: Guneshwor Singh <guneshwor.o.singh at intel.com>
Cc: Hardik T Shah <hardik.t.shah at intel.com>
Cc: Julia Lawall <Julia.Lawall at lip6.fr>
Cc: Vinod Koul <vinod.koul at intel.com>
Cc: "Subhransu S. Prusty" <subhransu.s.prusty at intel.com>
Cc: Libin Yang <libin.yang at intel.com>
Cc: linux-kernel at vger.kernel.org
---
 drivers/base/dd.c              |  2 ++
 sound/pci/hda/hda_bind.c       |  6 +++---
 sound/pci/hda/hda_controller.c |  8 +++++++-
 sound/pci/hda/hda_intel.c      | 13 +++++++++----
 4 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 4882f06d12df..842bc8782124 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -17,6 +17,8 @@
  * This file is released under the GPLv2
  */
 
+#define DEBUG
+
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index 6efadbfb3fe3..0bc164a17493 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -253,7 +253,7 @@ static int codec_bind_generic(struct hda_codec *codec)
 	request_codec_module(codec);
 	if (codec_probed(codec))
 		return 0;
-	return -ENODEV;
+	return -EPROBE_DEFER;
 }
 
 #if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
@@ -289,8 +289,8 @@ int snd_hda_codec_configure(struct hda_codec *codec)
 		codec_bind_module(codec);
 	if (!codec->preset) {
 		err = codec_bind_generic(codec);
-		if (err < 0) {
-			codec_err(codec, "Unable to bind the codec\n");
+		if (WARN_ON(err < 0)) {
+			codec_err(codec, "Unable to bind the codec, err=%i\n", err);
 			goto error;
 		}
 	}
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 3715a5725613..4b4262c72327 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -1337,9 +1337,15 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs);
 /* configure each codec instance */
 int azx_codec_configure(struct azx *chip)
 {
+	int ret;
+
 	struct hda_codec *codec;
 	list_for_each_codec(codec, &chip->bus) {
-		snd_hda_codec_configure(codec);
+		ret = snd_hda_codec_configure(codec);
+		if (ret) {
+			printk("bailing real hard %i\n", ret);
+			return ret;
+		}
 	}
 	return 0;
 }
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 07ea7f48aa01..8241387cc8ca 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1649,7 +1649,8 @@ static void azx_check_snoop_available(struct azx *chip)
 static void azx_probe_work(struct work_struct *work)
 {
 	struct hda_intel *hda = container_of(work, struct hda_intel, probe_work);
-	azx_probe_continue(&hda->chip);
+
+	WARN_ON(1);
 }
 
 static int default_bdl_pos_adj(struct azx *chip)
@@ -2158,7 +2159,6 @@ static int azx_probe(struct pci_dev *pci,
 					      azx_firmware_cb);
 		if (err < 0)
 			goto out_free;
-		schedule_probe = false; /* continued in azx_firmware_cb() */
 	}
 #endif /* CONFIG_SND_HDA_PATCH_LOADER */
 
@@ -2167,8 +2167,13 @@ static int azx_probe(struct pci_dev *pci,
 		dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
 #endif
 
-	if (schedule_probe)
-		schedule_work(&hda->probe_work);
+	if (schedule_probe) {
+		err = azx_probe_continue(chip);
+		if (err) {
+			printk("hit the right error return finally! err=%i\n", err);
+			goto out_free;
+		}
+	}
 
 	dev++;
 	if (chip->disabled)
-- 
2.5.5



More information about the Intel-gfx mailing list