[PATCH 06/11] ALSA: caiaq: Fix races at MIDI URB and trigger accesses
From: Takashi Iwai
Date: Thu Oct 08 2026 - 15:28:45 EST
URB completion and rawmidi trigger callbacks can race with each other,
which may put the state inconsistent, causing double submissions, etc.
Guard both with a new spinlock for avoiding the races.
Fixes: f3f80a9205da ("ALSA: caiaq - Fix Oops with MIDI")
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
---
sound/usb/caiaq/device.c | 1 +
sound/usb/caiaq/device.h | 3 ++-
sound/usb/caiaq/midi.c | 2 ++
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index c68ed16d7ac4..634dc36f2ead 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -455,6 +455,7 @@ static int create_card(struct usb_device *usb_dev,
cdev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct));
spin_lock_init(&cdev->spinlock);
+ spin_lock_init(&cdev->midi_lock);
mutex_init(&cdev->ep1_out_mutex);
*cardp = card;
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index dd726ca68e80..16f65e7867d1 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -77,7 +77,8 @@ struct snd_usb_caiaqdev {
unsigned char midi_out_buf[EP1_BUFSIZE];
struct caiaq_device_spec spec;
- spinlock_t spinlock;
+ spinlock_t spinlock; /* for PCM audio */
+ spinlock_t midi_lock; /* midi_x_stream, midi_out_active */
wait_queue_head_t ep1_wait_queue;
wait_queue_head_t prepare_wait_queue;
int spec_received, audio_parm_answer;
diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c
index 18529484c8dc..b7d7d24937a7 100644
--- a/sound/usb/caiaq/midi.c
+++ b/sound/usb/caiaq/midi.c
@@ -79,6 +79,7 @@ static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *subs
{
struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
+ guard(spinlock_irqsave)(&cdev->midi_lock);
if (up) {
cdev->midi_out_substream = substream;
if (!cdev->midi_out_active)
@@ -151,6 +152,7 @@ void snd_usb_caiaq_midi_output_done(struct urb* urb)
{
struct snd_usb_caiaqdev *cdev = urb->context;
+ guard(spinlock_irqsave)(&cdev->midi_lock);
cdev->midi_out_active = 0;
if (urb->status != 0)
return;
--
2.55.0