root/sound/core/memalloc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_malloc_dev_pages
  2. snd_free_dev_pages
  3. snd_malloc_dev_iram
  4. snd_free_dev_iram
  5. snd_dma_alloc_pages
  6. snd_dma_alloc_pages_fallback
  7. snd_dma_free_pages

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   4  *                   Takashi Iwai <tiwai@suse.de>
   5  * 
   6  *  Generic memory allocators
   7  */
   8 
   9 #include <linux/slab.h>
  10 #include <linux/mm.h>
  11 #include <linux/dma-mapping.h>
  12 #include <linux/genalloc.h>
  13 #ifdef CONFIG_X86
  14 #include <asm/set_memory.h>
  15 #endif
  16 #include <sound/memalloc.h>
  17 
  18 /*
  19  *
  20  *  Bus-specific memory allocators
  21  *
  22  */
  23 
  24 #ifdef CONFIG_HAS_DMA
  25 /* allocate the coherent DMA pages */
  26 static void snd_malloc_dev_pages(struct snd_dma_buffer *dmab, size_t size)
  27 {
  28         gfp_t gfp_flags;
  29 
  30         gfp_flags = GFP_KERNEL
  31                 | __GFP_COMP    /* compound page lets parts be mapped */
  32                 | __GFP_NORETRY /* don't trigger OOM-killer */
  33                 | __GFP_NOWARN; /* no stack trace print - this call is non-critical */
  34         dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr,
  35                                         gfp_flags);
  36 #ifdef CONFIG_X86
  37         if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
  38                 set_memory_wc((unsigned long)dmab->area,
  39                               PAGE_ALIGN(size) >> PAGE_SHIFT);
  40 #endif
  41 }
  42 
  43 /* free the coherent DMA pages */
  44 static void snd_free_dev_pages(struct snd_dma_buffer *dmab)
  45 {
  46 #ifdef CONFIG_X86
  47         if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
  48                 set_memory_wb((unsigned long)dmab->area,
  49                               PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
  50 #endif
  51         dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
  52 }
  53 
  54 #ifdef CONFIG_GENERIC_ALLOCATOR
  55 /**
  56  * snd_malloc_dev_iram - allocate memory from on-chip internal ram
  57  * @dmab: buffer allocation record to store the allocated data
  58  * @size: number of bytes to allocate from the iram
  59  *
  60  * This function requires iram phandle provided via of_node
  61  */
  62 static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size)
  63 {
  64         struct device *dev = dmab->dev.dev;
  65         struct gen_pool *pool = NULL;
  66 
  67         dmab->area = NULL;
  68         dmab->addr = 0;
  69 
  70         if (dev->of_node)
  71                 pool = of_gen_pool_get(dev->of_node, "iram", 0);
  72 
  73         if (!pool)
  74                 return;
  75 
  76         /* Assign the pool into private_data field */
  77         dmab->private_data = pool;
  78 
  79         dmab->area = gen_pool_dma_alloc(pool, size, &dmab->addr);
  80 }
  81 
  82 /**
  83  * snd_free_dev_iram - free allocated specific memory from on-chip internal ram
  84  * @dmab: buffer allocation record to store the allocated data
  85  */
  86 static void snd_free_dev_iram(struct snd_dma_buffer *dmab)
  87 {
  88         struct gen_pool *pool = dmab->private_data;
  89 
  90         if (pool && dmab->area)
  91                 gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes);
  92 }
  93 #endif /* CONFIG_GENERIC_ALLOCATOR */
  94 #endif /* CONFIG_HAS_DMA */
  95 
  96 /*
  97  *
  98  *  ALSA generic memory management
  99  *
 100  */
 101 
 102 
 103 /**
 104  * snd_dma_alloc_pages - allocate the buffer area according to the given type
 105  * @type: the DMA buffer type
 106  * @device: the device pointer
 107  * @size: the buffer size to allocate
 108  * @dmab: buffer allocation record to store the allocated data
 109  *
 110  * Calls the memory-allocator function for the corresponding
 111  * buffer type.
 112  *
 113  * Return: Zero if the buffer with the given size is allocated successfully,
 114  * otherwise a negative value on error.
 115  */
 116 int snd_dma_alloc_pages(int type, struct device *device, size_t size,
 117                         struct snd_dma_buffer *dmab)
 118 {
 119         if (WARN_ON(!size))
 120                 return -ENXIO;
 121         if (WARN_ON(!dmab))
 122                 return -ENXIO;
 123         if (WARN_ON(!device))
 124                 return -EINVAL;
 125 
 126         dmab->dev.type = type;
 127         dmab->dev.dev = device;
 128         dmab->bytes = 0;
 129         switch (type) {
 130         case SNDRV_DMA_TYPE_CONTINUOUS:
 131                 dmab->area = alloc_pages_exact(size,
 132                                                (__force gfp_t)(unsigned long)device);
 133                 dmab->addr = 0;
 134                 break;
 135 #ifdef CONFIG_HAS_DMA
 136 #ifdef CONFIG_GENERIC_ALLOCATOR
 137         case SNDRV_DMA_TYPE_DEV_IRAM:
 138                 snd_malloc_dev_iram(dmab, size);
 139                 if (dmab->area)
 140                         break;
 141                 /* Internal memory might have limited size and no enough space,
 142                  * so if we fail to malloc, try to fetch memory traditionally.
 143                  */
 144                 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
 145 #endif /* CONFIG_GENERIC_ALLOCATOR */
 146                 /* fall through */
 147         case SNDRV_DMA_TYPE_DEV:
 148         case SNDRV_DMA_TYPE_DEV_UC:
 149                 snd_malloc_dev_pages(dmab, size);
 150                 break;
 151 #endif
 152 #ifdef CONFIG_SND_DMA_SGBUF
 153         case SNDRV_DMA_TYPE_DEV_SG:
 154         case SNDRV_DMA_TYPE_DEV_UC_SG:
 155                 snd_malloc_sgbuf_pages(device, size, dmab, NULL);
 156                 break;
 157 #endif
 158         default:
 159                 pr_err("snd-malloc: invalid device type %d\n", type);
 160                 dmab->area = NULL;
 161                 dmab->addr = 0;
 162                 return -ENXIO;
 163         }
 164         if (! dmab->area)
 165                 return -ENOMEM;
 166         dmab->bytes = size;
 167         return 0;
 168 }
 169 EXPORT_SYMBOL(snd_dma_alloc_pages);
 170 
 171 /**
 172  * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
 173  * @type: the DMA buffer type
 174  * @device: the device pointer
 175  * @size: the buffer size to allocate
 176  * @dmab: buffer allocation record to store the allocated data
 177  *
 178  * Calls the memory-allocator function for the corresponding
 179  * buffer type.  When no space is left, this function reduces the size and
 180  * tries to allocate again.  The size actually allocated is stored in
 181  * res_size argument.
 182  *
 183  * Return: Zero if the buffer with the given size is allocated successfully,
 184  * otherwise a negative value on error.
 185  */
 186 int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
 187                                  struct snd_dma_buffer *dmab)
 188 {
 189         int err;
 190 
 191         while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
 192                 if (err != -ENOMEM)
 193                         return err;
 194                 if (size <= PAGE_SIZE)
 195                         return -ENOMEM;
 196                 size >>= 1;
 197                 size = PAGE_SIZE << get_order(size);
 198         }
 199         if (! dmab->area)
 200                 return -ENOMEM;
 201         return 0;
 202 }
 203 EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
 204 
 205 
 206 /**
 207  * snd_dma_free_pages - release the allocated buffer
 208  * @dmab: the buffer allocation record to release
 209  *
 210  * Releases the allocated buffer via snd_dma_alloc_pages().
 211  */
 212 void snd_dma_free_pages(struct snd_dma_buffer *dmab)
 213 {
 214         switch (dmab->dev.type) {
 215         case SNDRV_DMA_TYPE_CONTINUOUS:
 216                 free_pages_exact(dmab->area, dmab->bytes);
 217                 break;
 218 #ifdef CONFIG_HAS_DMA
 219 #ifdef CONFIG_GENERIC_ALLOCATOR
 220         case SNDRV_DMA_TYPE_DEV_IRAM:
 221                 snd_free_dev_iram(dmab);
 222                 break;
 223 #endif /* CONFIG_GENERIC_ALLOCATOR */
 224         case SNDRV_DMA_TYPE_DEV:
 225         case SNDRV_DMA_TYPE_DEV_UC:
 226                 snd_free_dev_pages(dmab);
 227                 break;
 228 #endif
 229 #ifdef CONFIG_SND_DMA_SGBUF
 230         case SNDRV_DMA_TYPE_DEV_SG:
 231         case SNDRV_DMA_TYPE_DEV_UC_SG:
 232                 snd_free_sgbuf_pages(dmab);
 233                 break;
 234 #endif
 235         default:
 236                 pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
 237         }
 238 }
 239 EXPORT_SYMBOL(snd_dma_free_pages);

/* [<][>][^][v][top][bottom][index][help] */