diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2016-02-24 19:10:39 -0800 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2016-02-25 15:14:12 -0800 |
commit | 6a809632388255a171f94bca1c463ec04ec057a8 (patch) | |
tree | 1fcf76008cadec8ebbfeb57750d472c2ec7bb7ae /sound/soc/fsl | |
parent | f25d83e0b9220c718415b7af8c4dd9e510416c11 (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/soc/fsl')
-rw-r--r-- | sound/soc/fsl/fsl_sai_ac97.c | 11 |
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) && |