aboutsummaryrefslogtreecommitdiff
path: root/sound/usb/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r--sound/usb/stream.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 310a3822..6b431e6b 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -69,9 +69,14 @@ static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
{
struct snd_usb_stream *stream = pcm->private_data;
+ struct snd_usb_audio *chip;
+
if (stream) {
+ mutex_lock(&stream->chip->dev_lock);
+ chip = stream->chip;
stream->pcm = NULL;
snd_usb_audio_stream_free(stream);
+ mutex_unlock(&chip->dev_lock);
}
}
@@ -315,7 +320,9 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
/*
* add this endpoint to the chip instance.
* if a stream with the same endpoint already exists, append to it.
- * if not, create a new pcm stream.
+ * if not, create a new pcm stream. note, fp is added to the substream
+ * fmt_list and will be freed on the chip instance release. do not free
+ * fp or do remove it from the substream fmt_list to avoid double-free.
*/
int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
int stream,
@@ -668,6 +675,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
* (fp->maxpacksize & 0x7ff);
fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
fp->clock = clock;
+ INIT_LIST_HEAD(&fp->list);
/* some quirks for attributes here */
@@ -716,6 +724,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) {
+ list_del(&fp->list); /* unlink for avoiding double-free */
kfree(fp->rate_table);
kfree(fp->chmap);
kfree(fp);