diff options
| -rw-r--r-- | include/sound/pcm.h | 38 | ||||
| -rw-r--r-- | sound/core/pcm_memory.c | 54 |
2 files changed, 92 insertions, 0 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index c83a4a79f16b..0ad2d28f2360 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
| @@ -905,6 +905,44 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, | |||
| 905 | int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size); | 905 | int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size); |
| 906 | int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream); | 906 | int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream); |
| 907 | 907 | ||
| 908 | int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, | ||
| 909 | size_t size, gfp_t gfp_flags); | ||
| 910 | int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream); | ||
| 911 | struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream, | ||
| 912 | unsigned long offset); | ||
| 913 | #if 0 /* for kernel-doc */ | ||
| 914 | /** | ||
| 915 | * snd_pcm_lib_alloc_vmalloc_buffer - allocate virtual DMA buffer | ||
| 916 | * @substream: the substream to allocate the buffer to | ||
| 917 | * @size: the requested buffer size, in bytes | ||
| 918 | * | ||
| 919 | * Allocates the PCM substream buffer using vmalloc(), i.e., the memory is | ||
| 920 | * contiguous in kernel virtual space, but not in physical memory. Use this | ||
| 921 | * if the buffer is accessed by kernel code but not by device DMA. | ||
| 922 | * | ||
| 923 | * Returns 1 if the buffer was changed, 0 if not changed, or a negative error | ||
| 924 | * code. | ||
| 925 | */ | ||
| 926 | static int snd_pcm_lib_alloc_vmalloc_buffer | ||
| 927 | (struct snd_pcm_substream *substream, size_t size); | ||
| 928 | /** | ||
| 929 | * snd_pcm_lib_alloc_vmalloc_32_buffer - allocate 32-bit-addressable buffer | ||
| 930 | * @substream: the substream to allocate the buffer to | ||
| 931 | * @size: the requested buffer size, in bytes | ||
| 932 | * | ||
| 933 | * This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses | ||
| 934 | * vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory. | ||
| 935 | */ | ||
| 936 | static int snd_pcm_lib_alloc_vmalloc_32_buffer | ||
| 937 | (struct snd_pcm_substream *substream, size_t size); | ||
| 938 | #endif | ||
| 939 | #define snd_pcm_lib_alloc_vmalloc_buffer(subs, size) \ | ||
| 940 | _snd_pcm_lib_alloc_vmalloc_buffer \ | ||
| 941 | (subs, size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO) | ||
| 942 | #define snd_pcm_lib_alloc_vmalloc_32_buffer(subs, size) \ | ||
| 943 | _snd_pcm_lib_alloc_vmalloc_buffer \ | ||
| 944 | (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO) | ||
| 945 | |||
| 908 | #ifdef CONFIG_SND_DMA_SGBUF | 946 | #ifdef CONFIG_SND_DMA_SGBUF |
| 909 | /* | 947 | /* |
| 910 | * SG-buffer handling | 948 | * SG-buffer handling |
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index caa7796bc2f5..d9727c74b2e1 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
| @@ -434,3 +434,57 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) | |||
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); | 436 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); |
| 437 | |||
| 438 | int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, | ||
| 439 | size_t size, gfp_t gfp_flags) | ||
| 440 | { | ||
| 441 | struct snd_pcm_runtime *runtime; | ||
| 442 | |||
| 443 | if (PCM_RUNTIME_CHECK(substream)) | ||
| 444 | return -EINVAL; | ||
| 445 | runtime = substream->runtime; | ||
| 446 | if (runtime->dma_area) { | ||
| 447 | if (runtime->dma_bytes >= size) | ||
| 448 | return 0; /* already large enough */ | ||
| 449 | vfree(runtime->dma_area); | ||
| 450 | } | ||
| 451 | runtime->dma_area = __vmalloc(size, gfp_flags, PAGE_KERNEL); | ||
| 452 | if (!runtime->dma_area) | ||
| 453 | return -ENOMEM; | ||
| 454 | runtime->dma_bytes = size; | ||
| 455 | return 1; | ||
| 456 | } | ||
| 457 | EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer); | ||
| 458 | |||
| 459 | /** | ||
| 460 | * snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer | ||
| 461 | * @substream: the substream with a buffer allocated by | ||
| 462 | * snd_pcm_lib_alloc_vmalloc_buffer() | ||
| 463 | */ | ||
| 464 | int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream) | ||
| 465 | { | ||
| 466 | struct snd_pcm_runtime *runtime; | ||
| 467 | |||
| 468 | if (PCM_RUNTIME_CHECK(substream)) | ||
| 469 | return -EINVAL; | ||
| 470 | runtime = substream->runtime; | ||
| 471 | vfree(runtime->dma_area); | ||
| 472 | runtime->dma_area = NULL; | ||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer); | ||
| 476 | |||
| 477 | /** | ||
| 478 | * snd_pcm_lib_get_vmalloc_page - map vmalloc buffer offset to page struct | ||
| 479 | * @substream: the substream with a buffer allocated by | ||
| 480 | * snd_pcm_lib_alloc_vmalloc_buffer() | ||
| 481 | * @offset: offset in the buffer | ||
| 482 | * | ||
| 483 | * This function is to be used as the page callback in the PCM ops. | ||
| 484 | */ | ||
| 485 | struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream, | ||
| 486 | unsigned long offset) | ||
| 487 | { | ||
| 488 | return vmalloc_to_page(substream->runtime->dma_area + offset); | ||
| 489 | } | ||
| 490 | EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page); | ||
