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

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.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 341a79ee
...@@ -241,30 +241,42 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, ...@@ -241,30 +241,42 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
{ {
unsigned long timeout; unsigned long timeout;
unsigned long loopcounter; unsigned long loopcounter;
wait_queue_entry_t wait;
init_wait_entry(&wait, 0);
timeout = jiffies + msecs_to_jiffies(1000); timeout = jiffies + msecs_to_jiffies(1000);
for (loopcounter = 0;; loopcounter++) { for (loopcounter = 0;; loopcounter++) {
spin_lock_irq(&bus->reg_lock); spin_lock_irq(&bus->reg_lock);
if (!bus->polling_mode)
prepare_to_wait(&bus->rirb_wq, &wait,
TASK_UNINTERRUPTIBLE);
if (bus->polling_mode) if (bus->polling_mode)
snd_hdac_bus_update_rirb(bus); snd_hdac_bus_update_rirb(bus);
if (!bus->rirb.cmds[addr]) { if (!bus->rirb.cmds[addr]) {
if (res) if (res)
*res = bus->rirb.res[addr]; /* the last value */ *res = bus->rirb.res[addr]; /* the last value */
if (!bus->polling_mode)
finish_wait(&bus->rirb_wq, &wait);
spin_unlock_irq(&bus->reg_lock); spin_unlock_irq(&bus->reg_lock);
return 0; return 0;
} }
spin_unlock_irq(&bus->reg_lock); spin_unlock_irq(&bus->reg_lock);
if (time_after(jiffies, timeout)) if (time_after(jiffies, timeout))
break; break;
if (loopcounter > 3000) if (!bus->polling_mode) {
schedule_timeout(msecs_to_jiffies(2));
} else if (loopcounter > 3000) {
msleep(2); /* temporary workaround */ msleep(2); /* temporary workaround */
else { } else {
udelay(10); udelay(10);
cond_resched(); cond_resched();
} }
} }
if (!bus->polling_mode)
finish_wait(&bus->rirb_wq, &wait);
return -EIO; return -EIO;
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response); EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment