Bug 212709 - Regression with MCP61 High Definition Audio (driver snd_hda_intel)
Summary: Regression with MCP61 High Definition Audio (driver snd_hda_intel)
Status: RESOLVED ANSWERED
Alias: None
Product: Drivers
Classification: Unclassified
Component: Sound(ALSA) (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Jaroslav Kysela
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-04-17 17:42 UTC by Sébastien P.
Modified: 2021-04-29 19:24 UTC (History)
1 user (show)

See Also:
Kernel Version: From 5.6.18 at least (5.4.113 latest known to work)
Subsystem:
Regression: No
Bisected commit-id:


Attachments
kernel.log (90.78 KB, text/plain)
2021-04-17 17:42 UTC, Sébastien P.
Details
config (83.91 KB, text/plain)
2021-04-17 17:42 UTC, Sébastien P.
Details
Commit found after bisect (5.12 KB, text/plain)
2021-04-23 22:06 UTC, Sébastien P.
Details
Workaround (2.84 KB, patch)
2021-04-24 09:44 UTC, Sébastien P.
Details | Diff

Description Sébastien P. 2021-04-17 17:42:25 UTC
Created attachment 296425 [details]
kernel.log

Hi,

I have a regression with my audio:
00:05.0 Audio device: NVIDIA Corporation MCP61 High Definition Audio (rev a2)
        Subsystem: ASUSTeK Computer Inc. MCP61 High Definition Audio
        Flags: bus master, 66MHz, fast devsel, latency 0, IRQ 22, NUMA node 0
        Memory at dbff8000 (32-bit, non-prefetchable) [size=16K]
        Capabilities: <access denied>
        Kernel driver in use: snd_hda_intel

I use LTS kernel from Gentoo. And since 5.10 migration (two weeks ago), sound is just crackling from the boot sequence until the shutdown. When I try to play a sound, I can heard both crackling and my sond.

I tried many kernels:
=> Working
linux-5.4.97-gentoo
linux-5.4.109-gentoo
linux-5.4.113

=> Compile but fail to launch (kernel panic, I do not understand… If you have any idea it can help me to identify which version introduce this bug)
linux-5.5.18
linux-5.5.19-gentoo
linux-5.6.0

=> Not working
linux-5.6.18-gentoo
linux-5.7.19-gentoo
linux-5.8.18-gentoo
linux-5.9.16-gentoo
linux-5.10.0-gentoo
linux-5.10.23-gentoo
linux-5.10.27-gentoo
linux-5.11.14
linux-5.12-rc7

I checked my logs but do not see anything except the device numbers. They are differents… but is it an issue?
5/6/7 => OK
0/1/2 => KO

Apr 17 19:21:41 fixe kernel: input: HDA NVidia Rear Mic as /devices/pci0000:00/0000:00:05.0/sound/card0/input0
Apr 17 19:21:41 fixe kernel: input: HDA NVidia Line as /devices/pci0000:00/0000:00:05.0/sound/card0/input1
Apr 17 19:21:41 fixe kernel: input: HDA NVidia Line Out as /devices/pci0000:00/0000:00:05.0/sound/card0/input2
=> 5.12-rc7

Apr 17 19:24:40 fixe kernel: input: HDA NVidia Rear Mic as /devices/pci0000:00/0000:00:05.0/sound/card0/input5
Apr 17 19:24:40 fixe kernel: input: HDA NVidia Line as /devices/pci0000:00/0000:00:05.0/sound/card0/input6
Apr 17 19:24:40 fixe kernel: input: HDA NVidia Line Out as /devices/pci0000:00/0000:00:05.0/sound/card0/input7
=> 5.4.113


Except looking at git changes, I do not see what I can do more :/.
Does anyone have an idea about what can break the sound? Or about the device numbers?

(Not very important: why I can not use a 5.5 kernel?)
Comment 1 Sébastien P. 2021-04-17 17:42:52 UTC
Created attachment 296427 [details]
config
Comment 2 Sébastien P. 2021-04-19 21:53:23 UTC
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 9b294c13809a..da9f4ea9bf4c 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -11,6 +11,12 @@ extra-y	+= vmlinux.lds
 
 CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
 
+# smpboot's init_secondary initializes stack canary.
+# Make sure we don't emit stack checks before it's
+# initialized.
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_smpboot.o := $(nostackp)
+

solved the kernel panic issue. Regression is between 5.5.19 (gentoo) and 5.6.0 (vanilla). I will check 5.5.19 vanilla tomorrow to be sure.
Then have a look to bisect.
Comment 3 Sébastien P. 2021-04-23 22:06:21 UTC
Created attachment 296469 [details]
Commit found after bisect

Hi,

After bisecting between 5.5 and 5.6, it leads me to the commit 88452da92ba2b264a3922218c2cec13aac51c502

It does not mean something to me. Probably due to non-knowledge of C.
I took a like at this commit and compared it with 5.12 (that are not working too). Most of the commit has disappeared.

diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index e05b95e83d5a..81373a2efd96 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -317,6 +317,7 @@ struct hdac_bus {
 	struct hdac_rb corb;
 	struct hdac_rb rirb;
 	unsigned int last_cmd[HDA_MAX_CODECS];	/* last sent command */
+	wait_queue_head_t rirb_wq;
 
 	/* CORB/RIRB and position buffers */
 	struct snd_dma_buffer rb;
diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c
index 8f19876244eb..48b227fff204 100644
--- a/sound/hda/hdac_bus.c
+++ b/sound/hda/hdac_bus.c
@@ -43,6 +43,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
 	mutex_init(&bus->cmd_mutex);
 	mutex_init(&bus->lock);
 	INIT_LIST_HEAD(&bus->hlink_list);
+	init_waitqueue_head(&bus->rirb_wq);
 	bus->irq = -1;
 	return 0;
 }
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index 7e7be8e4dcf9..cd1c3b282657 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -216,6 +216,9 @@ void snd_hdac_bus_update_rirb(struct hdac_bus *bus)
 		else if (bus->rirb.cmds[addr]) {
 			bus->rirb.res[addr] = res;
 			bus->rirb.cmds[addr]--;
+			if (!bus->rirb.cmds[addr] &&
+			    waitqueue_active(&bus->rirb_wq))
+				wake_up(&bus->rirb_wq);
 		} else {
 			dev_err_ratelimited(bus->dev,
 				"spurious response %#x:%#x, last cmd=%#08x\n",
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 2f3b7a35f2d9..f30a053d981e 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -792,21 +792,25 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
 	struct hda_bus *hbus = &chip->bus;
 	unsigned long timeout;
 	unsigned long loopcounter;
-	int do_poll = 0;
+	wait_queue_entry_t wait;
 	bool warned = false;
 
+	init_wait_entry(&wait, 0);
  again:
 	timeout = jiffies + msecs_to_jiffies(1000);
 
 	for (loopcounter = 0;; loopcounter++) {
 		spin_lock_irq(&bus->reg_lock);
-		if (bus->polling_mode || do_poll)
+		if (!bus->polling_mode)
+			prepare_to_wait(&bus->rirb_wq, &wait,
+					TASK_UNINTERRUPTIBLE);
+		if (bus->polling_mode)
 			snd_hdac_bus_update_rirb(bus);
 		if (!bus->rirb.cmds[addr]) {
-			if (!do_poll)
-				bus->poll_count = 0;
 			if (res)
 				*res = bus->rirb.res[addr]; /* the last value */
+			if (!bus->polling_mode)
+				finish_wait(&bus->rirb_wq, &wait);
 			spin_unlock_irq(&bus->reg_lock);
 			return 0;
 		}
@@ -814,7 +818,9 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
 		if (time_after(jiffies, timeout))
 			break;
 #define LOOP_COUNT_MAX	3000
-		if (hbus->needs_damn_long_delay ||
+		if (!bus->polling_mode) {
+			schedule_timeout(msecs_to_jiffies(2));
+		} else if (hbus->needs_damn_long_delay ||
 		    loopcounter > LOOP_COUNT_MAX) {
 			if (loopcounter > LOOP_COUNT_MAX && !warned) {
 				dev_dbg_ratelimited(chip->card->dev,
@@ -829,19 +835,12 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
 		}
 	}
 
+	if (!bus->polling_mode)
+		finish_wait(&bus->rirb_wq, &wait);
+
 	if (hbus->no_response_fallback)
 		return -EIO;
 
-	if (!bus->polling_mode && bus->poll_count < 2) {
-		dev_dbg(chip->card->dev,
-			"azx_get_response timeout, polling the codec once: last cmd=0x%08x\n",
-			bus->last_cmd[addr]);
-		do_poll = 1;
-		bus->poll_count++;
-		goto again;
-	}
-
-
 	if (!bus->polling_mode) {
 		dev_warn(chip->card->dev,
 			 "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n",


Any idea?
Comment 4 Sébastien P. 2021-04-24 09:44:06 UTC
Created attachment 296471 [details]
Workaround

I managed to create this workaround for 5.10.31 (with revert/manual merge). It is probably quite dirty but it works for me…

diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c
index 9766f6af8743..44d1e309a8b6 100644
--- a/sound/hda/hdac_bus.c
+++ b/sound/hda/hdac_bus.c
@@ -44,7 +44,6 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
 	mutex_init(&bus->cmd_mutex);
 	mutex_init(&bus->lock);
 	INIT_LIST_HEAD(&bus->hlink_list);
-	init_waitqueue_head(&bus->rirb_wq);
 	bus->irq = -1;
 
 	/*
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index b98449fd92f3..abdc0bb1b462 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -218,9 +218,6 @@ void snd_hdac_bus_update_rirb(struct hdac_bus *bus)
 		else if (bus->rirb.cmds[addr]) {
 			bus->rirb.res[addr] = res;
 			bus->rirb.cmds[addr]--;
-			if (!bus->rirb.cmds[addr] &&
-			    waitqueue_active(&bus->rirb_wq))
-				wake_up(&bus->rirb_wq);
 		} else {
 			dev_err_ratelimited(bus->dev,
 				"spurious response %#x:%#x, last cmd=%#08x\n",
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index b972d59eb1ec..0b621bd5b5ab 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -777,9 +777,46 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
 {
 	struct azx *chip = bus_to_azx(bus);
 	struct hda_bus *hbus = &chip->bus;
+	unsigned long timeout;
+	unsigned long loopcounter;
+	int do_poll = 0;
+	bool warned = false;
 	int err;
 
  again:
+	timeout = jiffies + msecs_to_jiffies(1000);
+
+	for (loopcounter = 0;; loopcounter++) {
+		spin_lock_irq(&bus->reg_lock);
+		if (bus->polling_mode || do_poll)
+			snd_hdac_bus_update_rirb(bus);
+		if (!bus->rirb.cmds[addr]) {
+			if (!do_poll)
+				bus->poll_count = 0;
+			if (res)
+				*res = bus->rirb.res[addr]; /* the last value */
+			spin_unlock_irq(&bus->reg_lock);
+			return 0;
+		}
+		spin_unlock_irq(&bus->reg_lock);
+		if (time_after(jiffies, timeout))
+			break;
+#define LOOP_COUNT_MAX	3000
+		if (hbus->core.needs_damn_long_delay ||
+		    loopcounter > LOOP_COUNT_MAX) {
+			if (loopcounter > LOOP_COUNT_MAX && !warned) {
+				dev_dbg_ratelimited(chip->card->dev,
+						    "too slow response, last cmd=%#08x\n",
+						    bus->last_cmd[addr]);
+				warned = true;
+			}
+			msleep(2); /* temporary workaround */
+		} else {
+			udelay(10);
+			cond_resched();
+		}
+	}
+
 	err = snd_hdac_bus_get_response(bus, addr, res);
 	if (!err)
 		return 0;
@@ -787,6 +824,16 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
 	if (hbus->no_response_fallback)
 		return -EIO;
 
+	if (!bus->polling_mode && bus->poll_count < 2) {
+		dev_dbg(chip->card->dev,
+			"azx_get_response timeout, polling the codec once: last cmd=0x%08x\n",
+			bus->last_cmd[addr]);
+		do_poll = 1;
+		bus->poll_count++;
+		goto again;
+	}
+
+
 	if (!bus->polling_mode) {
 		dev_warn(chip->card->dev,
 			 "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n",
Comment 5 Sébastien P. 2021-04-29 19:24:17 UTC
Add CONFIG_SND_HDA_CODEC_ANALOG=y solved the issue.

Maybe description is a bit to generic:
Say Y or M here to include Analog Devices HD-audio codec support in snd-hda-intel driver, such as AD1986A.
=> AD1986A is just one chipset among lots of: https://doc.ubuntu-fr.org/audio_intel_hda

I have compiled my kernels for 14years. Never used it!

Note You need to log in before you can comment on or make changes to this bug.