Linux Audio

Check our new training course

Loading...
v5.4
  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 */
 26static 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 */
 44static 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 */
 62static 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 */
 86static 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 */
116int 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}
169EXPORT_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 */
186int 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}
203EXPORT_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 */
212void 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}
239EXPORT_SYMBOL(snd_dma_free_pages);
v4.17
 
  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}
 57EXPORT_SYMBOL(snd_malloc_pages);
 58
 59/**
 60 * snd_free_pages - release the pages
 61 * @ptr: the buffer pointer to release
 62 * @size: the allocated buffer size
 63 *
 64 * Releases the buffer allocated via snd_malloc_pages().
 65 */
 66void snd_free_pages(void *ptr, size_t size)
 67{
 68	int pg;
 69
 70	if (ptr == NULL)
 71		return;
 72	pg = get_order(size);
 73	free_pages((unsigned long) ptr, pg);
 74}
 75EXPORT_SYMBOL(snd_free_pages);
 76
 77/*
 78 *
 79 *  Bus-specific memory allocators
 80 *
 81 */
 82
 83#ifdef CONFIG_HAS_DMA
 84/* allocate the coherent DMA pages */
 85static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
 86{
 87	int pg;
 88	gfp_t gfp_flags;
 89
 90	if (WARN_ON(!dma))
 91		return NULL;
 92	pg = get_order(size);
 93	gfp_flags = GFP_KERNEL
 94		| __GFP_COMP	/* compound page lets parts be mapped */
 95		| __GFP_NORETRY /* don't trigger OOM-killer */
 96		| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
 97	return dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
 
 
 
 
 
 
 98}
 99
