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