diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-05-30 03:49:41 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-05-30 05:37:41 -0400 |
commit | a5003fc04113c217370409beac812831cbf6e0ac (patch) | |
tree | abf148b548a089f08240a21c77c80db2c5a0691d | |
parent | 2621f0338ce4e3e57cc32a967f5a3d2999390fe3 (diff) |
[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 <tiwai@suse.de>
-rw-r--r-- | sound/pci/emu10k1/memory.c | 66 |
1 files changed, 28 insertions, 38 deletions
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 916c1dbcd53c..128eaca17a61 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, | |||
437 | *last_page_ret = last_page; | 437 | *last_page_ret = last_page; |
438 | } | 438 | } |
439 | 439 | ||
440 | /* release allocated pages */ | ||
441 | static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page, | ||
442 | int last_page) | ||
443 | { | ||
444 | int page; | ||
445 | |||
446 | for (page = first_page; page <= last_page; page++) { | ||
447 | free_page((unsigned long)emu->page_ptr_table[page]); | ||
448 | emu->page_addr_table[page] = 0; | ||
449 | emu->page_ptr_table[page] = NULL; | ||
450 | } | ||
451 | } | ||
452 | |||
440 | /* | 453 | /* |
441 | * allocate kernel pages | 454 | * allocate kernel pages |
442 | */ | 455 | */ |
443 | static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) | 456 | static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) |
444 | { | 457 | { |
445 | int page, first_page, last_page; | 458 | int page, first_page, last_page; |
446 | struct snd_dma_buffer dmab; | ||
447 | 459 | ||
448 | emu10k1_memblk_init(blk); | 460 | emu10k1_memblk_init(blk); |
449 | get_single_page_range(emu->memhdr, blk, &first_page, &last_page); | 461 | get_single_page_range(emu->memhdr, blk, &first_page, &last_page); |
450 | /* allocate kernel pages */ | 462 | /* allocate kernel pages */ |
451 | for (page = first_page; page <= last_page; page++) { | 463 | for (page = first_page; page <= last_page; page++) { |
452 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), | 464 | /* first try to allocate from <4GB zone */ |
453 | PAGE_SIZE, &dmab) < 0) | 465 | struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 | |
454 | goto __fail; | 466 | __GFP_NOWARN); |
455 | if (! is_valid_page(emu, dmab.addr)) { | 467 | if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) |
456 | snd_dma_free_pages(&dmab); | 468 | /* try to allocate from <16MB zone */ |
457 | goto __fail; | 469 | p = alloc_page(GFP_DMA | |
470 | __GFP_NORETRY | /* no OOM-killer */ | ||
471 | __GFP_NOWARN); | ||
472 | if (!p) { | ||
473 | __synth_free_pages(emu, first_page, page - 1); | ||
474 | return -ENOMEM; | ||
458 | } | 475 | } |
459 | emu->page_addr_table[page] = dmab.addr; | 476 | emu->page_addr_table[page] = page_to_phys(p); |
460 | emu->page_ptr_table[page] = dmab.area; | 477 | emu->page_ptr_table[page] = page_address(p); |
461 | } | 478 | } |
462 | return 0; | 479 | return 0; |
463 | |||
464 | __fail: | ||
465 | /* release allocated pages */ | ||
466 | last_page = page - 1; | ||
467 | for (page = first_page; page <= last_page; page++) { | ||
468 | dmab.area = emu->page_ptr_table[page]; | ||
469 | dmab.addr = emu->page_addr_table[page]; | ||
470 | dmab.bytes = PAGE_SIZE; | ||
471 | snd_dma_free_pages(&dmab); | ||
472 | emu->page_addr_table[page] = 0; | ||
473 | emu->page_ptr_table[page] = NULL; | ||
474 | } | ||
475 | |||
476 | return -ENOMEM; | ||
477 | } | 480 | } |
478 | 481 | ||
479 | /* | 482 | /* |
@@ -481,23 +484,10 @@ __fail: | |||
481 | */ | 484 | */ |
482 | static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) | 485 | static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) |
483 | { | 486 | { |
484 | int page, first_page, last_page; | 487 | int first_page, last_page; |
485 | struct snd_dma_buffer dmab; | ||
486 | 488 | ||
487 | get_single_page_range(emu->memhdr, blk, &first_page, &last_page); | 489 | get_single_page_range(emu->memhdr, blk, &first_page, &last_page); |
488 | dmab.dev.type = SNDRV_DMA_TYPE_DEV; | 490 | __synth_free_pages(emu, first_page, last_page); |
489 | dmab.dev.dev = snd_dma_pci_data(emu->pci); | ||
490 | for (page = first_page; page <= last_page; page++) { | ||
491 | if (emu->page_ptr_table[page] == NULL) | ||
492 | continue; | ||
493 | dmab.area = emu->page_ptr_table[page]; | ||
494 | dmab.addr = emu->page_addr_table[page]; | ||
495 | dmab.bytes = PAGE_SIZE; | ||
496 | snd_dma_free_pages(&dmab); | ||
497 | emu->page_addr_table[page] = 0; | ||
498 | emu->page_ptr_table[page] = NULL; | ||
499 | } | ||
500 | |||
501 | return 0; | 491 | return 0; |
502 | } | 492 | } |
503 | 493 | ||