summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-11-05 11:01:36 +0300
committerTakashi Iwai <tiwai@suse.de>2019-11-06 17:43:33 +0300
commit1fe7f397cfe229494a88c6496b53ba532d4d4a42 (patch)
tree4be717cf7f90a016e5f9b5453ab7932571823203
parent08422d2c559d1119b17c14e79b2d8ff89f46a356 (diff)
downloadlinux-1fe7f397cfe229494a88c6496b53ba532d4d4a42.tar.xz
ALSA: memalloc: Add vmalloc buffer allocation support
This patch adds the vmalloc buffer support to ALSA memalloc core. A new type, SNDRV_DMA_TYPE_VMALLOC was added. The vmalloc buffer has been already supported in the PCM via a few own helper functions, but the user sometimes get confused and misuse them. With this patch, the whole buffer management is integrated into the memalloc core, so they can be used in a sole common way. Link: https://lore.kernel.org/r/20191105080138.1260-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--include/sound/memalloc.h1
-rw-r--r--sound/core/memalloc.c20
2 files changed, 17 insertions, 4 deletions
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index 240622d89c0b..6ada3b8ede4e 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -44,6 +44,7 @@ struct snd_dma_device {
#else
#define SNDRV_DMA_TYPE_DEV_IRAM SNDRV_DMA_TYPE_DEV
#endif
+#define SNDRV_DMA_TYPE_VMALLOC 7 /* vmalloc'ed buffer */
/*
* info for buffer allocation
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 1b1c7620cbda..a83553fbedf0 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/genalloc.h>
+#include <linux/vmalloc.h>
#ifdef CONFIG_X86
#include <asm/set_memory.h>
#endif
@@ -99,10 +100,11 @@ static void snd_free_dev_iram(struct snd_dma_buffer *dmab)
*
*/
-static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev)
+static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev,
+ gfp_t default_gfp)
{
if (!dev)
- return GFP_KERNEL;
+ return default_gfp;
else
return (__force gfp_t)(unsigned long)dev;
}
@@ -123,6 +125,8 @@ static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev)
int snd_dma_alloc_pages(int type, struct device *device, size_t size,
struct snd_dma_buffer *dmab)
{
+ gfp_t gfp;
+
if (WARN_ON(!size))
return -ENXIO;
if (WARN_ON(!dmab))
@@ -133,8 +137,13 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
dmab->bytes = 0;
switch (type) {
case SNDRV_DMA_TYPE_CONTINUOUS:
- dmab->area = alloc_pages_exact(size,
- snd_mem_get_gfp_flags(device));
+ gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL);
+ dmab->area = alloc_pages_exact(size, gfp);
+ dmab->addr = 0;
+ break;
+ case SNDRV_DMA_TYPE_VMALLOC:
+ gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL | __GFP_HIGHMEM);
+ dmab->area = __vmalloc(size, gfp, PAGE_KERNEL);
dmab->addr = 0;
break;
#ifdef CONFIG_HAS_DMA
@@ -220,6 +229,9 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
case SNDRV_DMA_TYPE_CONTINUOUS:
free_pages_exact(dmab->area, dmab->bytes);
break;
+ case SNDRV_DMA_TYPE_VMALLOC:
+ vfree(dmab->area);
+ break;
#ifdef CONFIG_HAS_DMA
#ifdef CONFIG_GENERIC_ALLOCATOR
case SNDRV_DMA_TYPE_DEV_IRAM: