summaryrefslogtreecommitdiff
path: root/sound/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-12-12 20:11:00 +0100
committerTakashi Iwai <tiwai@suse.de>2019-12-13 14:36:44 +0100
commit89698ed5cc76d8de6c2b51d132c06bf4cd930314 (patch)
tree2d3217f19152cbeec9fa92f544ca555739e0f7e7 /sound/hda
parent341a79ee8b080ed41dccc13250fcffc2c2028ccd (diff)
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 88452da92ba2 ("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: Kai Vehmanen <kai.vehmanen@linux.intel.com> Link: https://lore.kernel.org/r/20191212191101.19517-2-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/hda')
-rw-r--r--sound/hda/hdac_controller.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index cd1c3b282657..61950b83b8c9 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -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);