linux-stable/sound/core
Brent Lu d50e6fcf8f ALSA: pcm: fix incorrect hw_base increase
commit e7513c5786 upstream.

There is a corner case that ALSA keeps increasing the hw_ptr but DMA
already stop working/updating the position for a long time.

In following log we can see the position returned from DMA driver does
not move at all but the hw_ptr got increased at some point of time so
snd_pcm_avail() will return a large number which seems to be a buffer
underrun event from user space program point of view. The program
thinks there is space in the buffer and fill more data.

[  418.510086] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 4096 avail 12368
[  418.510149] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 6910 avail 9554
...
[  418.681052] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 15102 avail 1362
[  418.681130] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 16464 avail 0
[  418.726515] sound pcmC0D5p: pos 96 hw_ptr 16464 appl_ptr 16464 avail 16368

This is because the hw_base will be increased by runtime->buffer_size
frames unconditionally if the hw_ptr is not updated for over half of
buffer time. As the hw_base increases, so does the hw_ptr increased
by the same number.

The avail value returned from snd_pcm_avail() could exceed the limit
(buffer_size) easily becase the hw_ptr itself got increased by same
buffer_size samples when the corner case happens. In following log,
the buffer_size is 16368 samples but the avail is 21810 samples so
CRAS server complains about it.

[  418.851755] sound pcmC0D5p: pos 96 hw_ptr 16464 appl_ptr 27390 avail 5442
[  418.926491] sound pcmC0D5p: pos 96 hw_ptr 32832 appl_ptr 27390 avail 21810

cras_server[1907]: pcm_avail returned frames larger than buf_size:
sof-glkda7219max: :0,5: 21810 > 16368

By updating runtime->hw_ptr_jiffies each time the HWSYNC is called,
the hw_base will keep the same when buffer stall happens at long as
the interval between each HWSYNC call is shorter than half of buffer
time.

Following is a log captured by a patched kernel. The hw_base/hw_ptr
value is fixed in this corner case and user space program should be
aware of the buffer stall and handle it.

[  293.525543] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 4096 avail 12368
[  293.525606] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 6880 avail 9584
[  293.525975] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 10976 avail 5488
[  293.611178] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 15072 avail 1392
[  293.696429] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 16464 avail 0
...
[  381.139517] sound pcmC0D5p: pos 96 hw_ptr 96 appl_ptr 16464 avail 0

Signed-off-by: Brent Lu <brent.lu@intel.com>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/1589776238-23877-1-git-send-email-brent.lu@intel.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-05-27 16:43:07 +02:00
..
oss ALSA: pcm: oss: Place the plugin buffer overflow checks correctly 2020-05-05 19:15:50 +02:00
seq ALSA: seq: oss: Fix running status after receiving sysex 2020-04-02 16:34:17 +02:00
compress_offload.c ASoC: compress: fix unsigned integer overflow check 2019-12-05 15:36:48 +01:00
control.c ALSA: ctl: allow TLV read operation for callback type of element in locked case 2020-02-28 16:35:55 +01:00
control_compat.c ALSA: control: fix a redundant-copy issue 2018-05-22 18:53:56 +02:00
ctljack.c
device.c
hrtimer.c ALSA: timer: Limit max instances per timer 2017-11-06 10:41:24 +01:00
hwdep.c
hwdep_compat.c
info.c ALSA: info: Fix racy addition/deletion of nodes 2019-04-27 09:35:41 +02:00
info_oss.c
init.c ALSA: core: Fix card races between register and disconnect 2019-04-27 09:35:37 +02:00
isadma.c
jack.c
Kconfig
Makefile
memalloc.c ALSA: memalloc: Don't exceed over the requested size 2018-08-22 07:46:10 +02:00
memory.c
misc.c
pcm.c ALSA: pcm: Fix potential Spectre v1 vulnerability 2019-01-09 17:14:46 +01:00
pcm_compat.c ALSA: pcm: Check PCM state at xfern compat ioctl 2018-05-09 09:51:49 +02:00
pcm_dmaengine.c
pcm_drm_eld.c
pcm_iec958.c
pcm_lib.c ALSA: pcm: fix incorrect hw_base increase 2020-05-27 16:43:07 +02:00
pcm_local.h
pcm_memory.c
pcm_misc.c
pcm_native.c ALSA: pcm: Avoid possible info leaks from PCM stream buffers 2019-12-31 12:36:45 +01:00
pcm_param_trace.h
pcm_timer.c
pcm_trace.h
rawmidi.c ALSA: rawmidi: Fix racy buffer resize under concurrent accesses 2020-05-20 08:17:14 +02:00
rawmidi_compat.c ALSA: rawmidi: Fix missing input substream checks in compat ioctls 2018-04-24 09:36:36 +02:00
seq_device.c
sgbuf.c
sound.c
sound_oss.c
timer.c ALSA: timer: Limit max amount of slave instances 2019-12-31 12:37:23 +01:00
timer_compat.c ALSA: timer: Remove kernel warning at compat ioctl error paths 2017-11-30 08:40:48 +00:00
vmaster.c ALSA: vmaster: Propagate slave error 2018-05-30 07:52:35 +02:00