linux/sound/core/memalloc.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   3 *                   Takashi Iwai <tiwai@suse.de>
   4 * 
   5 *  Generic memory allocators
   6 *
   7 *
   8 *   This program is free software; you can redistribute it and/or modify
   9 *   it under the terms of the GNU General Public License as published by
  10 *   the Free Software Foundation; either version 2 of the License, or
  11 *   (at your option) any later version.
  12 *
  13 *   This program is distributed in the hope that it will be useful,
  14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *   GNU General Public License for more details.
  17 *
  18 *   You should have received a copy of the GNU General Public License
  19 *   along with this program; if not, write to the Free Software
  20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21 *
  22 */
  23
  24#include <linux/slab.h>
  25#include <linux/mm.h>
  26#include <linux/dma-mapping.h>
  27#include <linux/genalloc.h>
  28#include <sound/memalloc.h>
  29
  30/*
  31 *
  32 *  Generic memory allocators
  33 *
  34 */
  35
  36/**
  37 * snd_malloc_pages - allocate pages with the given size
  38 * @size: the size to allocate in bytes
  39 * @gfp_flags: the allocation conditions, GFP_XXX
  40 *
  41 * Allocates the physically contiguous pages with the given size.
  42 *
  43 * Return: The pointer of the buffer, or %NULL if no enough memory.
  44 */
  45void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
  46{
  47        int pg;
  48
  49        if (WARN_ON(!size))
  50                return NULL;
  51        if (WARN_ON(!gfp_flags))
  52                return NULL;
  53        gfp_flags |= __GFP_COMP;        /* compound page lets parts be mapped */
  54        pg = get_order(size);
  55        return (void *) __get_free_pages(gfp_flags, pg);
  56}
  57
  58/**
  59 * snd_free_pages - release the pages
  60 * @ptr: the buffer pointer to release
  61 * @size: the allocated buffer size
  62 *
  63 * Releases the buffer allocated via snd_malloc_pages().
  64 */
  65void snd_free_pages(void *ptr, size_t size)
  66{
  67        int pg;
  68
  69        if (ptr == NULL)
  70                return;
  71        pg = get_order(size);
  72        free_pages((unsigned long) ptr, pg);
  73}
  74
  75/*
  76 *
  77 *  Bus-specific memory allocators
  78 *
  79 */
  80
  81#ifdef CONFIG_HAS_DMA
  82/* allocate the coherent DMA pages */
  83static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
  84{
  85        int pg;
  86        gfp_t gfp_flags;
  87
  88        if (WARN_ON(!dma))
  89                return NULL;
  90        pg = get_order(size);
  91        gfp_flags = GFP_KERNEL
  92                | __GFP_COMP    /* compound page lets parts be mapped */
  93                | __GFP_NORETRY /* don't trigger OOM-killer */
  94                | __GFP_NOWARN; /* no stack trace print - this call is non-critical */
  95        return dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
  96}
  97
  98/* free the coherent DMA pages */
  99static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
 100                               dma_addr_t dma)
 101{
 102        int pg;
 103
 104        if (ptr == NULL)
 105                return;
 106        pg = get_order(size);
 107        dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
 108}
 109
 110#ifdef CONFIG_GENERIC_ALLOCATOR
 111/**
 112 * snd_malloc_dev_iram - allocate memory from on-chip internal ram
 113 * @dmab: buffer allocation record to store the allocated data
 114 * @size: number of bytes to allocate from the iram
 115 *
 116 * This function requires iram phandle provided via of_node
 117 */
 118static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size)
 119{
 120        struct device *dev = dmab->dev.dev;
 121        struct gen_pool *pool = NULL;
 122
 123        dmab->area = NULL;
 124        dmab->addr = 0;
 125
 126        if (dev->of_node)
 127                pool = of_gen_pool_get(dev->of_node, "iram", 0);
 128
 129        if (!pool)
 130                return;
 131
 132        /* Assign the pool into private_data field */
 133        dmab->private_data = pool;
 134
 135        dmab->area = gen_pool_dma_alloc(pool, size, &dmab->addr);
 136}
 137
 138/**
 139 * snd_free_dev_iram - free allocated specific memory from on-chip internal ram
 140 * @dmab: buffer allocation record to store the allocated data
 141 */
 142static void snd_free_dev_iram(struct snd_dma_buffer *dmab)
 143{
 144        struct gen_pool *pool = dmab->private_data;
 145
 146        if (pool && dmab->area)
 147                gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes);
 148}
 149#endif /* CONFIG_GENERIC_ALLOCATOR */
 150#endif /* CONFIG_HAS_DMA */
 151
 152/*
 153 *
 154 *  ALSA generic memory management
 155 *
 156 */
 157
 158
 159/**
 160 * snd_dma_alloc_pages - allocate the buffer area according to the given type
 161 * @type: the DMA buffer type
 162 * @device: the device pointer
 163 * @size: the buffer size to allocate
 164 * @dmab: buffer allocation record to store the allocated data
 165 *
 166 * Calls the memory-allocator function for the corresponding
 167 * buffer type.
 168 *
 169 * Return: Zero if the buffer with the given size is allocated successfully,
 170 * otherwise a negative value on error.
 171 */
 172int snd_dma_alloc_pages(int type, struct device *device, size_t size,
 173                        struct snd_dma_buffer *dmab)
 174{
 175        if (WARN_ON(!size))
 176                return -ENXIO;
 177        if (WARN_ON(!dmab))
 178                return -ENXIO;
 179
 180        dmab->dev.type = type;
 181        dmab->dev.dev = device;
 182        dmab->bytes = 0;
 183        switch (type) {
 184        case SNDRV_DMA_TYPE_CONTINUOUS:
 185                dmab->area = snd_malloc_pages(size,
 186                                        (__force gfp_t)(unsigned long)device);
 187                dmab->addr = 0;
 188                break;
 189#ifdef CONFIG_HAS_DMA
 190#ifdef CONFIG_GENERIC_ALLOCATOR
 191        case SNDRV_DMA_TYPE_DEV_IRAM:
 192                snd_malloc_dev_iram(dmab, size);
 193                if (dmab->area)
 194                        break;
 195                /* Internal memory might have limited size and no enough space,
 196                 * so if we fail to malloc, try to fetch memory traditionally.
 197                 */
 198                dmab->dev.type = SNDRV_DMA_TYPE_DEV;
 199#endif /* CONFIG_GENERIC_ALLOCATOR */
 200        case SNDRV_DMA_TYPE_DEV:
 201                dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
 202                break;
 203#endif
 204#ifdef CONFIG_SND_DMA_SGBUF
 205        case SNDRV_DMA_TYPE_DEV_SG:
 206                snd_malloc_sgbuf_pages(device, size, dmab, NULL);
 207                break;
 208#endif
 209        default:
 210                pr_err("snd-malloc: invalid device type %d\n", type);
 211                dmab->area = NULL;
 212                dmab->addr = 0;
 213                return -ENXIO;
 214        }
 215        if (! dmab->area)
 216                return -ENOMEM;
 217        dmab->bytes = size;
 218        return 0;
 219}
 220
 221/**
 222 * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
 223 * @type: the DMA buffer type
 224 * @device: the device pointer
 225 * @size: the buffer size to allocate
 226 * @dmab: buffer allocation record to store the allocated data
 227 *
 228 * Calls the memory-allocator function for the corresponding
 229 * buffer type.  When no space is left, this function reduces the size and
 230 * tries to allocate again.  The size actually allocated is stored in
 231 * res_size argument.
 232 *
 233 * Return: Zero if the buffer with the given size is allocated successfully,
 234 * otherwise a negative value on error.
 235 */
 236int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
 237                                 struct snd_dma_buffer *dmab)
 238{
 239        int err;
 240
 241        while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
 242                size_t aligned_size;
 243                if (err != -ENOMEM)
 244                        return err;
 245                if (size <= PAGE_SIZE)
 246                        return -ENOMEM;
 247                aligned_size = PAGE_SIZE << get_order(size);
 248                if (size != aligned_size)
 249                        size = aligned_size;
 250                else
 251                        size >>= 1;
 252        }
 253        if (! dmab->area)
 254                return -ENOMEM;
 255        return 0;
 256}
 257
 258
 259/**
 260 * snd_dma_free_pages - release the allocated buffer
 261 * @dmab: the buffer allocation record to release
 262 *
 263 * Releases the allocated buffer via snd_dma_alloc_pages().
 264 */
 265void snd_dma_free_pages(struct snd_dma_buffer *dmab)
 266{
 267        switch (dmab->dev.type) {
 268        case SNDRV_DMA_TYPE_CONTINUOUS:
 269                snd_free_pages(dmab->area, dmab->bytes);
 270                break;
 271#ifdef CONFIG_HAS_DMA
 272#ifdef CONFIG_GENERIC_ALLOCATOR
 273        case SNDRV_DMA_TYPE_DEV_IRAM:
 274                snd_free_dev_iram(dmab);
 275                break;
 276#endif /* CONFIG_GENERIC_ALLOCATOR */
 277        case SNDRV_DMA_TYPE_DEV:
 278                snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 279                break;
 280#endif
 281#ifdef CONFIG_SND_DMA_SGBUF
 282        case SNDRV_DMA_TYPE_DEV_SG:
 283                snd_free_sgbuf_pages(dmab);
 284                break;
 285#endif
 286        default:
 287                pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
 288        }
 289}
 290
 291/*
 292 * exports
 293 */
 294EXPORT_SYMBOL(snd_dma_alloc_pages);
 295EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
 296EXPORT_SYMBOL(snd_dma_free_pages);
 297
 298EXPORT_SYMBOL(snd_malloc_pages);
 299EXPORT_SYMBOL(snd_free_pages);
 300