]>
Commit | Line | Data |
---|---|---|
74d76b87 GKH |
1 | From 113ce08109f8e3b091399e7cc32486df1cff48e7 Mon Sep 17 00:00:00 2001 |
2 | From: Takashi Iwai <tiwai@suse.de> | |
3 | Date: Mon, 25 Mar 2019 10:38:58 +0100 | |
4 | Subject: ALSA: pcm: Don't suspend stream in unrecoverable PCM state | |
5 | ||
6 | From: Takashi Iwai <tiwai@suse.de> | |
7 | ||
8 | commit 113ce08109f8e3b091399e7cc32486df1cff48e7 upstream. | |
9 | ||
10 | Currently PCM core sets each opened stream forcibly to SUSPENDED state | |
11 | via snd_pcm_suspend_all() call, and the user-space is responsible for | |
12 | re-triggering the resume manually either via snd_pcm_resume() or | |
13 | prepare call. The scheme works fine usually, but there are corner | |
14 | cases where the stream can't be resumed by that call: the streams | |
15 | still in OPEN state before finishing hw_params. When they are | |
16 | suspended, user-space cannot perform resume or prepare because they | |
17 | haven't been set up yet. The only possible recovery is to re-open the | |
18 | device, which isn't nice at all. Similarly, when a stream is in | |
19 | DISCONNECTED state, it makes no sense to change it to SUSPENDED | |
20 | state. Ditto for in SETUP state; which you can re-prepare directly. | |
21 | ||
22 | So, this patch addresses these issues by filtering the PCM streams to | |
23 | be suspended by checking the PCM state. When a stream is in either | |
24 | OPEN, SETUP or DISCONNECTED as well as already SUSPENDED, the suspend | |
25 | action is skipped. | |
26 | ||
27 | To be noted, this problem was originally reported for the PCM runtime | |
28 | PM on HD-audio. And, the runtime PM problem itself was already | |
29 | addressed (although not intended) by the code refactoring commits | |
30 | 3d21ef0b49f8 ("ALSA: pcm: Suspend streams globally via device type PM | |
31 | ops") and 17bc4815de58 ("ALSA: pci: Remove superfluous | |
32 | snd_pcm_suspend*() calls"). These commits eliminated the | |
33 | snd_pcm_suspend*() calls from the runtime PM suspend callback code | |
34 | path, hence the racy OPEN state won't appear while runtime PM. | |
35 | (FWIW, the race window is between snd_pcm_open_substream() and the | |
36 | first power up in azx_pcm_open().) | |
37 | ||
38 | Although the runtime PM issue was already "fixed", the same problem is | |
39 | still present for the system PM, hence this patch is still needed. | |
40 | And for stable trees, this patch alone should suffice for fixing the | |
41 | runtime PM problem, too. | |
42 | ||
43 | Reported-and-tested-by: Jon Hunter <jonathanh@nvidia.com> | |
44 | Cc: <stable@vger.kernel.org> | |
45 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | |
46 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
47 | ||
48 | --- | |
49 | sound/core/pcm_native.c | 9 ++++++++- | |
50 | 1 file changed, 8 insertions(+), 1 deletion(-) | |
51 | ||
52 | --- a/sound/core/pcm_native.c | |
53 | +++ b/sound/core/pcm_native.c | |
54 | @@ -1426,8 +1426,15 @@ static int snd_pcm_pause(struct snd_pcm_ | |
55 | static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state) | |
56 | { | |
57 | struct snd_pcm_runtime *runtime = substream->runtime; | |
58 | - if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) | |
59 | + switch (runtime->status->state) { | |
60 | + case SNDRV_PCM_STATE_SUSPENDED: | |
61 | return -EBUSY; | |
62 | + /* unresumable PCM state; return -EBUSY for skipping suspend */ | |
63 | + case SNDRV_PCM_STATE_OPEN: | |
64 | + case SNDRV_PCM_STATE_SETUP: | |
65 | + case SNDRV_PCM_STATE_DISCONNECTED: | |
66 | + return -EBUSY; | |
67 | + } | |
68 | runtime->trigger_master = substream; | |
69 | return 0; | |
70 | } |