[PATCH] ALSA: rawmidi: Work around false-positive mutex lockdep warning

Takashi Iwai <[email protected]> Thu, 6 Aug 2026 12:13:51 +0200
Newsgroups org.kernel.vger.linux-sound,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
When opening a legacy rawmidi device for a UMP, it may re-open an
existing rawmidi device for appending to a substream, leading to a
lockdep warning due to rmidi->open_mutex taken twice -- but the
rawmidi devices are completely individual, hence it's a
false-positive.

For avoiding the warning, modify the helper to open a rawmidi instance
with a proper locking subclass from the UMP legacy open.

Unfortunately, there is no good way to achieve it with guard(), so
reverted to the manual mutex calls again.

Reported-by: [email protected]
Closes: https://lore.kernel.org/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
---
 include/sound/rawmidi.h | 14 ++++++++++++--
 sound/core/rawmidi.c    | 12 +++++++-----
 sound/core/ump.c        |  9 +++++----
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 6916f7133597..88a6159364d0 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -176,8 +176,9 @@ int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream);
 /* main midi functions */
 
 int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info);
-int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice,
-			    int mode, struct snd_rawmidi_file *rfile);
+int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice,
+				   int mode, struct snd_rawmidi_file *rfile,
+				   int depth);
 int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile);
 int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
 			      struct snd_rawmidi_params *params);
@@ -191,6 +192,15 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
 long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,
 			      const unsigned char *buf, long count);
 
+/* non-nested version */
+static inline int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi,
+					  int subdevice,
+					  int mode,
+					  struct snd_rawmidi_file *rfile)
+{
+	return snd_rawmidi_kernel_open_nested(rmidi, subdevice, mode, rfile, 0);
+}
+
 /* set up the tied devices */
 static inline void snd_rawmidi_tie_devices(struct snd_rawmidi *r1,
 					   struct snd_rawmidi *r2)
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 1d55da2dcb01..bf504e27f73e 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -408,9 +408,10 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
 	return 0;
 }
 
-/* called from sound/core/seq/seq_midi.c */
-int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice,
-			    int mode, struct snd_rawmidi_file *rfile)
+/* called from sound/core/seq/seq_midi.c and sound/core/ump.c */
+int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice,
+				   int mode, struct snd_rawmidi_file *rfile,
+				   int depth)
 {
 	int err;
 
@@ -419,13 +420,14 @@ int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice,
 	if (!try_module_get(rmidi->card->module))
 		return -ENXIO;
 
-	guard(mutex)(&rmidi->open_mutex);
+	mutex_lock_nested(&rmidi->open_mutex, depth);
 	err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);
 	if (err < 0)
 		module_put(rmidi->card->module);
+	mutex_unlock(&rmidi->open_mutex);
 	return err;
 }
-EXPORT_SYMBOL(snd_rawmidi_kernel_open);
+EXPORT_SYMBOL(snd_rawmidi_kernel_open_nested);
 
 static int snd_rawmidi_open(struct inode *inode, struct file *file)
 {
diff --git a/sound/core/ump.c b/sound/core/ump.c
index 632c13baf21e..82ad155c56e6 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -1157,10 +1157,11 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
 		return -ENODEV;
 	if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) {
 		if (!ump->legacy_out_opens) {
-			err = snd_rawmidi_kernel_open(&ump->core, 0,
-						      SNDRV_RAWMIDI_LFLG_OUTPUT |
-						      SNDRV_RAWMIDI_LFLG_APPEND,
-						      &ump->legacy_out_rfile);
+			err = snd_rawmidi_kernel_open_nested(&ump->core, 0,
+							     SNDRV_RAWMIDI_LFLG_OUTPUT |
+							     SNDRV_RAWMIDI_LFLG_APPEND,
+							     &ump->legacy_out_rfile,
+							     SINGLE_DEPTH_NESTING);
 			if (err < 0)
 				return err;
 		}
-- 
2.55.0