ALSA: emu10k1 - simplify the last fix
[pandora-kernel.git] / sound / pci / emu10k1 / memory.c
index e7ec986..7d379f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
  *
  *  EMU10K1 memory page allocation (PTB area)
@@ -21,7 +21,6 @@
  *
  */
 
-#include <sound/driver.h>
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
@@ -287,6 +286,8 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b
        return err;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_memblk_map);
+
 /*
  * page allocation for DMA
  */
@@ -387,6 +388,7 @@ snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size)
        return (struct snd_util_memblk *)blk;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_synth_alloc);
 
 /*
  * free a synth sample area
@@ -409,6 +411,7 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk)
        return 0;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_synth_free);
 
 /* check new allocation range */
 static void get_single_page_range(struct snd_util_memhdr *hdr,
@@ -434,43 +437,49 @@ 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))) {
+                       if (p)
+                               __free_page(p);
+                       /* try to allocate from <16MB zone */
+                       p = alloc_page(GFP_ATOMIC | 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;
 }
 
 /*
@@ -478,23 +487,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;
 }
 
@@ -540,6 +536,8 @@ int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk
        return 0;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_synth_bzero);
+
 /*
  * copy_from_user(blk + offset, data, size)
  */
@@ -568,3 +566,5 @@ int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_me
        } while (offset < end_offset);
        return 0;
 }
+
+EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user);