sound: pcm: add vmalloc buffer helper functions
There are now five copies of the code to allocate a PCM buffer using vmalloc(). Add a sixth in the core so that the others can be removed. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
14d44e2c2c
commit
681b84e177
|
@ -905,6 +905,44 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
|
|||
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
|
||||
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
|
||||
|
||||
int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
|
||||
size_t size, gfp_t gfp_flags);
|
||||
int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream);
|
||||
struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
|
||||
unsigned long offset);
|
||||
#if 0 /* for kernel-doc */
|
||||
/**
|
||||
* snd_pcm_lib_alloc_vmalloc_buffer - allocate virtual DMA buffer
|
||||
* @substream: the substream to allocate the buffer to
|
||||
* @size: the requested buffer size, in bytes
|
||||
*
|
||||
* Allocates the PCM substream buffer using vmalloc(), i.e., the memory is
|
||||
* contiguous in kernel virtual space, but not in physical memory. Use this
|
||||
* if the buffer is accessed by kernel code but not by device DMA.
|
||||
*
|
||||
* Returns 1 if the buffer was changed, 0 if not changed, or a negative error
|
||||
* code.
|
||||
*/
|
||||
static int snd_pcm_lib_alloc_vmalloc_buffer
|
||||
(struct snd_pcm_substream *substream, size_t size);
|
||||
/**
|
||||
* snd_pcm_lib_alloc_vmalloc_32_buffer - allocate 32-bit-addressable buffer
|
||||
* @substream: the substream to allocate the buffer to
|
||||
* @size: the requested buffer size, in bytes
|
||||
*
|
||||
* This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses
|
||||
* vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory.
|
||||
*/
|
||||
static int snd_pcm_lib_alloc_vmalloc_32_buffer
|
||||
(struct snd_pcm_substream *substream, size_t size);
|
||||
#endif
|
||||
#define snd_pcm_lib_alloc_vmalloc_buffer(subs, size) \
|
||||
_snd_pcm_lib_alloc_vmalloc_buffer \
|
||||
(subs, size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO)
|
||||
#define snd_pcm_lib_alloc_vmalloc_32_buffer(subs, size) \
|
||||
_snd_pcm_lib_alloc_vmalloc_buffer \
|
||||
(subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO)
|
||||
|
||||
#ifdef CONFIG_SND_DMA_SGBUF
|
||||
/*
|
||||
* SG-buffer handling
|
||||
|
|
|
@ -434,3 +434,57 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
|
|||
}
|
||||
|
||||
EXPORT_SYMBOL(snd_pcm_lib_free_pages);
|
||||
|
||||
int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
|
||||
size_t size, gfp_t gfp_flags)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime;
|
||||
|
||||
if (PCM_RUNTIME_CHECK(substream))
|
||||
return -EINVAL;
|
||||
runtime = substream->runtime;
|
||||
if (runtime->dma_area) {
|
||||
if (runtime->dma_bytes >= size)
|
||||
return 0; /* already large enough */
|
||||
vfree(runtime->dma_area);
|
||||
}
|
||||
runtime->dma_area = __vmalloc(size, gfp_flags, PAGE_KERNEL);
|
||||
if (!runtime->dma_area)
|
||||
return -ENOMEM;
|
||||
runtime->dma_bytes = size;
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
|
||||
|
||||
/**
|
||||
* snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
|
||||
* @substream: the substream with a buffer allocated by
|
||||
* snd_pcm_lib_alloc_vmalloc_buffer()
|
||||
*/
|
||||
int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime;
|
||||
|
||||
if (PCM_RUNTIME_CHECK(substream))
|
||||
return -EINVAL;
|
||||
runtime = substream->runtime;
|
||||
vfree(runtime->dma_area);
|
||||
runtime->dma_area = NULL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
|
||||
|
||||
/**
|
||||
* snd_pcm_lib_get_vmalloc_page - map vmalloc buffer offset to page struct
|
||||
* @substream: the substream with a buffer allocated by
|
||||
* snd_pcm_lib_alloc_vmalloc_buffer()
|
||||
* @offset: offset in the buffer
|
||||
*
|
||||
* This function is to be used as the page callback in the PCM ops.
|
||||
*/
|
||||
struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
|
||||
unsigned long offset)
|
||||
{
|
||||
return vmalloc_to_page(substream->runtime->dma_area + offset);
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page);
|
||||
|
|
Loading…
Reference in New Issue