| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * OSS compatible sequencer driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * MIDI device handlers |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | | - * |
|---|
| 18 | | - * You should have received a copy of the GNU General Public License |
|---|
| 19 | | - * along with this program; if not, write to the Free Software |
|---|
| 20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 21 | 8 | */ |
|---|
| 22 | 9 | |
|---|
| 23 | 10 | #include <sound/asoundef.h> |
|---|
| .. | .. |
|---|
| 50 | 37 | struct snd_midi_event *coder; /* MIDI event coder */ |
|---|
| 51 | 38 | struct seq_oss_devinfo *devinfo; /* assigned OSSseq device */ |
|---|
| 52 | 39 | snd_use_lock_t use_lock; |
|---|
| 40 | + struct mutex open_mutex; |
|---|
| 53 | 41 | }; |
|---|
| 54 | 42 | |
|---|
| 55 | 43 | |
|---|
| .. | .. |
|---|
| 184 | 172 | mdev->flags = pinfo->capability; |
|---|
| 185 | 173 | mdev->opened = 0; |
|---|
| 186 | 174 | snd_use_lock_init(&mdev->use_lock); |
|---|
| 175 | + mutex_init(&mdev->open_mutex); |
|---|
| 187 | 176 | |
|---|
| 188 | 177 | /* copy and truncate the name of synth device */ |
|---|
| 189 | 178 | strlcpy(mdev->name, pinfo->name, sizeof(mdev->name)); |
|---|
| .. | .. |
|---|
| 280 | 269 | void |
|---|
| 281 | 270 | snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp) |
|---|
| 282 | 271 | { |
|---|
| 272 | + spin_lock_irq(®ister_lock); |
|---|
| 283 | 273 | dp->max_mididev = max_midi_devs; |
|---|
| 274 | + spin_unlock_irq(®ister_lock); |
|---|
| 284 | 275 | } |
|---|
| 285 | 276 | |
|---|
| 286 | 277 | /* |
|---|
| .. | .. |
|---|
| 330 | 321 | int perm; |
|---|
| 331 | 322 | struct seq_oss_midi *mdev; |
|---|
| 332 | 323 | struct snd_seq_port_subscribe subs; |
|---|
| 324 | + int err; |
|---|
| 333 | 325 | |
|---|
| 334 | 326 | if ((mdev = get_mididev(dp, dev)) == NULL) |
|---|
| 335 | 327 | return -ENODEV; |
|---|
| 336 | 328 | |
|---|
| 329 | + mutex_lock(&mdev->open_mutex); |
|---|
| 337 | 330 | /* already used? */ |
|---|
| 338 | 331 | if (mdev->opened && mdev->devinfo != dp) { |
|---|
| 339 | | - snd_use_lock_free(&mdev->use_lock); |
|---|
| 340 | | - return -EBUSY; |
|---|
| 332 | + err = -EBUSY; |
|---|
| 333 | + goto unlock; |
|---|
| 341 | 334 | } |
|---|
| 342 | 335 | |
|---|
| 343 | 336 | perm = 0; |
|---|
| .. | .. |
|---|
| 347 | 340 | perm |= PERM_READ; |
|---|
| 348 | 341 | perm &= mdev->flags; |
|---|
| 349 | 342 | if (perm == 0) { |
|---|
| 350 | | - snd_use_lock_free(&mdev->use_lock); |
|---|
| 351 | | - return -ENXIO; |
|---|
| 343 | + err = -ENXIO; |
|---|
| 344 | + goto unlock; |
|---|
| 352 | 345 | } |
|---|
| 353 | 346 | |
|---|
| 354 | 347 | /* already opened? */ |
|---|
| 355 | 348 | if ((mdev->opened & perm) == perm) { |
|---|
| 356 | | - snd_use_lock_free(&mdev->use_lock); |
|---|
| 357 | | - return 0; |
|---|
| 349 | + err = 0; |
|---|
| 350 | + goto unlock; |
|---|
| 358 | 351 | } |
|---|
| 359 | 352 | |
|---|
| 360 | 353 | perm &= ~mdev->opened; |
|---|
| .. | .. |
|---|
| 379 | 372 | } |
|---|
| 380 | 373 | |
|---|
| 381 | 374 | if (! mdev->opened) { |
|---|
| 382 | | - snd_use_lock_free(&mdev->use_lock); |
|---|
| 383 | | - return -ENXIO; |
|---|
| 375 | + err = -ENXIO; |
|---|
| 376 | + goto unlock; |
|---|
| 384 | 377 | } |
|---|
| 385 | 378 | |
|---|
| 386 | 379 | mdev->devinfo = dp; |
|---|
| 380 | + err = 0; |
|---|
| 381 | + |
|---|
| 382 | + unlock: |
|---|
| 383 | + mutex_unlock(&mdev->open_mutex); |
|---|
| 387 | 384 | snd_use_lock_free(&mdev->use_lock); |
|---|
| 388 | | - return 0; |
|---|
| 385 | + return err; |
|---|
| 389 | 386 | } |
|---|
| 390 | 387 | |
|---|
| 391 | 388 | /* |
|---|
| .. | .. |
|---|
| 399 | 396 | |
|---|
| 400 | 397 | if ((mdev = get_mididev(dp, dev)) == NULL) |
|---|
| 401 | 398 | return -ENODEV; |
|---|
| 402 | | - if (! mdev->opened || mdev->devinfo != dp) { |
|---|
| 403 | | - snd_use_lock_free(&mdev->use_lock); |
|---|
| 404 | | - return 0; |
|---|
| 405 | | - } |
|---|
| 399 | + mutex_lock(&mdev->open_mutex); |
|---|
| 400 | + if (!mdev->opened || mdev->devinfo != dp) |
|---|
| 401 | + goto unlock; |
|---|
| 406 | 402 | |
|---|
| 407 | 403 | memset(&subs, 0, sizeof(subs)); |
|---|
| 408 | 404 | if (mdev->opened & PERM_WRITE) { |
|---|
| .. | .. |
|---|
| 421 | 417 | mdev->opened = 0; |
|---|
| 422 | 418 | mdev->devinfo = NULL; |
|---|
| 423 | 419 | |
|---|
| 420 | + unlock: |
|---|
| 421 | + mutex_unlock(&mdev->open_mutex); |
|---|
| 424 | 422 | snd_use_lock_free(&mdev->use_lock); |
|---|
| 425 | 423 | return 0; |
|---|
| 426 | 424 | } |
|---|