summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCássio Gabriel <cassiogabrielcontato@gmail.com>2026-05-04 17:08:45 +0300
committerTakashi Iwai <tiwai@suse.de>2026-05-04 18:49:16 +0300
commitf3c57c9c2a49a21d784b7c04a2c883bffc070659 (patch)
tree8e36d56e54240a710c3ed689f260064d9e2a0d0d
parentdc1e0172be54e742bccb28d5f14c0c395e28c098 (diff)
downloadlinux-f3c57c9c2a49a21d784b7c04a2c883bffc070659.tar.xz
ALSA: usb-audio: midi2: Restart output URBs on resume
USB MIDI 2.0 suspend saves the endpoint running state, clears it and kills all endpoint URBs. Resume restores the running state, but only restarts input endpoints. For a running output endpoint, this leaves the endpoint marked running with an empty URB queue. Output transfer progress depends on either the rawmidi trigger path starting the queue or an output completion refilling it. After suspend there is no completion left, and output data that remains queued in the raw UMP or legacy rawmidi buffer can stay stalled until userspace happens to trigger the stream again. Restore the saved state with atomic accessors, keep input endpoints restarted as before, and restart output endpoints that were running before suspend. Clear the saved suspend state after restoring it. Fixes: ff49d1df79ae ("ALSA: usb-audio: USB MIDI 2.0 UMP support") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com> Link: https://patch.msgid.link/20260504-usb-midi2-output-resume-v1-1-c089cc8ad3c6@gmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/midi2.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/sound/usb/midi2.c b/sound/usb/midi2.c
index 3546ba926cb3..2785600d2312 100644
--- a/sound/usb/midi2.c
+++ b/sound/usb/midi2.c
@@ -227,7 +227,7 @@ static void kill_midi_urbs(struct snd_usb_midi2_endpoint *ep, bool suspending)
if (!ep)
return;
if (suspending)
- ep->suspended = ep->running;
+ atomic_set(&ep->suspended, atomic_read(&ep->running));
atomic_set(&ep->running, 0);
for (i = 0; i < ep->num_urbs; i++) {
if (!ep->urbs[i].urb)
@@ -1188,10 +1188,11 @@ void snd_usb_midi_v2_suspend_all(struct snd_usb_audio *chip)
static void resume_midi2_endpoint(struct snd_usb_midi2_endpoint *ep)
{
- ep->running = ep->suspended;
- if (ep->direction == STR_IN)
+ atomic_set(&ep->running, atomic_read(&ep->suspended));
+ atomic_set(&ep->suspended, 0);
+
+ if (ep->direction == STR_IN || atomic_read(&ep->running))
submit_io_urbs(ep);
- /* FIXME: does it all? */
}
void snd_usb_midi_v2_resume_all(struct snd_usb_audio *chip)