xref: /openbmc/linux/sound/core/memalloc.c (revision 9726bfcd)
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);
240