Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / sound / core / memalloc.c
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);