diff mbox

[v1,1/2] ASoC: rsnd: ssi: fix race condition in rsnd_ssi_pointer_update

Message ID 1512634956-17760-2-git-send-email-jiada_wang@mentor.com (mailing list archive)
State Accepted
Commit 33f801366bdf3f8b67dfe325b84f4051a090d01e
Headers show

Commit Message

Wang, Jiada Dec. 7, 2017, 8:22 a.m. UTC
From: Jiada Wang <jiada_wang@mentor.com>

Currently there is race condition between set of byte_pos and wrap
it around when new buffer starts. If .pointer is called in-between
it will result in inconsistent pointer position be returned
from .pointer callback.

This patch increments buffer pointer atomically to avoid this issue.

Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
Reviewed-by: Takashi Sakamoto <takashi.sakamoto@miraclelinux.com>
---
 sound/soc/sh/rcar/ssi.c |   16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

Comments

Kuninori Morimoto Dec. 7, 2017, 9:45 a.m. UTC | #1
Hi Jiada

Thank you for your patch

> Currently there is race condition between set of byte_pos and wrap
> it around when new buffer starts. If .pointer is called in-between
> it will result in inconsistent pointer position be returned
> from .pointer callback.
> 
> This patch increments buffer pointer atomically to avoid this issue.
> 
> Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
> Reviewed-by: Takashi Sakamoto <takashi.sakamoto@miraclelinux.com>
> ---

You using playback with PIO mode ?
Because this function is no longer used on DMA mode

Best regards
---
Kuninori Morimoto
Wang, Jiada Dec. 8, 2017, 5:35 a.m. UTC | #2
Hello Morimoto-san

On 12/07/2017 01:45 AM, Kuninori Morimoto wrote:
> Hi Jiada
>
> Thank you for your patch
>
>> Currently there is race condition between set of byte_pos and wrap
>> it around when new buffer starts. If .pointer is called in-between
>> it will result in inconsistent pointer position be returned
>> from .pointer callback.
>>
>> This patch increments buffer pointer atomically to avoid this issue.
>>
>> Signed-off-by: Jiada Wang<jiada_wang@mentor.com>
>> Reviewed-by: Takashi Sakamoto<takashi.sakamoto@miraclelinux.com>
>> ---
> You using playback with PIO mode ?
> Because this function is no longer used on DMA mode
No, we are using rcar sound in DMA mode,
our original patch resolves the issue in core.c for both PIO & DMA mode.

but with your commit a97a06c ("ASoC: rsnd: cleanup pointer related code"),
DMA mode no longer has the race condition issue,
so I ported our fix patch to only address the issue in PIO mode

Thanks,
Jiada
> Best regards
> ---
> Kuninori Morimoto
Kuninori Morimoto Dec. 8, 2017, 6 a.m. UTC | #3
Hi Jiada

> >> Currently there is race condition between set of byte_pos and wrap
> >> it around when new buffer starts. If .pointer is called in-between
> >> it will result in inconsistent pointer position be returned
> >> from .pointer callback.
> >>
> >> This patch increments buffer pointer atomically to avoid this issue.
> >>
> >> Signed-off-by: Jiada Wang<jiada_wang@mentor.com>
> >> Reviewed-by: Takashi Sakamoto<takashi.sakamoto@miraclelinux.com>
> >> ---
> > You using playback with PIO mode ?
> > Because this function is no longer used on DMA mode
> No, we are using rcar sound in DMA mode,
> our original patch resolves the issue in core.c for both PIO & DMA mode.
> 
> but with your commit a97a06c ("ASoC: rsnd: cleanup pointer related code"),
> DMA mode no longer has the race condition issue,
> so I ported our fix patch to only address the issue in PIO mode

Thanks. Nice to know.

Best regards
---
Kuninori Morimoto
diff mbox

Patch

diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index fece1e5f..cbf3bf3 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -446,25 +446,29 @@  static bool rsnd_ssi_pointer_update(struct rsnd_mod *mod,
 				    int byte)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	bool ret = false;
+	int byte_pos;
 
-	ssi->byte_pos += byte;
+	byte_pos = ssi->byte_pos + byte;
 
-	if (ssi->byte_pos >= ssi->next_period_byte) {
+	if (byte_pos >= ssi->next_period_byte) {
 		struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 
 		ssi->period_pos++;
 		ssi->next_period_byte += ssi->byte_per_period;
 
 		if (ssi->period_pos >= runtime->periods) {
-			ssi->byte_pos = 0;
+			byte_pos = 0;
 			ssi->period_pos = 0;
 			ssi->next_period_byte = ssi->byte_per_period;
 		}
 
-		return true;
+		ret = true;
 	}
 
-	return false;
+	WRITE_ONCE(ssi->byte_pos, byte_pos);
+
+	return ret;
 }
 
 /*
@@ -838,7 +842,7 @@  static int rsnd_ssi_pointer(struct rsnd_mod *mod,
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 
-	*pointer = bytes_to_frames(runtime, ssi->byte_pos);
+	*pointer = bytes_to_frames(runtime, READ_ONCE(ssi->byte_pos));
 
 	return 0;
 }