]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
c1017a4c | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
1da177e4 LT |
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 | ||
1da177e4 LT |
24 | #include <linux/slab.h> |
25 | #include <linux/mm.h> | |
26 | #include <linux/dma-mapping.h> | |
05503214 | 27 | #include <linux/genalloc.h> |
42e748a0 TI |
28 | #ifdef CONFIG_X86 |
29 | #include <asm/set_memory.h> | |
30 | #endif | |
1da177e4 | 31 | #include <sound/memalloc.h> |
1da177e4 | 32 | |
1da177e4 LT |
33 | /* |
34 | * | |
35 | * Generic memory allocators | |
36 | * | |
37 | */ | |
38 | ||
1da177e4 LT |
39 | /** |
40 | * snd_malloc_pages - allocate pages with the given size | |
41 | * @size: the size to allocate in bytes | |
42 | * @gfp_flags: the allocation conditions, GFP_XXX | |
43 | * | |
44 | * Allocates the physically contiguous pages with the given size. | |
45 | * | |
eb7c06e8 | 46 | * Return: The pointer of the buffer, or %NULL if no enough memory. |
1da177e4 | 47 | */ |
1ef64e67 | 48 | void *snd_malloc_pages(size_t size, gfp_t gfp_flags) |
1da177e4 LT |
49 | { |
50 | int pg; | |
1da177e4 | 51 | |
7eaa943c TI |
52 | if (WARN_ON(!size)) |
53 | return NULL; | |
54 | if (WARN_ON(!gfp_flags)) | |
55 | return NULL; | |
f3d48f03 | 56 | gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */ |
1da177e4 | 57 | pg = get_order(size); |
d7b13541 | 58 | return (void *) __get_free_pages(gfp_flags, pg); |
1da177e4 | 59 | } |
35f80014 | 60 | EXPORT_SYMBOL(snd_malloc_pages); |
1da177e4 LT |
61 | |
62 | /** | |
63 | * snd_free_pages - release the pages | |
64 | * @ptr: the buffer pointer to release | |
65 | * @size: the allocated buffer size | |
66 | * | |
67 | * Releases the buffer allocated via snd_malloc_pages(). | |
68 | */ | |
69 | void snd_free_pages(void *ptr, size_t size) | |
70 | { | |
71 | int pg; | |
72 | ||
73 | if (ptr == NULL) | |
74 | return; | |
75 | pg = get_order(size); | |
1da177e4 LT |
76 | free_pages((unsigned long) ptr, pg); |
77 | } | |
35f80014 | 78 | EXPORT_SYMBOL(snd_free_pages); |
1da177e4 LT |
79 | |
80 | /* | |
81 | * | |
82 | * Bus-specific memory allocators | |
83 | * | |
84 | */ | |
85 | ||
8f11551b | 86 | #ifdef CONFIG_HAS_DMA |
1da177e4 | 87 | /* allocate the coherent DMA pages */ |
28f3f4f6 | 88 | static void snd_malloc_dev_pages(struct snd_dma_buffer *dmab, size_t size) |
1da177e4 | 89 | { |
1ef64e67 | 90 | gfp_t gfp_flags; |
1da177e4 | 91 | |
1da177e4 | 92 | gfp_flags = GFP_KERNEL |
f3d48f03 | 93 | | __GFP_COMP /* compound page lets parts be mapped */ |
1da177e4 LT |
94 | | __GFP_NORETRY /* don't trigger OOM-killer */ |
95 | | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ | |
28f3f4f6 TI |
96 | dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, |
97 | gfp_flags); | |
42e748a0 TI |
98 | #ifdef CONFIG_X86 |
99 | if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) | |
100 | set_memory_wc((unsigned long)dmab->area, | |
101 | PAGE_ALIGN(size) >> PAGE_SHIFT); | |
102 | #endif | |
1da177e4 LT |
103 | } |
104 | ||
105 | /* free the coherent DMA pages */ | |
28f3f4f6 | 106 | static void snd_free_dev_pages(struct snd_dma_buffer *dmab) |
1da177e4 | 107 | { |
42e748a0 TI |
108 | #ifdef CONFIG_X86 |
109 | if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) | |
110 | set_memory_wb((unsigned long)dmab->area, | |
111 | PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT); | |
112 | #endif | |
28f3f4f6 | 113 | dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); |
1da177e4 | 114 | } |
05503214 | 115 | |
63437313 | 116 | #ifdef CONFIG_GENERIC_ALLOCATOR |
05503214 NC |
117 | /** |
118 | * snd_malloc_dev_iram - allocate memory from on-chip internal ram | |
119 | * @dmab: buffer allocation record to store the allocated data | |
120 | * @size: number of bytes to allocate from the iram | |
121 | * | |
122 | * This function requires iram phandle provided via of_node | |
123 | */ | |
9f694bc7 | 124 | static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size) |
05503214 NC |
125 | { |
126 | struct device *dev = dmab->dev.dev; | |
127 | struct gen_pool *pool = NULL; | |
128 | ||
a40a3937 TI |
129 | dmab->area = NULL; |
130 | dmab->addr = 0; | |
131 | ||
05503214 | 132 | if (dev->of_node) |
abdd4a70 | 133 | pool = of_gen_pool_get(dev->of_node, "iram", 0); |
05503214 NC |
134 | |
135 | if (!pool) | |
136 | return; | |
137 | ||
138 | /* Assign the pool into private_data field */ | |
139 | dmab->private_data = pool; | |
140 | ||
07968fe4 | 141 | dmab->area = gen_pool_dma_alloc(pool, size, &dmab->addr); |
05503214 NC |
142 | } |
143 | ||
144 | /** | |
145 | * snd_free_dev_iram - free allocated specific memory from on-chip internal ram | |
146 | * @dmab: buffer allocation record to store the allocated data | |
147 | */ | |
9f694bc7 | 148 | static void snd_free_dev_iram(struct snd_dma_buffer *dmab) |
05503214 NC |
149 | { |
150 | struct gen_pool *pool = dmab->private_data; | |
151 | ||
152 | if (pool && dmab->area) | |
153 | gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes); | |
154 | } | |
63437313 | 155 | #endif /* CONFIG_GENERIC_ALLOCATOR */ |
8f11551b | 156 | #endif /* CONFIG_HAS_DMA */ |
1da177e4 | 157 | |
1da177e4 LT |
158 | /* |
159 | * | |
160 | * ALSA generic memory management | |
161 | * | |
162 | */ | |
163 | ||
164 | ||
165 | /** | |
166 | * snd_dma_alloc_pages - allocate the buffer area according to the given type | |
167 | * @type: the DMA buffer type | |
168 | * @device: the device pointer | |
169 | * @size: the buffer size to allocate | |
170 | * @dmab: buffer allocation record to store the allocated data | |
171 | * | |
172 | * Calls the memory-allocator function for the corresponding | |
173 | * buffer type. | |
eb7c06e8 YB |
174 | * |
175 | * Return: Zero if the buffer with the given size is allocated successfully, | |
176 | * otherwise a negative value on error. | |
1da177e4 LT |
177 | */ |
178 | int snd_dma_alloc_pages(int type, struct device *device, size_t size, | |
179 | struct snd_dma_buffer *dmab) | |
180 | { | |
7eaa943c TI |
181 | if (WARN_ON(!size)) |
182 | return -ENXIO; | |
183 | if (WARN_ON(!dmab)) | |
184 | return -ENXIO; | |
1da177e4 LT |
185 | |
186 | dmab->dev.type = type; | |
187 | dmab->dev.dev = device; | |
188 | dmab->bytes = 0; | |
189 | switch (type) { | |
190 | case SNDRV_DMA_TYPE_CONTINUOUS: | |
fea952e5 CL |
191 | dmab->area = snd_malloc_pages(size, |
192 | (__force gfp_t)(unsigned long)device); | |
1da177e4 LT |
193 | dmab->addr = 0; |
194 | break; | |
8f11551b | 195 | #ifdef CONFIG_HAS_DMA |
a5606f85 | 196 | #ifdef CONFIG_GENERIC_ALLOCATOR |
05503214 NC |
197 | case SNDRV_DMA_TYPE_DEV_IRAM: |
198 | snd_malloc_dev_iram(dmab, size); | |
199 | if (dmab->area) | |
200 | break; | |
201 | /* Internal memory might have limited size and no enough space, | |
202 | * so if we fail to malloc, try to fetch memory traditionally. | |
203 | */ | |
204 | dmab->dev.type = SNDRV_DMA_TYPE_DEV; | |
a5606f85 | 205 | #endif /* CONFIG_GENERIC_ALLOCATOR */ |
3c4cfa7b | 206 | /* fall through */ |
1da177e4 | 207 | case SNDRV_DMA_TYPE_DEV: |
42e748a0 | 208 | case SNDRV_DMA_TYPE_DEV_UC: |
28f3f4f6 | 209 | snd_malloc_dev_pages(dmab, size); |
1da177e4 | 210 | break; |
cc6a8acd TI |
211 | #endif |
212 | #ifdef CONFIG_SND_DMA_SGBUF | |
1da177e4 | 213 | case SNDRV_DMA_TYPE_DEV_SG: |
42e748a0 | 214 | case SNDRV_DMA_TYPE_DEV_UC_SG: |
1da177e4 LT |
215 | snd_malloc_sgbuf_pages(device, size, dmab, NULL); |
216 | break; | |
8f11551b | 217 | #endif |
1da177e4 | 218 | default: |
f2f9307a | 219 | pr_err("snd-malloc: invalid device type %d\n", type); |
1da177e4 LT |
220 | dmab->area = NULL; |
221 | dmab->addr = 0; | |
222 | return -ENXIO; | |
223 | } | |
224 | if (! dmab->area) | |
225 | return -ENOMEM; | |
226 | dmab->bytes = size; | |
227 | return 0; | |
228 | } | |
35f80014 | 229 | EXPORT_SYMBOL(snd_dma_alloc_pages); |
1da177e4 LT |
230 | |
231 | /** | |
232 | * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback | |
233 | * @type: the DMA buffer type | |
234 | * @device: the device pointer | |
235 | * @size: the buffer size to allocate | |
236 | * @dmab: buffer allocation record to store the allocated data | |
237 | * | |
238 | * Calls the memory-allocator function for the corresponding | |
239 | * buffer type. When no space is left, this function reduces the size and | |
240 | * tries to allocate again. The size actually allocated is stored in | |
241 | * res_size argument. | |
eb7c06e8 YB |
242 | * |
243 | * Return: Zero if the buffer with the given size is allocated successfully, | |
244 | * otherwise a negative value on error. | |
1da177e4 LT |
245 | */ |
246 | int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, | |
247 | struct snd_dma_buffer *dmab) | |
248 | { | |
249 | int err; | |
250 | ||
1da177e4 LT |
251 | while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) { |
252 | if (err != -ENOMEM) | |
253 | return err; | |
1da177e4 LT |
254 | if (size <= PAGE_SIZE) |
255 | return -ENOMEM; | |
dfef01e1 TI |
256 | size >>= 1; |
257 | size = PAGE_SIZE << get_order(size); | |
1da177e4 LT |
258 | } |
259 | if (! dmab->area) | |
260 | return -ENOMEM; | |
261 | return 0; | |
262 | } | |
35f80014 | 263 | EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); |
1da177e4 LT |
264 | |
265 | ||
266 | /** | |
267 | * snd_dma_free_pages - release the allocated buffer | |
268 | * @dmab: the buffer allocation record to release | |
269 | * | |
270 | * Releases the allocated buffer via snd_dma_alloc_pages(). | |
271 | */ | |
272 | void snd_dma_free_pages(struct snd_dma_buffer *dmab) | |
273 | { | |
274 | switch (dmab->dev.type) { | |
275 | case SNDRV_DMA_TYPE_CONTINUOUS: | |
276 | snd_free_pages(dmab->area, dmab->bytes); | |
277 | break; | |
8f11551b | 278 | #ifdef CONFIG_HAS_DMA |
a5606f85 | 279 | #ifdef CONFIG_GENERIC_ALLOCATOR |
05503214 NC |
280 | case SNDRV_DMA_TYPE_DEV_IRAM: |
281 | snd_free_dev_iram(dmab); | |
282 | break; | |
a5606f85 | 283 | #endif /* CONFIG_GENERIC_ALLOCATOR */ |
1da177e4 | 284 | case SNDRV_DMA_TYPE_DEV: |
42e748a0 | 285 | case SNDRV_DMA_TYPE_DEV_UC: |
28f3f4f6 | 286 | snd_free_dev_pages(dmab); |
1da177e4 | 287 | break; |
cc6a8acd TI |
288 | #endif |
289 | #ifdef CONFIG_SND_DMA_SGBUF | |
1da177e4 | 290 | case SNDRV_DMA_TYPE_DEV_SG: |
42e748a0 | 291 | case SNDRV_DMA_TYPE_DEV_UC_SG: |
1da177e4 LT |
292 | snd_free_sgbuf_pages(dmab); |
293 | break; | |
8f11551b | 294 | #endif |
1da177e4 | 295 | default: |
f2f9307a | 296 | pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); |
1da177e4 LT |
297 | } |
298 | } | |
1da177e4 | 299 | EXPORT_SYMBOL(snd_dma_free_pages); |