Instead of recursively calling rz_ssi_pio_recv() use a loop instead to read the samples from RX fifo.
Inspiration for this patch is to avoid recursion, as recursion is unwelcome in kernel due to limited stack use. Also to add this driver will later be used on RZ/A2 SoC's which runs with limited memory.
This also fixes an issue where the return value of rz_ssi_pio_recv() was ignored when called recursively.
Fixes: 03e786bd4341 ("ASoC: sh: Add RZ/G2L SSIF-2 driver") Reported-by: Pavel Machek pavel@denx.de Signed-off-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com --- v1->v2 * Used a do while loop * Fixed comments pointed by Cezary. --- sound/soc/sh/rz-ssi.c | 65 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 34 deletions(-)
diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index fa0cc08f70ec..637802117c6c 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -414,51 +414,48 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) u16 *buf; int fifo_samples; int frames_left; - int samples = 0; + int samples; int i;
if (!rz_ssi_stream_is_valid(ssi, strm)) return -EINVAL;
runtime = substream->runtime; - /* frames left in this period */ - frames_left = runtime->period_size - (strm->buffer_pos % - runtime->period_size); - if (frames_left == 0) - frames_left = runtime->period_size;
- /* Samples in RX FIFO */ - fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >> - SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK; - - /* Only read full frames at a time */ - while (frames_left && (fifo_samples >= runtime->channels)) { - samples += runtime->channels; - fifo_samples -= runtime->channels; - frames_left--; - } - - /* not enough samples yet */ - if (samples == 0) - return 0; + do { + /* frames left in this period */ + frames_left = runtime->period_size - + (strm->buffer_pos % runtime->period_size); + if (!frames_left) + frames_left = runtime->period_size; + + /* Samples in RX FIFO */ + fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >> + SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK; + + /* Only read full frames at a time */ + samples = 0; + while (frames_left && (fifo_samples >= runtime->channels)) { + samples += runtime->channels; + fifo_samples -= runtime->channels; + frames_left--; + }
- /* calculate new buffer index */ - buf = (u16 *)(runtime->dma_area); - buf += strm->buffer_pos * runtime->channels; + /* not enough samples yet */ + if (!samples) + break;
- /* Note, only supports 16-bit samples */ - for (i = 0; i < samples; i++) - *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16); + /* calculate new buffer index */ + buf = (u16 *)runtime->dma_area; + buf += strm->buffer_pos * runtime->channels;
- rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); - rz_ssi_pointer_update(strm, samples / runtime->channels); + /* Note, only supports 16-bit samples */ + for (i = 0; i < samples; i++) + *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
- /* - * If we finished this period, but there are more samples in - * the RX FIFO, call this function again - */ - if (frames_left == 0 && fifo_samples >= runtime->channels) - rz_ssi_pio_recv(ssi, strm); + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); + rz_ssi_pointer_update(strm, samples / runtime->channels); + } while (!frames_left && fifo_samples >= runtime->channels);
return 0; }