Linux Audio

Check our new training course

Loading...
v5.9
  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 */
 27static void snd_malloc_dev_pages(struct snd_dma_buffer *dmab, size_t size)
 28{
 
 29	gfp_t gfp_flags;
 30
 
 
 
 31	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	dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr,
 36					gfp_flags);
 37#ifdef CONFIG_X86
 38	if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
 39		set_memory_wc((unsigned long)dmab->area,
 40			      PAGE_ALIGN(size) >> PAGE_SHIFT);
 41#endif
 42}
 43
 44/* free the coherent DMA pages */
 45static void snd_free_dev_pages(struct snd_dma_buffer *dmab)
 
 46{
 47#ifdef CONFIG_X86
 48	if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
 49		set_memory_wb((unsigned long)dmab->area,
 50			      PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
 51#endif
 52	dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 53}
 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 */
 63static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size)
 64{
 65	struct device *dev = dmab->dev.dev;
 66	struct gen_pool *pool = NULL;
 67
 68	dmab->area = NULL;
 69	dmab->addr = 0;
 70
 71	if (dev->of_node)
 72		pool = of_gen_pool_get(dev->of_node, "iram", 0);
 73
 74	if (!pool)
 75		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 */
 87static void snd_free_dev_iram(struct snd_dma_buffer *dmab)
 88{
 89	struct gen_pool *pool = dmab->private_data;
 90
 91	if (pool && dmab->area)
 92		gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes);
 93}
 94#endif /* CONFIG_GENERIC_ALLOCATOR */
 95#endif /* CONFIG_HAS_DMA */
 96
 97/*
 98 *
 99 *  ALSA generic memory management
100 *
101 */
102
103static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev,
104					  gfp_t default_gfp)
105{
106	if (!dev)
107		return default_gfp;
108	else
109		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 */
125int snd_dma_alloc_pages(int type, struct device *device, size_t size,
126			struct snd_dma_buffer *dmab)
127{
128	gfp_t gfp;
129
130	if (WARN_ON(!size))
131		return -ENXIO;
132	if (WARN_ON(!dmab))
133		return -ENXIO;
134
135	dmab->dev.type = type;
136	dmab->dev.dev = device;
137	dmab->bytes = 0;
138	dmab->area = NULL;
139	dmab->addr = 0;
140	dmab->private_data = NULL;
141	switch (type) {
142	case SNDRV_DMA_TYPE_CONTINUOUS:
143		gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL);
144		dmab->area = alloc_pages_exact(size, gfp);
145		break;
146	case SNDRV_DMA_TYPE_VMALLOC:
147		gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL | __GFP_HIGHMEM);
148		dmab->area = __vmalloc(size, gfp);
149		break;
150#ifdef CONFIG_HAS_DMA
151#ifdef CONFIG_GENERIC_ALLOCATOR
152	case SNDRV_DMA_TYPE_DEV_IRAM:
153		snd_malloc_dev_iram(dmab, size);
154		if (dmab->area)
155			break;
156		/* Internal memory might have limited size and no enough space,
157		 * so if we fail to malloc, try to fetch memory traditionally.
158		 */
159		dmab->dev.type = SNDRV_DMA_TYPE_DEV;
160#endif /* CONFIG_GENERIC_ALLOCATOR */
161		fallthrough;
162	case SNDRV_DMA_TYPE_DEV:
163	case SNDRV_DMA_TYPE_DEV_UC:
164		snd_malloc_dev_pages(dmab, size);
165		break;
166#endif
167#ifdef CONFIG_SND_DMA_SGBUF
168	case SNDRV_DMA_TYPE_DEV_SG:
169	case SNDRV_DMA_TYPE_DEV_UC_SG:
170		snd_malloc_sgbuf_pages(device, size, dmab, NULL);
171		break;
172#endif
173	default:
174		pr_err("snd-malloc: invalid device type %d\n", type);
 
 
175		return -ENXIO;
176	}
177	if (! dmab->area)
178		return -ENOMEM;
179	dmab->bytes = size;
180	return 0;
181}
182EXPORT_SYMBOL(snd_dma_alloc_pages);
183
184/**
185 * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
186 * @type: the DMA buffer type
187 * @device: the device pointer
188 * @size: the buffer size to allocate
189 * @dmab: buffer allocation record to store the allocated data
190 *
191 * Calls the memory-allocator function for the corresponding
192 * buffer type.  When no space is left, this function reduces the size and
193 * tries to allocate again.  The size actually allocated is stored in
194 * res_size argument.
195 *
196 * Return: Zero if the buffer with the given size is allocated successfully,
197 * otherwise a negative value on error.
198 */
199int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
200				 struct snd_dma_buffer *dmab)
201{
202	int err;
203
204	while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
 
205		if (err != -ENOMEM)
206			return err;
207		if (size <= PAGE_SIZE)
208			return -ENOMEM;
209		size >>= 1;
210		size = PAGE_SIZE << get_order(size);
 
 
 
211	}
212	if (! dmab->area)
213		return -ENOMEM;
214	return 0;
215}
216EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
217
218
219/**
220 * snd_dma_free_pages - release the allocated buffer
221 * @dmab: the buffer allocation record to release
222 *
223 * Releases the allocated buffer via snd_dma_alloc_pages().
224 */
225void snd_dma_free_pages(struct snd_dma_buffer *dmab)
226{
227	switch (dmab->dev.type) {
228	case SNDRV_DMA_TYPE_CONTINUOUS:
229		free_pages_exact(dmab->area, dmab->bytes);
230		break;
231	case SNDRV_DMA_TYPE_VMALLOC:
232		vfree(dmab->area);
233		break;
234#ifdef CONFIG_HAS_DMA
235#ifdef CONFIG_GENERIC_ALLOCATOR
236	case SNDRV_DMA_TYPE_DEV_IRAM:
237		snd_free_dev_iram(dmab);
238		break;
239#endif /* CONFIG_GENERIC_ALLOCATOR */
240	case SNDRV_DMA_TYPE_DEV:
241	case SNDRV_DMA_TYPE_DEV_UC:
242		snd_free_dev_pages(dmab);
243		break;
244#endif
245#ifdef CONFIG_SND_DMA_SGBUF
246	case SNDRV_DMA_TYPE_DEV_SG:
247	case SNDRV_DMA_TYPE_DEV_UC_SG:
248		snd_free_sgbuf_pages(dmab);
249		break;
250#endif
251	default:
252		pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
253	}
254}
 
 
 
 
 
 
255EXPORT_SYMBOL(snd_dma_free_pages);
v3.15
 
  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);