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 | 176 | /* main midi functions */ |
| 177 | 177 | |
| 178 | 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, | |
| 180 | − int mode, struct snd_rawmidi_file *rfile); | |
| 179 | +int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice, | |
| 180 | + int mode, struct snd_rawmidi_file *rfile, | |
| 181 | + int depth); | |
| 181 | 182 | int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile); |
| 182 | 183 | int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, |
| 183 | 184 | struct snd_rawmidi_params *params); |
| @@ -191,6 +192,15 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream, · 7 unmodified lines | ||
| 191 | 192 | long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, |
| 192 | 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 | 204 | /* set up the tied devices */ |
| 195 | 205 | static inline void snd_rawmidi_tie_devices(struct snd_rawmidi *r1, |
| 196 | 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 | 408 | return 0; |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | −/* called from sound/core/seq/seq_midi.c */ | |
| 412 | −int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice, | |
| 413 | − int mode, struct snd_rawmidi_file *rfile) | |
| 411 | +/* called from sound/core/seq/seq_midi.c and sound/core/ump.c */ | |
| 412 | +int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice, | |
| 413 | + int mode, struct snd_rawmidi_file *rfile, | |
| 414 | + int depth) | |
| 414 | 415 | { |
| 415 | 416 | int err; |
| 416 | 417 | |
| @@ -419,13 +420,14 @@ int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice, · 2 unmodified lines | ||
| 419 | 420 | if (!try_module_get(rmidi->card->module)) |
| 420 | 421 | return -ENXIO; |
| 421 | 422 | |
| 422 | − guard(mutex)(&rmidi->open_mutex); | |
| 423 | + mutex_lock_nested(&rmidi->open_mutex, depth); | |
| 423 | 424 | err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); |
| 424 | 425 | if (err < 0) |
| 425 | 426 | module_put(rmidi->card->module); |
| 427 | + mutex_unlock(&rmidi->open_mutex); | |
| 426 | 428 | return err; |
| 427 | 429 | } |
| 428 | −EXPORT_SYMBOL(snd_rawmidi_kernel_open); | |
| 430 | +EXPORT_SYMBOL(snd_rawmidi_kernel_open_nested); | |
| 429 | 431 | |
| 430 | 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 | 1157 | return -ENODEV; |
| 1158 | 1158 | if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) { |
| 1159 | 1159 | if (!ump->legacy_out_opens) { |
| 1160 | − err = snd_rawmidi_kernel_open(&ump->core, 0, | |
| 1161 | − SNDRV_RAWMIDI_LFLG_OUTPUT | | |
| 1162 | − SNDRV_RAWMIDI_LFLG_APPEND, | |
| 1163 | − &ump->legacy_out_rfile); | |
| 1160 | + err = snd_rawmidi_kernel_open_nested(&ump->core, 0, | |
| 1161 | + SNDRV_RAWMIDI_LFLG_OUTPUT | | |
| 1162 | + SNDRV_RAWMIDI_LFLG_APPEND, | |
| 1163 | + &ump->legacy_out_rfile, | |
| 1164 | + SINGLE_DEPTH_NESTING); | |
| 1164 | 1165 | if (err < 0) |
| 1165 | 1166 | return err; |
| 1166 | 1167 | } |