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.
Unified · Split
| @@ -176,8 +176,9 @@ int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream); · 175 unmodified lines | |||
| 176 | /* main midi functions */ | 176 | /* main midi functions */ |
| 177 | 177 | ||
| 178 | int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info); | 178 | int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info); |
| 179 | int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice, | 179 | int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice, |
| 180 | int mode, struct snd_rawmidi_file *rfile); | 180 | int mode, struct snd_rawmidi_file *rfile, |
| 181 | int depth); | ||
| 181 | int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile); | 182 | int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile); |
| 182 | int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, | 183 | int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, |
| 183 | struct snd_rawmidi_params *params); | 184 | struct snd_rawmidi_params *params); |
| @@ -191,6 +192,15 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream, · 7 unmodified lines | |||
| 191 | long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, | 192 | long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, |
| 192 | const unsigned char *buf, long count); | 193 | const unsigned char *buf, long count); |
| 193 | 194 | ||
| 195 | /* non-nested version */ | ||
| 196 | static inline int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, | ||
| 197 | int subdevice, | ||
| 198 | int mode, | ||
| 199 | struct snd_rawmidi_file *rfile) | ||
| 200 | { | ||
| 201 | return snd_rawmidi_kernel_open_nested(rmidi, subdevice, mode, rfile, 0); | ||
| 202 | } | ||
| 203 | |||
| 194 | /* set up the tied devices */ | 204 | /* set up the tied devices */ |
| 195 | static inline void snd_rawmidi_tie_devices(struct snd_rawmidi *r1, | 205 | static inline void snd_rawmidi_tie_devices(struct snd_rawmidi *r1, |
| 196 | struct snd_rawmidi *r2) | 206 | struct snd_rawmidi *r2) |
| @@ -408,9 +408,10 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, · 407 unmodified lines | |||
| 408 | return 0; | 408 | return 0; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | /* called from sound/core/seq/seq_midi.c */ | 411 | /* called from sound/core/seq/seq_midi.c and sound/core/ump.c */ |
| 412 | int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice, | 412 | int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice, |
| 413 | int mode, struct snd_rawmidi_file *rfile) | 413 | int mode, struct snd_rawmidi_file *rfile, |
| 414 | int depth) | ||
| 414 | { | 415 | { |
| 415 | int err; | 416 | int err; |
| 416 | 417 | ||
| @@ -419,13 +420,14 @@ int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice, · 2 unmodified lines | |||
| 419 | if (!try_module_get(rmidi->card->module)) | 420 | if (!try_module_get(rmidi->card->module)) |
| 420 | return -ENXIO; | 421 | return -ENXIO; |
| 421 | 422 | ||
| 422 | guard(mutex)(&rmidi->open_mutex); | 423 | mutex_lock_nested(&rmidi->open_mutex, depth); |
| 423 | err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); | 424 | err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); |
| 424 | if (err < 0) | 425 | if (err < 0) |
| 425 | module_put(rmidi->card->module); | 426 | module_put(rmidi->card->module); |
| 427 | mutex_unlock(&rmidi->open_mutex); | ||
| 426 | return err; | 428 | return err; |
| 427 | } | 429 | } |
| 428 | EXPORT_SYMBOL(snd_rawmidi_kernel_open); | 430 | EXPORT_SYMBOL(snd_rawmidi_kernel_open_nested); |
| 429 | 431 | ||
| 430 | static int snd_rawmidi_open(struct inode *inode, struct file *file) | 432 | static int snd_rawmidi_open(struct inode *inode, struct file *file) |
| 431 | { | 433 | { |
| @@ -1157,10 +1157,11 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream) · 1156 unmodified lines | |||
| 1157 | return -ENODEV; | 1157 | return -ENODEV; |
| 1158 | if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) { | 1158 | if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) { |
| 1159 | if (!ump->legacy_out_opens) { | 1159 | if (!ump->legacy_out_opens) { |
| 1160 | err = snd_rawmidi_kernel_open(&ump->core, 0, | 1160 | err = snd_rawmidi_kernel_open_nested(&ump->core, 0, |
| 1161 | SNDRV_RAWMIDI_LFLG_OUTPUT | | 1161 | SNDRV_RAWMIDI_LFLG_OUTPUT | |
| 1162 | SNDRV_RAWMIDI_LFLG_APPEND, | 1162 | SNDRV_RAWMIDI_LFLG_APPEND, |
| 1163 | &ump->legacy_out_rfile); | 1163 | &ump->legacy_out_rfile, |
| 1164 | SINGLE_DEPTH_NESTING); | ||
| 1164 | if (err < 0) | 1165 | if (err < 0) |
| 1165 | return err; | 1166 | return err; |
| 1166 | } | 1167 | } |