From a5003fc04113c217370409beac812831cbf6e0ac Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 May 2008 09:49:41 +0200 Subject: [ALSA] emu10k1 - simplify page allocation for synth Simplify the page allocation of emu10k1 driver for emux synth support. Since these pages aren't be necessarily coherent, we can avoid expensive DMA-coherent routines. Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/memory.c | 66 ++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) (limited to 'sound/pci/emu10k1/memory.c') diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 916c1dbcd53..128eaca17a6 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -437,43 +437,46 @@ static void get_single_page_range(struct snd_util_memhdr *hdr, *last_page_ret = last_page; } +/* release allocated pages */ +static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page, + int last_page) +{ + int page; + + for (page = first_page; page <= last_page; page++) { + free_page((unsigned long)emu->page_ptr_table[page]); + emu->page_addr_table[page] = 0; + emu->page_ptr_table[page] = NULL; + } +} + /* * allocate kernel pages */ static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) { int page, first_page, last_page; - struct snd_dma_buffer dmab; emu10k1_memblk_init(blk); get_single_page_range(emu->memhdr, blk, &first_page, &last_page); /* allocate kernel pages */ for (page = first_page; page <= last_page; page++) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), - PAGE_SIZE, &dmab) < 0) - goto __fail; - if (! is_valid_page(emu, dmab.addr)) { - snd_dma_free_pages(&dmab); - goto __fail; + /* first try to allocate from <4GB zone */ + struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 | + __GFP_NOWARN); + if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) + /* try to allocate from <16MB zone */ + p = alloc_page(GFP_DMA | + __GFP_NORETRY | /* no OOM-killer */ + __GFP_NOWARN); + if (!p) { + __synth_free_pages(emu, first_page, page - 1); + return -ENOMEM; } - emu->page_addr_table[page] = dmab.addr; - emu->page_ptr_table[page] = dmab.area; + emu->page_addr_table[page] = page_to_phys(p); + emu->page_ptr_table[page] = page_address(p); } return 0; - -__fail: - /* release allocated pages */ - last_page = page - 1; - for (page = first_page; page <= last_page; page++) { - dmab.area = emu->page_ptr_table[page]; - dmab.addr = emu->page_addr_table[page]; - dmab.bytes = PAGE_SIZE; - snd_dma_free_pages(&dmab); - emu->page_addr_table[page] = 0; - emu->page_ptr_table[page] = NULL; - } - - return -ENOMEM; } /* @@ -481,23 +484,10 @@ __fail: */ static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) { - int page, first_page, last_page; - struct snd_dma_buffer dmab; + int first_page, last_page; get_single_page_range(emu->memhdr, blk, &first_page, &last_page); - dmab.dev.type = SNDRV_DMA_TYPE_DEV; - dmab.dev.dev = snd_dma_pci_data(emu->pci); - for (page = first_page; page <= last_page; page++) { - if (emu->page_ptr_table[page] == NULL) - continue; - dmab.area = emu->page_ptr_table[page]; - dmab.addr = emu->page_addr_table[page]; - dmab.bytes = PAGE_SIZE; - snd_dma_free_pages(&dmab); - emu->page_addr_table[page] = 0; - emu->page_ptr_table[page] = NULL; - } - + __synth_free_pages(emu, first_page, last_page); return 0; } -- cgit v1.2.3 From 781711a93e8aae756e8ae07acef185a6dfe552b8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Jun 2008 12:34:45 +0200 Subject: ALSA: emu10k1 - Fix page allocation with GFP_DMA Added the missing GFP_ATOMIC to page_alloc when called with GFP_DMA. GFP_KERNEL often results in stalls for ZONE_DMA, so GFP_ATOMIC is more prgmatic. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/emu10k1/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/pci/emu10k1/memory.c') diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 128eaca17a6..42943b4fcb7 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -466,7 +466,7 @@ static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk __GFP_NOWARN); if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) /* try to allocate from <16MB zone */ - p = alloc_page(GFP_DMA | + p = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_NORETRY | /* no OOM-killer */ __GFP_NOWARN); if (!p) { -- cgit v1.2.3 From 9f515b6898d0f2c1b9eb34ae9986794045f34e2b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 17 Jun 2008 16:20:13 +0200 Subject: ALSA: emu10k1 - fix possible memory leak in memory allocation routines The leak was introduced in "[ALSA] emu10k1 - simplify page allocation for synth" commit. Signed-off-by: Jaroslav Kysela --- sound/pci/emu10k1/memory.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'sound/pci/emu10k1/memory.c') diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 42943b4fcb7..759e29f8947 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -464,11 +464,17 @@ static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk /* first try to allocate from <4GB zone */ struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_NOWARN); - if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) + if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) { /* try to allocate from <16MB zone */ - p = alloc_page(GFP_ATOMIC | GFP_DMA | + struct page *p1 = + alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_NORETRY | /* no OOM-killer */ __GFP_NOWARN); + /* free page outside dma_mask range */ + if (p) + free_page((unsigned long)page_address(p)); + p = p1; + } if (!p) { __synth_free_pages(emu, first_page, page - 1); return -ENOMEM; -- cgit v1.2.3 From 284373059f9605442cac6453780f6aaecf9abac1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jun 2008 16:30:27 +0200 Subject: ALSA: emu10k1 - simplify the last fix Clean up the previous commit for fixing memory leaks. Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/memory.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'sound/pci/emu10k1/memory.c') diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 759e29f8947..7d379f5131f 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -465,15 +465,12 @@ static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_NOWARN); if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) { + if (p) + __free_page(p); /* try to allocate from <16MB zone */ - struct page *p1 = - alloc_page(GFP_ATOMIC | GFP_DMA | + p = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_NORETRY | /* no OOM-killer */ __GFP_NOWARN); - /* free page outside dma_mask range */ - if (p) - free_page((unsigned long)page_address(p)); - p = p1; } if (!p) { __synth_free_pages(emu, first_page, page - 1); -- cgit v1.2.3