Branch data Line data Source code
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 : 3312 : 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 : 0 : 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 : 0 : dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); 52 : 0 : } 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 : 0 : static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size) 63 : : { 64 : 0 : struct device *dev = dmab->dev.dev; 65 : : struct gen_pool *pool = NULL; 66 : : 67 : 0 : dmab->area = NULL; 68 : 0 : dmab->addr = 0; 69 : : 70 [ # # ]: 0 : if (dev->of_node) 71 : 0 : pool = of_gen_pool_get(dev->of_node, "iram", 0); 72 : : 73 [ # # ]: 0 : if (!pool) 74 : 0 : return; 75 : : 76 : : /* Assign the pool into private_data field */ 77 : 0 : dmab->private_data = pool; 78 : : 79 : 0 : 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 : 0 : static void snd_free_dev_iram(struct snd_dma_buffer *dmab) 87 : : { 88 : 0 : struct gen_pool *pool = dmab->private_data; 89 : : 90 [ # # # # ]: 0 : if (pool && dmab->area) 91 : 0 : gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes); 92 : 0 : } 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 : 1656 : int snd_dma_alloc_pages(int type, struct device *device, size_t size, 117 : : struct snd_dma_buffer *dmab) 118 : : { 119 [ - + + - ]: 1656 : if (WARN_ON(!size)) 120 : : return -ENXIO; 121 [ - + + - ]: 1656 : if (WARN_ON(!dmab)) 122 : : return -ENXIO; 123 [ - + + - ]: 1656 : if (WARN_ON(!device)) 124 : : return -EINVAL; 125 : : 126 : 1656 : dmab->dev.type = type; 127 : 1656 : dmab->dev.dev = device; 128 : 1656 : dmab->bytes = 0; 129 [ - - + - ]: 1656 : switch (type) { 130 : : case SNDRV_DMA_TYPE_CONTINUOUS: 131 : 0 : dmab->area = alloc_pages_exact(size, 132 : : (__force gfp_t)(unsigned long)device); 133 : 0 : dmab->addr = 0; 134 : 0 : break; 135 : : #ifdef CONFIG_HAS_DMA 136 : : #ifdef CONFIG_GENERIC_ALLOCATOR 137 : : case SNDRV_DMA_TYPE_DEV_IRAM: 138 : 0 : snd_malloc_dev_iram(dmab, size); 139 [ # # ]: 0 : 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 : 0 : 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 : 0 : pr_err("snd-malloc: invalid device type %d\n", type); 160 : 0 : dmab->area = NULL; 161 : 0 : dmab->addr = 0; 162 : 0 : return -ENXIO; 163 : : } 164 [ + - ]: 1656 : if (! dmab->area) 165 : : return -ENOMEM; 166 : 1656 : dmab->bytes = size; 167 : 1656 : 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 : 0 : 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 [ # # ]: 0 : while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) { 192 [ # # ]: 0 : if (err != -ENOMEM) 193 : 0 : return err; 194 [ # # ]: 0 : if (size <= PAGE_SIZE) 195 : : return -ENOMEM; 196 : 0 : size >>= 1; 197 : 0 : size = PAGE_SIZE << get_order(size); 198 : : } 199 [ # # ]: 0 : if (! dmab->area) 200 : : return -ENOMEM; 201 : 0 : 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 : 0 : void snd_dma_free_pages(struct snd_dma_buffer *dmab) 213 : : { 214 [ # # # # ]: 0 : switch (dmab->dev.type) { 215 : : case SNDRV_DMA_TYPE_CONTINUOUS: 216 : 0 : free_pages_exact(dmab->area, dmab->bytes); 217 : 0 : break; 218 : : #ifdef CONFIG_HAS_DMA 219 : : #ifdef CONFIG_GENERIC_ALLOCATOR 220 : : case SNDRV_DMA_TYPE_DEV_IRAM: 221 : 0 : snd_free_dev_iram(dmab); 222 : 0 : break; 223 : : #endif /* CONFIG_GENERIC_ALLOCATOR */ 224 : : case SNDRV_DMA_TYPE_DEV: 225 : : case SNDRV_DMA_TYPE_DEV_UC: 226 : 0 : snd_free_dev_pages(dmab); 227 : 0 : 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 : 0 : pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); 237 : : } 238 : 0 : } 239 : : EXPORT_SYMBOL(snd_dma_free_pages);