100/* free the coherent DMA pages */
101static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
102			       dma_addr_t dma)
103{
104	int pg;
105
106	if (ptr == NULL)
107		return;
108	pg = get_order(size);
109	dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
110}
111
112#ifdef CONFIG_GENERIC_ALLOCATOR
113/**
114 * snd_malloc_dev_iram - allocate memory from on-chip internal ram
115 * @dmab: buffer allocation record to store the allocated data
116 * @size: number of bytes to allocate from the iram
117 *
118 * This function requires iram phandle provided via of_node
119 */
120static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size)
121{
122	struct device *dev = dmab->dev.dev;
123	struct gen_pool *pool = NULL;
124
125	dmab->area = NULL;
126	dmab->addr = 0;
127
128	if (dev->of_node)
129		pool = of_gen_pool_get(dev->of_node, "iram", 0);
130
131	if (!pool)
132		return;
133
134	/* Assign the pool into private_data field */
135	dmab->private_data = pool;
136
137	dmab->area = gen_pool_dma_alloc(pool, size, &dmab->addr);
138}
139
140/**
141 * snd_free_dev_iram - free allocated specific memory from on-chip internal ram
142 * @dmab: buffer allocation record to store the allocated data
143 */
144static void snd_free_dev_iram(struct snd_dma_buffer *dmab)
145{
146	struct gen_pool *pool = dmab->private_data;
147
148	if (pool && dmab->area)
149		gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes);
150}
151#endif /* CONFIG_GENERIC_ALLOCATOR */
152#endif /* CONFIG_HAS_DMA */
153
154/*
155 *
156 *  ALSA generic memory management
157 *
158 */
159
160
161/**
162 * snd_dma_alloc_pages - allocate the buffer area according to the given type
163 * @type: the DMA buffer type
164 * @device: the device pointer
165 * @size: the buffer size to allocate
166 * @dmab: buffer allocation record to store the allocated data
167 *
168 * Calls the memory-allocator function for the corresponding
169 * buffer type.
170 *
171 * Return: Zero if the buffer with the given size is allocated successfully,
172 * otherwise a negative value on error.
173 */
174int snd_dma_alloc_pages(int type, struct device *device, size_t size,
175			struct snd_dma_buffer *dmab)
176{
177	if (WARN_ON(!size))
178		return -ENXIO;
179	if (WARN_ON(!dmab))
180		return -ENXIO;
 
 
181
182	dmab->dev.type = type;
183	dmab->dev.dev = device;
184	dmab->bytes = 0;
185	switch (type) {
186	case SNDRV_DMA_TYPE_CONTINUOUS:
187		dmab->area = snd_malloc_pages(size,
188					(__force gfp_t)(unsigned long)device);
189		dmab->addr = 0;
190		break;
191#ifdef CONFIG_HAS_DMA
192#ifdef CONFIG_GENERIC_ALLOCATOR
193	case SNDRV_DMA_TYPE_DEV_IRAM:
194		snd_malloc_dev_iram(dmab, size);
195		if (dmab->area)
196			break;
197		/* Internal memory might have limited size and no enough space,
198		 * so if we fail to malloc, try to fetch memory traditionally.
199		 */
200		dmab->dev.type = SNDRV_DMA_TYPE_DEV;
201#endif /* CONFIG_GENERIC_ALLOCATOR */
 
202	case SNDRV_DMA_TYPE_DEV:
203		dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
 
204		break;
205#endif
206#ifdef CONFIG_SND_DMA_SGBUF
207	case SNDRV_DMA_TYPE_DEV_SG:
 
208		snd_malloc_sgbuf_pages(device, size, dmab, NULL);
209		break;
210#endif
211	default:
212		pr_err("snd-malloc: invalid device type %d\n", type);
213		dmab->area = NULL;
214		dmab->addr = 0;
215		return -ENXIO;
216	}
217	if (! dmab->area)
218		return -ENOMEM;
219	dmab->bytes = size;
220	return 0;
221}
222EXPORT_SYMBOL(snd_dma_alloc_pages);
223
224/**
225 * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
226 * @type: the DMA buffer type
227 * @device: the device pointer
228 * @size: the buffer size to allocate
229 * @dmab: buffer allocation record to store the allocated data
230 *
231 * Calls the memory-allocator function for the corresponding
232 * buffer type.  When no space is left, this function reduces the size and
233 * tries to allocate again.  The size actually allocated is stored in
234 * res_size argument.
235 *
236 * Return: Zero if the buffer with the given size is allocated successfully,
237 * otherwise a negative value on error.
238 */
239int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
240				 struct snd_dma_buffer *dmab)
241{
242	int err;
243
244	while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
245		size_t aligned_size;
246		if (err != -ENOMEM)
247			return err;
248		if (size <= PAGE_SIZE)
249			return -ENOMEM;
250		aligned_size = PAGE_SIZE << get_order(size);
251		if (size != aligned_size)
252			size = aligned_size;
253		else
254			size >>= 1;
255	}
256	if (! dmab->area)
257		return -ENOMEM;
258	return 0;
259}
260EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
261
262
263/**
264 * snd_dma_free_pages - release the allocated buffer
265 * @dmab: the buffer allocation record to release
266 *
267 * Releases the allocated buffer via snd_dma_alloc_pages().
268 */
269void snd_dma_free_pages(struct snd_dma_buffer *dmab)
270{
271	switch (dmab->dev.type) {
272	case SNDRV_DMA_TYPE_CONTINUOUS:
273		snd_free_pages(dmab->area, dmab->bytes);
274		break;
275#ifdef CONFIG_HAS_DMA
276#ifdef CONFIG_GENERIC_ALLOCATOR
277	case SNDRV_DMA_TYPE_DEV_IRAM:
278		snd_free_dev_iram(dmab);
279		break;
280#endif /* CONFIG_GENERIC_ALLOCATOR */
281	case SNDRV_DMA_TYPE_DEV:
282		snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 
283		break;
284#endif
285#ifdef CONFIG_SND_DMA_SGBUF
286	case SNDRV_DMA_TYPE_DEV_SG:
 
287		snd_free_sgbuf_pages(dmab);
288		break;
289#endif
290	default:
291		pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
292	}
293}
294EXPORT_SYMBOL(snd_dma_free_pages);