hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/sound/core/pcm_memory.c
....@@ -1,22 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Digital Audio (PCM) abstract layer
34 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4
- *
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
- *
205 */
216
227 #include <linux/io.h>
....@@ -30,6 +15,7 @@
3015 #include <sound/pcm.h>
3116 #include <sound/info.h>
3217 #include <sound/initval.h>
18
+#include "pcm_local.h"
3319
3420 static int preallocate_dma = 1;
3521 module_param(preallocate_dma, int, 0444);
....@@ -41,6 +27,39 @@
4127
4228 static const size_t snd_minimum_buffer = 16384;
4329
30
+static unsigned long max_alloc_per_card = 32UL * 1024UL * 1024UL;
31
+module_param(max_alloc_per_card, ulong, 0644);
32
+MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card.");
33
+
34
+static int do_alloc_pages(struct snd_card *card, int type, struct device *dev,
35
+ size_t size, struct snd_dma_buffer *dmab)
36
+{
37
+ int err;
38
+
39
+ if (max_alloc_per_card &&
40
+ card->total_pcm_alloc_bytes + size > max_alloc_per_card)
41
+ return -ENOMEM;
42
+
43
+ err = snd_dma_alloc_pages(type, dev, size, dmab);
44
+ if (!err) {
45
+ mutex_lock(&card->memory_mutex);
46
+ card->total_pcm_alloc_bytes += dmab->bytes;
47
+ mutex_unlock(&card->memory_mutex);
48
+ }
49
+ return err;
50
+}
51
+
52
+static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
53
+{
54
+ if (!dmab->area)
55
+ return;
56
+ mutex_lock(&card->memory_mutex);
57
+ WARN_ON(card->total_pcm_alloc_bytes < dmab->bytes);
58
+ card->total_pcm_alloc_bytes -= dmab->bytes;
59
+ mutex_unlock(&card->memory_mutex);
60
+ snd_dma_free_pages(dmab);
61
+ dmab->area = NULL;
62
+}
4463
4564 /*
4665 * try to allocate as the large pages as possible.
....@@ -51,16 +70,15 @@
5170 static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
5271 {
5372 struct snd_dma_buffer *dmab = &substream->dma_buffer;
73
+ struct snd_card *card = substream->pcm->card;
5474 size_t orig_size = size;
5575 int err;
5676
5777 do {
58
- if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
59
- size, dmab)) < 0) {
60
- if (err != -ENOMEM)
61
- return err; /* fatal error */
62
- } else
63
- return 0;
78
+ err = do_alloc_pages(card, dmab->dev.type, dmab->dev.dev,
79
+ size, dmab);
80
+ if (err != -ENOMEM)
81
+ return err;
6482 size >>= 1;
6583 } while (size >= snd_minimum_buffer);
6684 dmab->bytes = 0; /* tell error */
....@@ -76,10 +94,7 @@
7694 */
7795 static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream)
7896 {
79
- if (substream->dma_buffer.area == NULL)
80
- return;
81
- snd_dma_free_pages(&substream->dma_buffer);
82
- substream->dma_buffer.area = NULL;
97
+ do_free_pages(substream->pcm->card, &substream->dma_buffer);
8398 }
8499
85100 /**
....@@ -87,19 +102,10 @@
87102 * @substream: the pcm substream instance
88103 *
89104 * Releases the pre-allocated buffer of the given substream.
90
- *
91
- * Return: Zero if successful, or a negative error code on failure.
92105 */
93
-int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
106
+void snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
94107 {
95108 snd_pcm_lib_preallocate_dma_free(substream);
96
-#ifdef CONFIG_SND_VERBOSE_PROCFS
97
- snd_info_free_entry(substream->proc_prealloc_max_entry);
98
- substream->proc_prealloc_max_entry = NULL;
99
- snd_info_free_entry(substream->proc_prealloc_entry);
100
- substream->proc_prealloc_entry = NULL;
101
-#endif
102
- return 0;
103109 }
104110
105111 /**
....@@ -107,10 +113,8 @@
107113 * @pcm: the pcm instance
108114 *
109115 * Releases all the pre-allocated buffers on the given pcm.
110
- *
111
- * Return: Zero if successful, or a negative error code on failure.
112116 */
113
-int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
117
+void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
114118 {
115119 struct snd_pcm_substream *substream;
116120 int stream;
....@@ -118,7 +122,6 @@
118122 for (stream = 0; stream < 2; stream++)
119123 for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
120124 snd_pcm_lib_preallocate_free(substream);
121
- return 0;
122125 }
123126 EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
124127
....@@ -156,68 +159,66 @@
156159 struct snd_info_buffer *buffer)
157160 {
158161 struct snd_pcm_substream *substream = entry->private_data;
162
+ struct snd_card *card = substream->pcm->card;
159163 char line[64], str[64];
160164 size_t size;
161165 struct snd_dma_buffer new_dmab;
162166
167
+ mutex_lock(&substream->pcm->open_mutex);
163168 if (substream->runtime) {
164169 buffer->error = -EBUSY;
165
- return;
170
+ goto unlock;
166171 }
167172 if (!snd_info_get_line(buffer, line, sizeof(line))) {
168173 snd_info_get_str(str, line, sizeof(str));
169174 size = simple_strtoul(str, NULL, 10) * 1024;
170175 if ((size != 0 && size < 8192) || size > substream->dma_max) {
171176 buffer->error = -EINVAL;
172
- return;
177
+ goto unlock;
173178 }
174179 if (substream->dma_buffer.bytes == size)
175
- return;
180
+ goto unlock;
176181 memset(&new_dmab, 0, sizeof(new_dmab));
177182 new_dmab.dev = substream->dma_buffer.dev;
178183 if (size > 0) {
179
- if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
180
- substream->dma_buffer.dev.dev,
181
- size, &new_dmab) < 0) {
184
+ if (do_alloc_pages(card,
185
+ substream->dma_buffer.dev.type,
186
+ substream->dma_buffer.dev.dev,
187
+ size, &new_dmab) < 0) {
182188 buffer->error = -ENOMEM;
183
- return;
189
+ goto unlock;
184190 }
185191 substream->buffer_bytes_max = size;
186192 } else {
187193 substream->buffer_bytes_max = UINT_MAX;
188194 }
189195 if (substream->dma_buffer.area)
190
- snd_dma_free_pages(&substream->dma_buffer);
196
+ do_free_pages(card, &substream->dma_buffer);
191197 substream->dma_buffer = new_dmab;
192198 } else {
193199 buffer->error = -EINVAL;
194200 }
201
+ unlock:
202
+ mutex_unlock(&substream->pcm->open_mutex);
195203 }
196204
197205 static inline void preallocate_info_init(struct snd_pcm_substream *substream)
198206 {
199207 struct snd_info_entry *entry;
200208
201
- if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
202
- entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
209
+ entry = snd_info_create_card_entry(substream->pcm->card, "prealloc",
210
+ substream->proc_root);
211
+ if (entry) {
212
+ snd_info_set_text_ops(entry, substream,
213
+ snd_pcm_lib_preallocate_proc_read);
203214 entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
204215 entry->mode |= 0200;
205
- entry->private_data = substream;
206
- if (snd_info_register(entry) < 0) {
207
- snd_info_free_entry(entry);
208
- entry = NULL;
209
- }
210216 }
211
- substream->proc_prealloc_entry = entry;
212
- if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max", substream->proc_root)) != NULL) {
213
- entry->c.text.read = snd_pcm_lib_preallocate_max_proc_read;
214
- entry->private_data = substream;
215
- if (snd_info_register(entry) < 0) {
216
- snd_info_free_entry(entry);
217
- entry = NULL;
218
- }
219
- }
220
- substream->proc_prealloc_max_entry = entry;
217
+ entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max",
218
+ substream->proc_root);
219
+ if (entry)
220
+ snd_info_set_text_ops(entry, substream,
221
+ snd_pcm_lib_preallocate_max_proc_read);
221222 }
222223
223224 #else /* !CONFIG_SND_VERBOSE_PROCFS */
....@@ -227,9 +228,15 @@
227228 /*
228229 * pre-allocate the buffer and create a proc file for the substream
229230 */
230
-static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
231
- size_t size, size_t max)
231
+static void preallocate_pages(struct snd_pcm_substream *substream,
232
+ int type, struct device *data,
233
+ size_t size, size_t max, bool managed)
232234 {
235
+ if (snd_BUG_ON(substream->dma_buffer.dev.type))
236
+ return;
237
+
238
+ substream->dma_buffer.dev.type = type;
239
+ substream->dma_buffer.dev.dev = data;
233240
234241 if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
235242 preallocate_pcm_pages(substream, size);
....@@ -237,10 +244,25 @@
237244 if (substream->dma_buffer.bytes > 0)
238245 substream->buffer_bytes_max = substream->dma_buffer.bytes;
239246 substream->dma_max = max;
240
- preallocate_info_init(substream);
241
- return 0;
247
+ if (max > 0)
248
+ preallocate_info_init(substream);
249
+ if (managed)
250
+ substream->managed_buffer_alloc = 1;
242251 }
243252
253
+static void preallocate_pages_for_all(struct snd_pcm *pcm, int type,
254
+ void *data, size_t size, size_t max,
255
+ bool managed)
256
+{
257
+ struct snd_pcm_substream *substream;
258
+ int stream;
259
+
260
+ for (stream = 0; stream < 2; stream++)
261
+ for (substream = pcm->streams[stream].substream; substream;
262
+ substream = substream->next)
263
+ preallocate_pages(substream, type, data, size, max,
264
+ managed);
265
+}
244266
245267 /**
246268 * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type
....@@ -251,16 +273,12 @@
251273 * @max: the max. allowed pre-allocation size
252274 *
253275 * Do pre-allocation for the given DMA buffer type.
254
- *
255
- * Return: Zero if successful, or a negative error code on failure.
256276 */
257
-int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
277
+void snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
258278 int type, struct device *data,
259279 size_t size, size_t max)
260280 {
261
- substream->dma_buffer.dev.type = type;
262
- substream->dma_buffer.dev.dev = data;
263
- return snd_pcm_lib_preallocate_pages1(substream, size, max);
281
+ preallocate_pages(substream, type, data, size, max, false);
264282 }
265283 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
266284
....@@ -274,26 +292,62 @@
274292 *
275293 * Do pre-allocation to all substreams of the given pcm for the
276294 * specified DMA type.
277
- *
278
- * Return: Zero if successful, or a negative error code on failure.
279295 */
280
-int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
296
+void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
281297 int type, void *data,
282298 size_t size, size_t max)
283299 {
284
- struct snd_pcm_substream *substream;
285
- int stream, err;
286
-
287
- for (stream = 0; stream < 2; stream++)
288
- for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
289
- if ((err = snd_pcm_lib_preallocate_pages(substream, type, data, size, max)) < 0)
290
- return err;
291
- return 0;
300
+ preallocate_pages_for_all(pcm, type, data, size, max, false);
292301 }
293302 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
294303
295
-#ifdef CONFIG_SND_DMA_SGBUF
296304 /**
305
+ * snd_pcm_set_managed_buffer - set up buffer management for a substream
306
+ * @substream: the pcm substream instance
307
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
308
+ * @data: DMA type dependent data
309
+ * @size: the requested pre-allocation size in bytes
310
+ * @max: the max. allowed pre-allocation size
311
+ *
312
+ * Do pre-allocation for the given DMA buffer type, and set the managed
313
+ * buffer allocation mode to the given substream.
314
+ * In this mode, PCM core will allocate a buffer automatically before PCM
315
+ * hw_params ops call, and release the buffer after PCM hw_free ops call
316
+ * as well, so that the driver doesn't need to invoke the allocation and
317
+ * the release explicitly in its callback.
318
+ * When a buffer is actually allocated before the PCM hw_params call, it
319
+ * turns on the runtime buffer_changed flag for drivers changing their h/w
320
+ * parameters accordingly.
321
+ */
322
+void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
323
+ struct device *data, size_t size, size_t max)
324
+{
325
+ preallocate_pages(substream, type, data, size, max, true);
326
+}
327
+EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
328
+
329
+/**
330
+ * snd_pcm_set_managed_buffer_all - set up buffer management for all substreams
331
+ * for all substreams
332
+ * @pcm: the pcm instance
333
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
334
+ * @data: DMA type dependent data
335
+ * @size: the requested pre-allocation size in bytes
336
+ * @max: the max. allowed pre-allocation size
337
+ *
338
+ * Do pre-allocation to all substreams of the given pcm for the specified DMA
339
+ * type and size, and set the managed_buffer_alloc flag to each substream.
340
+ */
341
+void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
342
+ struct device *data,
343
+ size_t size, size_t max)
344
+{
345
+ preallocate_pages_for_all(pcm, type, data, size, max, true);
346
+}
347
+EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);
348
+
349
+#ifdef CONFIG_SND_DMA_SGBUF
350
+/*
297351 * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
298352 * @substream: the pcm substream instance
299353 * @offset: the buffer offset
....@@ -311,7 +365,6 @@
311365 return NULL;
312366 return sgbuf->page_table[idx];
313367 }
314
-EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
315368 #endif /* CONFIG_SND_DMA_SGBUF */
316369
317370 /**
....@@ -327,6 +380,7 @@
327380 */
328381 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
329382 {
383
+ struct snd_card *card;
330384 struct snd_pcm_runtime *runtime;
331385 struct snd_dma_buffer *dmab = NULL;
332386
....@@ -336,6 +390,7 @@
336390 SNDRV_DMA_TYPE_UNKNOWN))
337391 return -EINVAL;
338392 runtime = substream->runtime;
393
+ card = substream->pcm->card;
339394
340395 if (runtime->dma_buffer_p) {
341396 /* perphaps, we might free the large DMA memory region
....@@ -355,9 +410,10 @@
355410 if (! dmab)
356411 return -ENOMEM;
357412 dmab->dev = substream->dma_buffer.dev;
358
- if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
359
- substream->dma_buffer.dev.dev,
360
- size, dmab) < 0) {
413
+ if (do_alloc_pages(card,
414
+ substream->dma_buffer.dev.type,
415
+ substream->dma_buffer.dev.dev,
416
+ size, dmab) < 0) {
361417 kfree(dmab);
362418 return -ENOMEM;
363419 }
....@@ -386,8 +442,10 @@
386442 if (runtime->dma_area == NULL)
387443 return 0;
388444 if (runtime->dma_buffer_p != &substream->dma_buffer) {
445
+ struct snd_card *card = substream->pcm->card;
446
+
389447 /* it's a newly allocated buffer. release it now. */
390
- snd_dma_free_pages(runtime->dma_buffer_p);
448
+ do_free_pages(card, runtime->dma_buffer_p);
391449 kfree(runtime->dma_buffer_p);
392450 }
393451 snd_pcm_set_runtime_buffer(substream, NULL);
....@@ -408,7 +466,7 @@
408466 return 0; /* already large enough */
409467 vfree(runtime->dma_area);
410468 }
411
- runtime->dma_area = __vmalloc(size, gfp_flags, PAGE_KERNEL);
469
+ runtime->dma_area = __vmalloc(size, gfp_flags);
412470 if (!runtime->dma_area)
413471 return -ENOMEM;
414472 runtime->dma_bytes = size;