Commit 89698ed5 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda: Use waitqueue for RIRB in HDA-core helper, too



This patch implements the same logic that was done for the legacy
HD-audio controller driver by the commit 88452da9 ("ALSA: hda: Use
standard waitqueue for RIRB wakeup") to the HDA-core helper code,
too.  This makes snd_hdac_bus_get_response() waiting for the response
with bus->rirb_wq instead of polling when bus->polling is false.
It'll save both CPU time and response latency.

Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/20191212191101.19517-2-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 341a79ee
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -241,30 +241,42 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
{
	unsigned long timeout;
	unsigned long loopcounter;
	wait_queue_entry_t wait;

	init_wait_entry(&wait, 0);
	timeout = jiffies + msecs_to_jiffies(1000);

	for (loopcounter = 0;; loopcounter++) {
		spin_lock_irq(&bus->reg_lock);
		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 (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;
		}
		spin_unlock_irq(&bus->reg_lock);
		if (time_after(jiffies, timeout))
			break;
		if (loopcounter > 3000)
		if (!bus->polling_mode) {
			schedule_timeout(msecs_to_jiffies(2));
		} else if (loopcounter > 3000) {
			msleep(2); /* temporary workaround */
		else {
		} else {
			udelay(10);
			cond_resched();
		}
	}

	if (!bus->polling_mode)
		finish_wait(&bus->rirb_wq, &wait);

	return -EIO;
}
EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response);