linux-stable/sound
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
..
aoa ALSA: aoa: onyx: always initialize register read value 2020-01-27 14:46:41 +01:00
arm
atmel
core ALSA: pcm: fix incorrect hw_base increase 2020-05-27 16:43:07 +02:00
drivers ALSA: dummy: Fix PCM format loop in proc output 2020-02-14 16:32:08 -05:00
firewire ALSA: firewire-motu: Correct a typo in the clock proc string 2020-01-09 10:17:56 +01:00
hda ALSA: hda: Use scnprintf() for printing texts for sysfs/procfs 2020-02-28 16:35:51 +01:00
i2c ALSA: i2c/cs8427: Fix int to char conversion 2019-12-01 09:13:39 +01:00
isa ALSA: opti9xx: shut up gcc-10 range warning 2020-05-05 19:15:52 +02:00
mips
oss
parisc
pci ALSA: iec1712: Initialize STDSP24 properly when using the model=staudio option 2020-05-27 16:43:07 +02:00
pcmcia
ppc
sh ALSA: sh: Fix compile warning wrt const 2020-02-28 16:36:02 +01:00
soc ASoC: codecs: hdac_hdmi: Fix incorrect use of list_for_each_entry 2020-05-10 10:28:59 +02:00
sparc
spi
synth
usb ALSA: usb-audio: Add control message quirk delay for Kingston HyperX headset 2020-05-20 08:17:15 +02:00
x86
ac97_bus.c
Kconfig
last.c
Makefile
sound_core.c sound: fix a memory leak bug 2019-08-16 10:13:46 +02:00