Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
[firefly-linux-kernel-4.4.55.git] / sound / core / pcm_native.c
index 25ed9fe41b89ceaf245278438c7113bc89ddc0f3..3fe99e644eb838a34913f8c6870742e67c227a31 100644 (file)
@@ -1586,12 +1586,18 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        struct file *file;
        struct snd_pcm_file *pcm_file;
        struct snd_pcm_substream *substream1;
+       struct snd_pcm_group *group;
 
        file = snd_pcm_file_fd(fd);
        if (!file)
                return -EBADFD;
        pcm_file = file->private_data;
        substream1 = pcm_file->substream;
+       group = kmalloc(sizeof(*group), GFP_KERNEL);
+       if (!group) {
+               res = -ENOMEM;
+               goto _nolock;
+       }
        down_write(&snd_pcm_link_rwsem);
        write_lock_irq(&snd_pcm_link_rwlock);
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
@@ -1604,11 +1610,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
                goto _end;
        }
        if (!snd_pcm_stream_linked(substream)) {
-               substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC);
-               if (substream->group == NULL) {
-                       res = -ENOMEM;
-                       goto _end;
-               }
+               substream->group = group;
                spin_lock_init(&substream->group->lock);
                INIT_LIST_HEAD(&substream->group->substreams);
                list_add_tail(&substream->link_list, &substream->group->substreams);
@@ -1620,7 +1622,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
  _end:
        write_unlock_irq(&snd_pcm_link_rwlock);
        up_write(&snd_pcm_link_rwsem);
+ _nolock:
        fput(file);
+       if (res < 0)
+               kfree(group);
        return res;
 }