diff options
author | Jiri Kosina <jkosina@suse.cz> | 2013-12-19 15:08:03 +0100 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-12-19 15:08:32 +0100 |
commit | e23c34bb41da65f354fb7eee04300c56ee48f60c (patch) | |
tree | 549fbe449d55273b81ef104a9755109bf4ae7817 /sound/core/memalloc.c | |
parent | b481c2cb3534c85dca625973b33eba15f9af3e4c (diff) | |
parent | 319e2e3f63c348a9b66db4667efa73178e18b17d (diff) |
Merge branch 'master' into for-next
Sync with Linus' tree to be able to apply fixes on top of newer things
in tree (efi-stub).
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'sound/core/memalloc.c')
-rw-r--r-- | sound/core/memalloc.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index bdf826f4fe0c..5e1c7bc73b29 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -30,6 +30,7 @@ #include <linux/seq_file.h> #include <asm/uaccess.h> #include <linux/dma-mapping.h> +#include <linux/genalloc.h> #include <linux/moduleparam.h> #include <linux/mutex.h> #include <sound/memalloc.h> @@ -157,6 +158,47 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, dec_snd_pages(pg); dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma); } + +#ifdef CONFIG_GENERIC_ALLOCATOR +/** + * snd_malloc_dev_iram - allocate memory from on-chip internal ram + * @dmab: buffer allocation record to store the allocated data + * @size: number of bytes to allocate from the iram + * + * This function requires iram phandle provided via of_node + */ +static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size) +{ + struct device *dev = dmab->dev.dev; + struct gen_pool *pool = NULL; + + dmab->area = NULL; + dmab->addr = 0; + + if (dev->of_node) + pool = of_get_named_gen_pool(dev->of_node, "iram", 0); + + if (!pool) + return; + + /* Assign the pool into private_data field */ + dmab->private_data = pool; + + dmab->area = gen_pool_dma_alloc(pool, size, &dmab->addr); +} + +/** + * snd_free_dev_iram - free allocated specific memory from on-chip internal ram + * @dmab: buffer allocation record to store the allocated data + */ +static void snd_free_dev_iram(struct snd_dma_buffer *dmab) +{ + struct gen_pool *pool = dmab->private_data; + + if (pool && dmab->area) + gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes); +} +#endif /* CONFIG_GENERIC_ALLOCATOR */ #endif /* CONFIG_HAS_DMA */ /* @@ -197,6 +239,16 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, dmab->addr = 0; break; #ifdef CONFIG_HAS_DMA +#ifdef CONFIG_GENERIC_ALLOCATOR + case SNDRV_DMA_TYPE_DEV_IRAM: + snd_malloc_dev_iram(dmab, size); + if (dmab->area) + break; + /* Internal memory might have limited size and no enough space, + * so if we fail to malloc, try to fetch memory traditionally. + */ + dmab->dev.type = SNDRV_DMA_TYPE_DEV; +#endif /* CONFIG_GENERIC_ALLOCATOR */ case SNDRV_DMA_TYPE_DEV: dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); break; @@ -269,6 +321,11 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) snd_free_pages(dmab->area, dmab->bytes); break; #ifdef CONFIG_HAS_DMA +#ifdef CONFIG_GENERIC_ALLOCATOR + case SNDRV_DMA_TYPE_DEV_IRAM: + snd_free_dev_iram(dmab); + break; +#endif /* CONFIG_GENERIC_ALLOCATOR */ case SNDRV_DMA_TYPE_DEV: snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); break; |