aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-13 10:55:43 -0400
committerTakashi Iwai <tiwai@suse.de>2012-03-15 02:36:00 -0400
commit1662591b2e6876b8bc041cd48837ccd297c2028f (patch)
treefdb4c9be9d073cb057af0571449c984730d8f75f
parent4af87a939ef7092fdca267fba473cf8407d6d8e2 (diff)
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>
-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)
1586 struct file *file; 1586 struct file *file;
1587 struct snd_pcm_file *pcm_file; 1587 struct snd_pcm_file *pcm_file;
1588 struct snd_pcm_substream *substream1; 1588 struct snd_pcm_substream *substream1;
1589 struct snd_pcm_group *group;
1589 1590
1590 file = snd_pcm_file_fd(fd); 1591 file = snd_pcm_file_fd(fd);
1591 if (!file) 1592 if (!file)
1592 return -EBADFD; 1593 return -EBADFD;
1593 pcm_file = file->private_data; 1594 pcm_file = file->private_data;
1594 substream1 = pcm_file->substream; 1595 substream1 = pcm_file->substream;
1596 group = kmalloc(sizeof(*group), GFP_KERNEL);
1597 if (!group) {
1598 res = -ENOMEM;
1599 goto _nolock;
1600 }
1595 down_write(&snd_pcm_link_rwsem); 1601 down_write(&snd_pcm_link_rwsem);
1596 write_lock_irq(&snd_pcm_link_rwlock); 1602 write_lock_irq(&snd_pcm_link_rwlock);
1597 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || 1603 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)
1604 goto _end; 1610 goto _end;
1605 } 1611 }
1606 if (!snd_pcm_stream_linked(substream)) { 1612 if (!snd_pcm_stream_linked(substream)) {
1607 substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC); 1613 substream->group = group;
1608 if (substream->group == NULL) {
1609 res = -ENOMEM;
1610 goto _end;
1611 }
1612 spin_lock_init(&substream->group->lock); 1614 spin_lock_init(&substream->group->lock);
1613 INIT_LIST_HEAD(&substream->group->substreams); 1615 INIT_LIST_HEAD(&substream->group->substreams);
1614 list_add_tail(&substream->link_list, &substream->group->substreams); 1616 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)
1620 _end: 1622 _end:
1621 write_unlock_irq(&snd_pcm_link_rwlock); 1623 write_unlock_irq(&snd_pcm_link_rwlock);
1622 up_write(&snd_pcm_link_rwsem); 1624 up_write(&snd_pcm_link_rwsem);
1625 _nolock:
1623 fput(file); 1626 fput(file);
1627 if (res < 0)
1628 kfree(group);
1624 return res; 1629 return res;
1625} 1630}
1626 1631