aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-10-15 06:16:02 -0400
committerTakashi Iwai <tiwai@suse.de>2012-10-30 06:07:00 -0400
commit34f3c89fda4fba9fe689db22253ca8db2f5e6386 (patch)
tree213e1b6e6ceaee42dc4f9ec74307794dc7a83b20 /sound
parent978520b75f0a1ce82b17e1e8186417250de6d545 (diff)
ALSA: usb-audio: Use rwsem for disconnect protection
Replace mutex with rwsem for codec->shutdown protection so that concurrent accesses are allowed. Also add the protection to snd_usb_autosuspend() and snd_usb_autoresume(), too. Reported-by: Matthieu CASTET <matthieu.castet@parrot.com> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/card.c12
-rw-r--r--sound/usb/mixer.c12
-rw-r--r--sound/usb/pcm.c12
-rw-r--r--sound/usb/usbaudio.h2
4 files changed, 21 insertions, 17 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 561bb74fd364..282f0fc9fed1 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
339 } 339 }
340 340
341 mutex_init(&chip->mutex); 341 mutex_init(&chip->mutex);
342 mutex_init(&chip->shutdown_mutex); 342 init_rwsem(&chip->shutdown_rwsem);
343 chip->index = idx; 343 chip->index = idx;
344 chip->dev = dev; 344 chip->dev = dev;
345 chip->card = card; 345 chip->card = card;
@@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
560 560
561 card = chip->card; 561 card = chip->card;
562 mutex_lock(&register_mutex); 562 mutex_lock(&register_mutex);
563 mutex_lock(&chip->shutdown_mutex); 563 down_write(&chip->shutdown_rwsem);
564 chip->shutdown = 1; 564 chip->shutdown = 1;
565 chip->num_interfaces--; 565 chip->num_interfaces--;
566 if (chip->num_interfaces <= 0) { 566 if (chip->num_interfaces <= 0) {
@@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
582 snd_usb_mixer_disconnect(p); 582 snd_usb_mixer_disconnect(p);
583 } 583 }
584 usb_chip[chip->index] = NULL; 584 usb_chip[chip->index] = NULL;
585 mutex_unlock(&chip->shutdown_mutex); 585 up_write(&chip->shutdown_rwsem);
586 mutex_unlock(&register_mutex); 586 mutex_unlock(&register_mutex);
587 snd_card_free_when_closed(card); 587 snd_card_free_when_closed(card);
588 } else { 588 } else {
589 mutex_unlock(&chip->shutdown_mutex); 589 up_write(&chip->shutdown_rwsem);
590 mutex_unlock(&register_mutex); 590 mutex_unlock(&register_mutex);
591 } 591 }
592} 592}
@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
618{ 618{
619 int err = -ENODEV; 619 int err = -ENODEV;
620 620
621 down_read(&chip->shutdown_rwsem);
621 if (!chip->shutdown && !chip->probing) 622 if (!chip->shutdown && !chip->probing)
622 err = usb_autopm_get_interface(chip->pm_intf); 623 err = usb_autopm_get_interface(chip->pm_intf);
624 up_read(&chip->shutdown_rwsem);
623 625
624 return err; 626 return err;
625} 627}
626 628
627void snd_usb_autosuspend(struct snd_usb_audio *chip) 629void snd_usb_autosuspend(struct snd_usb_audio *chip)
628{ 630{
631 down_read(&chip->shutdown_rwsem);
629 if (!chip->shutdown && !chip->probing) 632 if (!chip->shutdown && !chip->probing)
630 usb_autopm_put_interface(chip->pm_intf); 633 usb_autopm_put_interface(chip->pm_intf);
634 up_read(&chip->shutdown_rwsem);
631} 635}
632 636
633static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) 637static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index c2ef11ccd66a..298070e8f2d4 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -292,7 +292,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
292 err = snd_usb_autoresume(cval->mixer->chip); 292 err = snd_usb_autoresume(cval->mixer->chip);
293 if (err < 0) 293 if (err < 0)
294 return -EIO; 294 return -EIO;
295 mutex_lock(&chip->shutdown_mutex); 295 down_read(&chip->shutdown_rwsem);
296 while (timeout-- > 0) { 296 while (timeout-- > 0) {
297 if (chip->shutdown) 297 if (chip->shutdown)
298 break; 298 break;
@@ -310,7 +310,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
310 err = -EINVAL; 310 err = -EINVAL;
311 311
312 out: 312 out:
313 mutex_unlock(&chip->shutdown_mutex); 313 up_read(&chip->shutdown_rwsem);
314 snd_usb_autosuspend(cval->mixer->chip); 314 snd_usb_autosuspend(cval->mixer->chip);
315 return err; 315 return err;
316} 316}
@@ -337,7 +337,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
337 if (ret) 337 if (ret)
338 goto error; 338 goto error;
339 339
340 mutex_lock(&chip->shutdown_mutex); 340 down_read(&chip->shutdown_rwsem);
341 if (chip->shutdown) 341 if (chip->shutdown)
342 ret = -ENODEV; 342 ret = -ENODEV;
343 else { 343 else {
@@ -346,7 +346,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
346 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 346 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
347 validx, idx, buf, size); 347 validx, idx, buf, size);
348 } 348 }
349 mutex_unlock(&chip->shutdown_mutex); 349 up_read(&chip->shutdown_rwsem);
350 snd_usb_autosuspend(chip); 350 snd_usb_autosuspend(chip);
351 351
352 if (ret < 0) { 352 if (ret < 0) {
@@ -453,7 +453,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
453 err = snd_usb_autoresume(chip); 453 err = snd_usb_autoresume(chip);
454 if (err < 0) 454 if (err < 0)
455 return -EIO; 455 return -EIO;
456 mutex_lock(&chip->shutdown_mutex); 456 down_read(&chip->shutdown_rwsem);
457 while (timeout-- > 0) { 457 while (timeout-- > 0) {
458 if (chip->shutdown) 458 if (chip->shutdown)
459 break; 459 break;
@@ -471,7 +471,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
471 err = -EINVAL; 471 err = -EINVAL;
472 472
473 out: 473 out:
474 mutex_unlock(&chip->shutdown_mutex); 474 up_read(&chip->shutdown_rwsem);
475 snd_usb_autosuspend(chip); 475 snd_usb_autosuspend(chip);
476 return err; 476 return err;
477} 477}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 55e741c5f231..37428f74dbb6 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -503,12 +503,12 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
503 return -EINVAL; 503 return -EINVAL;
504 } 504 }
505 505
506 mutex_lock(&subs->stream->chip->shutdown_mutex); 506 down_read(&subs->stream->chip->shutdown_rwsem);
507 if (subs->stream->chip->shutdown) 507 if (subs->stream->chip->shutdown)
508 ret = -ENODEV; 508 ret = -ENODEV;
509 else 509 else
510 ret = set_format(subs, fmt); 510 ret = set_format(subs, fmt);
511 mutex_unlock(&subs->stream->chip->shutdown_mutex); 511 up_read(&subs->stream->chip->shutdown_rwsem);
512 if (ret < 0) 512 if (ret < 0)
513 return ret; 513 return ret;
514 514
@@ -531,12 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
531 subs->cur_audiofmt = NULL; 531 subs->cur_audiofmt = NULL;
532 subs->cur_rate = 0; 532 subs->cur_rate = 0;
533 subs->period_bytes = 0; 533 subs->period_bytes = 0;
534 mutex_lock(&subs->stream->chip->shutdown_mutex); 534 down_read(&subs->stream->chip->shutdown_rwsem);
535 if (!subs->stream->chip->shutdown) { 535 if (!subs->stream->chip->shutdown) {
536 stop_endpoints(subs, 0, 1, 1); 536 stop_endpoints(subs, 0, 1, 1);
537 deactivate_endpoints(subs); 537 deactivate_endpoints(subs);
538 } 538 }
539 mutex_unlock(&subs->stream->chip->shutdown_mutex); 539 up_read(&subs->stream->chip->shutdown_rwsem);
540 return snd_pcm_lib_free_vmalloc_buffer(substream); 540 return snd_pcm_lib_free_vmalloc_buffer(substream);
541} 541}
542 542
@@ -558,7 +558,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
558 return -ENXIO; 558 return -ENXIO;
559 } 559 }
560 560
561 mutex_lock(&subs->stream->chip->shutdown_mutex); 561 down_read(&subs->stream->chip->shutdown_rwsem);
562 if (subs->stream->chip->shutdown) { 562 if (subs->stream->chip->shutdown) {
563 ret = -ENODEV; 563 ret = -ENODEV;
564 goto unlock; 564 goto unlock;
@@ -608,7 +608,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
608 ret = start_endpoints(subs, 1); 608 ret = start_endpoints(subs, 1);
609 609
610 unlock: 610 unlock:
611 mutex_unlock(&subs->stream->chip->shutdown_mutex); 611 up_read(&subs->stream->chip->shutdown_rwsem);
612 return ret; 612 return ret;
613} 613}
614 614
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b8233ebe250f..ef42797f56fb 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -37,7 +37,7 @@ struct snd_usb_audio {
37 struct usb_interface *pm_intf; 37 struct usb_interface *pm_intf;
38 u32 usb_id; 38 u32 usb_id;
39 struct mutex mutex; 39 struct mutex mutex;
40 struct mutex shutdown_mutex; 40 struct rw_semaphore shutdown_rwsem;
41 unsigned int shutdown:1; 41 unsigned int shutdown:1;
42 unsigned int probing:1; 42 unsigned int probing:1;
43 unsigned int autosuspended:1; 43 unsigned int autosuspended:1;