summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2016-02-24 19:10:39 -0800
committerStefan Agner <stefan.agner@toradex.com>2016-02-25 15:14:12 -0800
commit6a809632388255a171f94bca1c463ec04ec057a8 (patch)
tree1fcf76008cadec8ebbfeb57750d472c2ec7bb7ae /sound
parentf25d83e0b9220c718415b7af8c4dd9e510416c11 (diff)
ASoC: fsl_sai_ac97: add timeout for AC97 register read/writes
If the DMA has been activated but has not yet been started (e.g. due to missing bit clock), a read or write would loop forever. Avoid this by using a timeout counter. The AC97 core does opportunistic reads in some cases (e.g. when trying to determine if a cold reset is necessary, by just reading the ID register after the warm reset). Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/fsl/fsl_sai_ac97.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sound/soc/fsl/fsl_sai_ac97.c b/sound/soc/fsl/fsl_sai_ac97.c
index a46e11869a92..6ded58db4e15 100644
--- a/sound/soc/fsl/fsl_sai_ac97.c
+++ b/sound/soc/fsl/fsl_sai_ac97.c
@@ -307,6 +307,7 @@ static int vf610_sai_ac97_read_write(struct snd_ac97 *ac97, bool isread,
unsigned long flags;
int ret = 0;
int rxbufmaxcheck = 10;
+ int timeout = 10;
/*
* We need to disable interrupts to make sure we insert the message
@@ -359,7 +360,8 @@ static int vf610_sai_ac97_read_write(struct snd_ac97 *ac97, bool isread,
if (unlikely(txbufid < txbufidstart) &&
(curbufid > txbufid && curbufid < txbufidstart))
break;
- } while (true);
+ } while (--timeout);
+ ret = !timeout ? -ETIMEDOUT : 0;
goto clear_command;
}
@@ -387,7 +389,7 @@ static int vf610_sai_ac97_read_write(struct snd_ac97 *ac97, bool isread,
rxbufid = rxbufidstart;
curbufid = rxbufid;
do {
- while (rxbufid == curbufid)
+ while (rxbufid == curbufid && --timeout)
{
/* Wait for frames being transmitted/received... */
usleep_range(50, 200);
@@ -396,6 +398,11 @@ static int vf610_sai_ac97_read_write(struct snd_ac97 *ac97, bool isread,
curbufid = ((SAI_AC97_RBUF_SIZE_TOT - rx_state.residue) / SAI_AC97_DMABUF_SIZE);
}
+ if (!timeout) {
+ ret = -ETIMEDOUT;
+ goto clear_command;
+ }
+
/* Ok, check frames... */
rx_aclink = (struct ac97_rx *)(info->rx_buf.area + rxbufid * SAI_AC97_DMABUF_SIZE);
if (rx_aclink->slot_valid & (1 << 11 | 1 << 10) &&