1
2
3
4
5
6
7#include <linux/io.h>
8#include <linux/time.h>
9#include <linux/init.h>
10#include <linux/slab.h>
11#include <linux/moduleparam.h>
12#include <linux/vmalloc.h>
13#include <linux/export.h>
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/info.h>
17#include <sound/initval.h>
18#include "pcm_local.h"
19
20static int preallocate_dma = 1;
21module_param(preallocate_dma, int, 0444);
22MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized.");
23
24static int maximum_substreams = 4;
25module_param(maximum_substreams, int, 0444);
26MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory.");
27
28static const size_t snd_minimum_buffer = 16384;
29
30static unsigned long max_alloc_per_card = 32UL * 1024UL * 1024UL;
31module_param(max_alloc_per_card, ulong, 0644);
32MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card.");
33
34static 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
52static 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}
63
64
65
66
67
68
69
70static int preallocate_pcm_pages(struct snd_pcm_substream *substream,
71 size_t size, bool no_fallback)
72{
73 struct snd_dma_buffer *dmab = &substream->dma_buffer;
74 struct snd_card *card = substream->pcm->card;
75 size_t orig_size = size;
76 int err;
77
78 do {
79 err = do_alloc_pages(card, dmab->dev.type, dmab->dev.dev,
80 size, dmab);
81 if (err != -ENOMEM)
82 return err;
83 if (no_fallback)
84 break;
85 size >>= 1;
86 } while (size >= snd_minimum_buffer);
87 dmab->bytes = 0;
88 pr_warn("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
89 substream->pcm->card->number, substream->pcm->device,
90 substream->stream ? 'c' : 'p', substream->number,
91 substream->pcm->name, orig_size);
92 return -ENOMEM;
93}
94
95
96
97
98
99
100
101void snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
102{
103 do_free_pages(substream->pcm->card, &substream->dma_buffer);
104}
105
106
107
108
109
110
111
112void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
113{
114 struct snd_pcm_substream *substream;
115 int stream;
116
117 for_each_pcm_substream(pcm, stream, substream)
118 snd_pcm_lib_preallocate_free(substream);
119}
120EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
121
122#ifdef CONFIG_SND_VERBOSE_PROCFS
123
124
125
126
127
128static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry,
129 struct snd_info_buffer *buffer)
130{
131 struct snd_pcm_substream *substream = entry->private_data;
132 snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024);
133}
134
135
136
137
138
139
140static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry,
141 struct snd_info_buffer *buffer)
142{
143 struct snd_pcm_substream *substream = entry->private_data;
144 snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024);
145}
146
147
148
149
150
151
152static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
153 struct snd_info_buffer *buffer)
154{
155 struct snd_pcm_substream *substream = entry->private_data;
156 struct snd_card *card = substream->pcm->card;
157 char line[64], str[64];
158 size_t size;
159 struct snd_dma_buffer new_dmab;
160
161 if (substream->runtime) {
162 buffer->error = -EBUSY;
163 return;
164 }
165 if (!snd_info_get_line(buffer, line, sizeof(line))) {
166 snd_info_get_str(str, line, sizeof(str));
167 size = simple_strtoul(str, NULL, 10) * 1024;
168 if ((size != 0 && size < 8192) || size > substream->dma_max) {
169 buffer->error = -EINVAL;
170 return;
171 }
172 if (substream->dma_buffer.bytes == size)
173 return;
174 memset(&new_dmab, 0, sizeof(new_dmab));
175 new_dmab.dev = substream->dma_buffer.dev;
176 if (size > 0) {
177 if (do_alloc_pages(card,
178 substream->dma_buffer.dev.type,
179 substream->dma_buffer.dev.dev,
180 size, &new_dmab) < 0) {
181 buffer->error = -ENOMEM;
182 pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
183 substream->pcm->card->number, substream->pcm->device,
184 substream->stream ? 'c' : 'p', substream->number,
185 substream->pcm->name, size);
186 return;
187 }
188 substream->buffer_bytes_max = size;
189 } else {
190 substream->buffer_bytes_max = UINT_MAX;
191 }
192 if (substream->dma_buffer.area)
193 do_free_pages(card, &substream->dma_buffer);
194 substream->dma_buffer = new_dmab;
195 } else {
196 buffer->error = -EINVAL;
197 }
198}
199
200static inline void preallocate_info_init(struct snd_pcm_substream *substream)
201{
202 struct snd_info_entry *entry;
203
204 entry = snd_info_create_card_entry(substream->pcm->card, "prealloc",
205 substream->proc_root);
206 if (entry) {
207 snd_info_set_text_ops(entry, substream,
208 snd_pcm_lib_preallocate_proc_read);
209 entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
210 entry->mode |= 0200;
211 }
212 entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max",
213 substream->proc_root);
214 if (entry)
215 snd_info_set_text_ops(entry, substream,
216 snd_pcm_lib_preallocate_max_proc_read);
217}
218
219#else
220static inline void preallocate_info_init(struct snd_pcm_substream *substream)
221{
222}
223#endif
224
225
226
227
228static int preallocate_pages(struct snd_pcm_substream *substream,
229 int type, struct device *data,
230 size_t size, size_t max, bool managed)
231{
232 int err;
233
234 if (snd_BUG_ON(substream->dma_buffer.dev.type))
235 return -EINVAL;
236
237 substream->dma_buffer.dev.type = type;
238 substream->dma_buffer.dev.dev = data;
239
240 if (size > 0) {
241 if (!max) {
242
243 err = preallocate_pcm_pages(substream, size, true);
244 if (err < 0)
245 return err;
246 } else if (preallocate_dma &&
247 substream->number < maximum_substreams) {
248 err = preallocate_pcm_pages(substream, size, false);
249 if (err < 0 && err != -ENOMEM)
250 return err;
251 }
252 }
253
254 if (substream->dma_buffer.bytes > 0)
255 substream->buffer_bytes_max = substream->dma_buffer.bytes;
256 substream->dma_max = max;
257 if (max > 0)
258 preallocate_info_init(substream);
259 if (managed)
260 substream->managed_buffer_alloc = 1;
261 return 0;
262}
263
264static int preallocate_pages_for_all(struct snd_pcm *pcm, int type,
265 void *data, size_t size, size_t max,
266 bool managed)
267{
268 struct snd_pcm_substream *substream;
269 int stream, err;
270
271 for_each_pcm_substream(pcm, stream, substream) {
272 err = preallocate_pages(substream, type, data, size, max, managed);
273 if (err < 0)
274 return err;
275 }
276 return 0;
277}
278
279
280
281
282
283
284
285
286
287
288
289void snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
290 int type, struct device *data,
291 size_t size, size_t max)
292{
293 preallocate_pages(substream, type, data, size, max, false);
294}
295EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
296
297
298
299
300
301
302
303
304
305
306
307
308void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
309 int type, void *data,
310 size_t size, size_t max)
311{
312 preallocate_pages_for_all(pcm, type, data, size, max, false);
313}
314EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
346 struct device *data, size_t size, size_t max)
347{
348 return preallocate_pages(substream, type, data, size, max, true);
349}
350EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
351
352
353
354
355
356
357
358
359
360
361
362
363
364int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
365 struct device *data,
366 size_t size, size_t max)
367{
368 return preallocate_pages_for_all(pcm, type, data, size, max, true);
369}
370EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);
371
372
373
374
375
376
377
378
379
380
381
382
383int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
384{
385 struct snd_card *card;
386 struct snd_pcm_runtime *runtime;
387 struct snd_dma_buffer *dmab = NULL;
388
389 if (PCM_RUNTIME_CHECK(substream))
390 return -EINVAL;
391 if (snd_BUG_ON(substream->dma_buffer.dev.type ==
392 SNDRV_DMA_TYPE_UNKNOWN))
393 return -EINVAL;
394 runtime = substream->runtime;
395 card = substream->pcm->card;
396
397 if (runtime->dma_buffer_p) {
398
399
400
401 if (runtime->dma_buffer_p->bytes >= size) {
402 runtime->dma_bytes = size;
403 return 0;
404 }
405 snd_pcm_lib_free_pages(substream);
406 }
407 if (substream->dma_buffer.area != NULL &&
408 substream->dma_buffer.bytes >= size) {
409 dmab = &substream->dma_buffer;
410 } else {
411
412 if (substream->dma_buffer.area && !substream->dma_max)
413 return -ENOMEM;
414 dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
415 if (! dmab)
416 return -ENOMEM;
417 dmab->dev = substream->dma_buffer.dev;
418 if (do_alloc_pages(card,
419 substream->dma_buffer.dev.type,
420 substream->dma_buffer.dev.dev,
421 size, dmab) < 0) {
422 kfree(dmab);
423 pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
424 substream->pcm->card->number, substream->pcm->device,
425 substream->stream ? 'c' : 'p', substream->number,
426 substream->pcm->name, size);
427 return -ENOMEM;
428 }
429 }
430 snd_pcm_set_runtime_buffer(substream, dmab);
431 runtime->dma_bytes = size;
432 return 1;
433}
434EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
435
436
437
438
439
440
441
442
443
444int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
445{
446 struct snd_card *card = substream->pcm->card;
447 struct snd_pcm_runtime *runtime;
448
449 if (PCM_RUNTIME_CHECK(substream))
450 return -EINVAL;
451 runtime = substream->runtime;
452 if (runtime->dma_area == NULL)
453 return 0;
454 if (runtime->dma_buffer_p != &substream->dma_buffer) {
455
456 do_free_pages(card, runtime->dma_buffer_p);
457 kfree(runtime->dma_buffer_p);
458 }
459 snd_pcm_set_runtime_buffer(substream, NULL);
460 return 0;
461}
462EXPORT_SYMBOL(snd_pcm_lib_free_pages);
463
464int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
465 size_t size, gfp_t gfp_flags)
466{
467 struct snd_pcm_runtime *runtime;
468
469 if (PCM_RUNTIME_CHECK(substream))
470 return -EINVAL;
471 runtime = substream->runtime;
472 if (runtime->dma_area) {
473 if (runtime->dma_bytes >= size)
474 return 0;
475 vfree(runtime->dma_area);
476 }
477 runtime->dma_area = __vmalloc(size, gfp_flags);
478 if (!runtime->dma_area)
479 return -ENOMEM;
480 runtime->dma_bytes = size;
481 return 1;
482}
483EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
484
485
486
487
488
489
490
491
492int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
493{
494 struct snd_pcm_runtime *runtime;
495
496 if (PCM_RUNTIME_CHECK(substream))
497 return -EINVAL;
498 runtime = substream->runtime;
499 vfree(runtime->dma_area);
500 runtime->dma_area = NULL;
501 return 0;
502}
503EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
504
505
506
507
508
509
510
511
512
513
514
515struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
516 unsigned long offset)
517{
518 return vmalloc_to_page(substream->runtime->dma_area + offset);
519}
520EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page);
521