diff options
| author | Takashi Iwai <tiwai@suse.de> | 2019-02-06 01:30:44 -0500 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2019-02-08 10:54:31 -0500 |
| commit | 00a399cad1a063e7665f06b6497a807db20441fd (patch) | |
| tree | 8f2a341d6882481c2cccc2523912e06f7cba65ec | |
| parent | 0a5cf9e88b5178d15f00f3cf35081841d80403cd (diff) | |
ALSA: pcm: Revert capture stream behavior change in blocking mode
In the commit 62ba568f7aef ("ALSA: pcm: Return 0 when size <
start_threshold in capture"), we changed the behavior of
__snd_pcm_lib_xfer() to return immediately with 0 when a capture
stream has a high start_threshold. This was intended to be a
correction of the behavior consistency and looked harmless, but this
was the culprit of the recent breakage reported by syzkaller, which
was fixed by the commit e190161f96b8 ("ALSA: pcm: Fix tight loop of
OSS capture stream").
At the time for the OSS fix, I didn't touch the behavior for ALSA
native API, as assuming that this behavior actually is good. But this
turned out to be also broken actually for a similar deployment,
e.g. one thread goes to a write loop in blocking mode while another
thread controls the start/stop of the stream manually.
Overall, the original commit is harmful, and it brings less merit to
keep that behavior. Let's revert it.
Fixes: 62ba568f7aef ("ALSA: pcm: Return 0 when size < start_threshold in capture")
Fixes: e190161f96b8 ("ALSA: pcm: Fix tight loop of OSS capture stream")
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | sound/core/pcm_lib.c | 20 |
1 files changed, 4 insertions, 16 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 6c99fa8ac5fa..6c0b30391ba9 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
| @@ -2112,13 +2112,6 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, | |||
| 2112 | return 0; | 2112 | return 0; |
| 2113 | } | 2113 | } |
| 2114 | 2114 | ||
| 2115 | /* allow waiting for a capture stream that hasn't been started */ | ||
| 2116 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) | ||
| 2117 | #define wait_capture_start(substream) ((substream)->oss.oss) | ||
| 2118 | #else | ||
| 2119 | #define wait_capture_start(substream) false | ||
| 2120 | #endif | ||
| 2121 | |||
| 2122 | /* the common loop for read/write data */ | 2115 | /* the common loop for read/write data */ |
| 2123 | snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, | 2116 | snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, |
| 2124 | void *data, bool interleaved, | 2117 | void *data, bool interleaved, |
| @@ -2184,16 +2177,11 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, | |||
| 2184 | snd_pcm_update_hw_ptr(substream); | 2177 | snd_pcm_update_hw_ptr(substream); |
| 2185 | 2178 | ||
| 2186 | if (!is_playback && | 2179 | if (!is_playback && |
| 2187 | runtime->status->state == SNDRV_PCM_STATE_PREPARED) { | 2180 | runtime->status->state == SNDRV_PCM_STATE_PREPARED && |
| 2188 | if (size >= runtime->start_threshold) { | 2181 | size >= runtime->start_threshold) { |
| 2189 | err = snd_pcm_start(substream); | 2182 | err = snd_pcm_start(substream); |
| 2190 | if (err < 0) | 2183 | if (err < 0) |
| 2191 | goto _end_unlock; | ||
| 2192 | } else if (!wait_capture_start(substream)) { | ||
| 2193 | /* nothing to do */ | ||
| 2194 | err = 0; | ||
| 2195 | goto _end_unlock; | 2184 | goto _end_unlock; |
| 2196 | } | ||
| 2197 | } | 2185 | } |
| 2198 | 2186 | ||
| 2199 | avail = snd_pcm_avail(substream); | 2187 | avail = snd_pcm_avail(substream); |
