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_get_named_gen_pool(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