Skip to content

Commit 34f3c89

Browse files
committed
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>
1 parent 978520b commit 34f3c89

File tree

4 files changed

+21
-17
lines changed

4 files changed

+21
-17
lines changed

Diff for: sound/usb/card.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
339339
}
340340

341341
mutex_init(&chip->mutex);
342-
mutex_init(&chip->shutdown_mutex);
342+
init_rwsem(&chip->shutdown_rwsem);
343343
chip->index = idx;
344344
chip->dev = dev;
345345
chip->card = card;
@@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
560560

561561
card = chip->card;
562562
mutex_lock(&register_mutex);
563-
mutex_lock(&chip->shutdown_mutex);
563+
down_write(&chip->shutdown_rwsem);
564564
chip->shutdown = 1;
565565
chip->num_interfaces--;
566566
if (chip->num_interfaces <= 0) {
@@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
582582
snd_usb_mixer_disconnect(p);
583583
}
584584
usb_chip[chip->index] = NULL;
585-
mutex_unlock(&chip->shutdown_mutex);
585+
up_write(&chip->shutdown_rwsem);
586586
mutex_unlock(&register_mutex);
587587
snd_card_free_when_closed(card);
588588
} else {
589-
mutex_unlock(&chip->shutdown_mutex);
589+
up_write(&chip->shutdown_rwsem);
590590
mutex_unlock(&register_mutex);
591591
}
592592
}
@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
618618
{
619619
int err = -ENODEV;
620620

621+
down_read(&chip->shutdown_rwsem);
621622
if (!chip->shutdown && !chip->probing)
622623
err = usb_autopm_get_interface(chip->pm_intf);
624+
up_read(&chip->shutdown_rwsem);
623625

624626
return err;
625627
}
626628

627629
void snd_usb_autosuspend(struct snd_usb_audio *chip)
628630
{
631+
down_read(&chip->shutdown_rwsem);
629632
if (!chip->shutdown && !chip->probing)
630633
usb_autopm_put_interface(chip->pm_intf);
634+
up_read(&chip->shutdown_rwsem);
631635
}
632636

633637
static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)

Diff for: sound/usb/mixer.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
292292
err = snd_usb_autoresume(cval->mixer->chip);
293293
if (err < 0)
294294
return -EIO;
295-
mutex_lock(&chip->shutdown_mutex);
295+
down_read(&chip->shutdown_rwsem);
296296
while (timeout-- > 0) {
297297
if (chip->shutdown)
298298
break;
@@ -310,7 +310,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
310310
err = -EINVAL;
311311

312312
out:
313-
mutex_unlock(&chip->shutdown_mutex);
313+
up_read(&chip->shutdown_rwsem);
314314
snd_usb_autosuspend(cval->mixer->chip);
315315
return err;
316316
}
@@ -337,7 +337,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
337337
if (ret)
338338
goto error;
339339

340-
mutex_lock(&chip->shutdown_mutex);
340+
down_read(&chip->shutdown_rwsem);
341341
if (chip->shutdown)
342342
ret = -ENODEV;
343343
else {
@@ -346,7 +346,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
346346
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
347347
validx, idx, buf, size);
348348
}
349-
mutex_unlock(&chip->shutdown_mutex);
349+
up_read(&chip->shutdown_rwsem);
350350
snd_usb_autosuspend(chip);
351351

352352
if (ret < 0) {
@@ -453,7 +453,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
453453
err = snd_usb_autoresume(chip);
454454
if (err < 0)
455455
return -EIO;
456-
mutex_lock(&chip->shutdown_mutex);
456+
down_read(&chip->shutdown_rwsem);
457457
while (timeout-- > 0) {
458458
if (chip->shutdown)
459459
break;
@@ -471,7 +471,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
471471
err = -EINVAL;
472472

473473
out:
474-
mutex_unlock(&chip->shutdown_mutex);
474+
up_read(&chip->shutdown_rwsem);
475475
snd_usb_autosuspend(chip);
476476
return err;
477477
}

Diff for: sound/usb/pcm.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -503,12 +503,12 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
503503
return -EINVAL;
504504
}
505505

506-
mutex_lock(&subs->stream->chip->shutdown_mutex);
506+
down_read(&subs->stream->chip->shutdown_rwsem);
507507
if (subs->stream->chip->shutdown)
508508
ret = -ENODEV;
509509
else
510510
ret = set_format(subs, fmt);
511-
mutex_unlock(&subs->stream->chip->shutdown_mutex);
511+
up_read(&subs->stream->chip->shutdown_rwsem);
512512
if (ret < 0)
513513
return ret;
514514

@@ -531,12 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
531531
subs->cur_audiofmt = NULL;
532532
subs->cur_rate = 0;
533533
subs->period_bytes = 0;
534-
mutex_lock(&subs->stream->chip->shutdown_mutex);
534+
down_read(&subs->stream->chip->shutdown_rwsem);
535535
if (!subs->stream->chip->shutdown) {
536536
stop_endpoints(subs, 0, 1, 1);
537537
deactivate_endpoints(subs);
538538
}
539-
mutex_unlock(&subs->stream->chip->shutdown_mutex);
539+
up_read(&subs->stream->chip->shutdown_rwsem);
540540
return snd_pcm_lib_free_vmalloc_buffer(substream);
541541
}
542542

@@ -558,7 +558,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
558558
return -ENXIO;
559559
}
560560

561-
mutex_lock(&subs->stream->chip->shutdown_mutex);
561+
down_read(&subs->stream->chip->shutdown_rwsem);
562562
if (subs->stream->chip->shutdown) {
563563
ret = -ENODEV;
564564
goto unlock;
@@ -608,7 +608,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
608608
ret = start_endpoints(subs, 1);
609609

610610
unlock:
611-
mutex_unlock(&subs->stream->chip->shutdown_mutex);
611+
up_read(&subs->stream->chip->shutdown_rwsem);
612612
return ret;
613613
}
614614

Diff for: sound/usb/usbaudio.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct snd_usb_audio {
3737
struct usb_interface *pm_intf;
3838
u32 usb_id;
3939
struct mutex mutex;
40-
struct mutex shutdown_mutex;
40+
struct rw_semaphore shutdown_rwsem;
4141
unsigned int shutdown:1;
4242
unsigned int probing:1;
4343
unsigned int autosuspended:1;

0 commit comments

Comments
 (0)