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