[PATCH 1/1] ALSA: hda: add fallback to polling to hdac_bus_get_response()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The AZX controller implementation in azx_rirb_get_response()
implements logic to fallback to polling in case interrupt is
not received from HDA codec.

Port over this same logic to the generic snd_hdac_bus_get_response()
function, which is used by other HDAC clients such as SOF.

Without this fix, failures are observed in module reload
stress tests with the SOF driver, while test passes on same
hardware with the snd_hda_intel driver. Considering
the AZX implementation has been much more widely used and
there can be exceptions with other systems (and codecs), it
is best to align the implementation and use the time-proven
logic in all drivers.

Signed-off-by: Kai Vehmanen <kai.vehmanen@xxxxxxxxxxxxxxx>
---
 sound/hda/hdac_controller.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index d3999e7b0705..994c1dd2eb2e 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -238,14 +238,18 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
 {
 	unsigned long timeout;
 	unsigned long loopcounter;
+	int do_poll = 0;
 
+ again:
 	timeout = jiffies + msecs_to_jiffies(1000);
 
 	for (loopcounter = 0;; loopcounter++) {
 		spin_lock_irq(&bus->reg_lock);
-		if (bus->polling_mode)
+		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);
@@ -262,6 +266,23 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
 		}
 	}
 
+	if (!bus->polling_mode && bus->poll_count < 2) {
+		dev_dbg(bus->dev,
+			"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(bus->dev,
+			 "response timeout, switching to polling mode: last cmd=0x%08x\n",
+			 bus->last_cmd[addr]);
+		bus->polling_mode = 1;
+		goto again;
+	}
+
 	return -EIO;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response);
-- 
2.17.1

_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxx
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel



[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux