]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ALSA: ice1724: Fix blocking open for independent surround PCMs
authorCássio Gabriel <cassiogabrielcontato@gmail.com>
Mon, 18 May 2026 14:32:05 +0000 (11:32 -0300)
committerTakashi Iwai <tiwai@suse.de>
Tue, 19 May 2026 05:37:59 +0000 (07:37 +0200)
The independent surround playback open path rejects a substream when the
matching PDMA channel is reserved by the multi-channel PDMA0 stream. It
currently returns -EBUSY for that case, although the driver has carried a
FIXME noting that blocking mode is not handled properly.

ALSA PCM open waits and retries only when the low-level open callback
returns -EAGAIN. Returning -EBUSY therefore makes blocking opens fail
immediately, the same as nonblocking opens.

Return -EAGAIN for the temporary PDMA0 reservation conflict. The PCM core
continues to report -EBUSY for O_NONBLOCK callers, while blocking callers
sleep and retry.

Also wake the independent surround PCM wait queue when hw_free releases a
PDMA reservation. The reservation can be released by the pro PCM, while
waiters are sleeping on the independent surround PCM, so waking the current
substream PCM is not sufficient for this cross-PCM reservation.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260518-ice1724-blocking-open-v1-1-1bfa3e5aa7cf@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/ice1712/ice1724.c

index 2e64f9c020e5a10acd9de7aca0a57d76b5c706ef..79d57938a1c8cb9bbec601ee99cb345e56e1bf9b 100644 (file)
@@ -730,13 +730,22 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream,
 static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+       bool released = false;
        int i;
 
-       guard(mutex)(&ice->open_mutex);
-       /* unmark surround channels */
-       for (i = 0; i < 3; i++)
-               if (ice->pcm_reserved[i] == substream)
+       scoped_guard(mutex, &ice->open_mutex) {
+               /* unmark surround channels */
+               for (i = 0; i < 3; i++) {
+                       if (ice->pcm_reserved[i] != substream)
+                               continue;
                        ice->pcm_reserved[i] = NULL;
+                       released = true;
+               }
+       }
+
+       if (released && ice->pcm_ds)
+               wake_up(&ice->pcm_ds->open_wait);
+
        return 0;
 }
 
@@ -1364,7 +1373,7 @@ static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream)
        scoped_guard(mutex, &ice->open_mutex) {
                /* already used by PDMA0? */
                if (ice->pcm_reserved[substream->number])
-                       return -EBUSY; /* FIXME: should handle blocking mode properly */
+                       return -EAGAIN;
        }
        runtime->private_data = (void *)&vt1724_playback_dma_regs[substream->number];
        ice->playback_con_substream_ds[substream->number] = substream;