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

Takashi Iwai <[email protected]>
Newsgroups gmane.linux.sound,gmane.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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.