summaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-13 15:55:43 +0100
committerTakashi Iwai <tiwai@suse.de>2012-03-15 07:36:00 +0100
commit1662591b2e6876b8bc041cd48837ccd297c2028f (patch)
treefdb4c9be9d073cb057af0571449c984730d8f75f /sound/core
parentALSA: pcm: Constify the list in snd_pcm_hw_constraint_list (diff)
downloadlinux-1662591b2e6876b8bc041cd48837ccd297c2028f.tar.xz
linux-1662591b2e6876b8bc041cd48837ccd297c2028f.zip
ALSA: pcm - Avoid GFP_ATOMIC in snd_pcm_link()
GFP_ATOMIC is used in snd_pcm_link() just because the kmalloc is called inside a lock. Since this function isn't too critical for speed and is rarely called in practice, better to allocate the chunk at first before spinlock and free it in error paths, so that GFP_KERNEL can be used. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_native.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 25ed9fe41b89..3fe99e644eb8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -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;
}