From 6a809632388255a171f94bca1c463ec04ec057a8 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 24 Feb 2016 19:10:39 -0800 Subject: 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 --- sound/soc/fsl/fsl_sai_ac97.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'sound/soc/fsl') 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) && -- cgit v1.2.3